欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

分離與繼承的思想實(shí)現(xiàn)圖片上傳后的預(yù)覽功能:ImageUploadView

 更新時(shí)間:2016年04月07日 10:29:25   作者:流云諸葛  
本文要介紹的是網(wǎng)頁中常見的圖片上傳后直接在頁面生成小圖預(yù)覽的實(shí)現(xiàn)思路,考慮到該功能有一定的適用性,于是把相關(guān)的邏輯封裝成了一個(gè)ImageUploadView組件,實(shí)際使用效果可查看下一段的git效果圖

本文要介紹的是網(wǎng)頁中常見的圖片上傳后直接在頁面生成小圖預(yù)覽的實(shí)現(xiàn)思路,考慮到該功能有一定的適用性,于是把相關(guān)的邏輯封裝成了一個(gè)ImageUploadView組件,實(shí)際使用效果可查看下一段的git效果圖。在實(shí)現(xiàn)這個(gè)組件的過程中,有用到前面幾篇博客介紹的相關(guān)內(nèi)容,比如繼承庫class.js,任意組件的事件管理庫eventBase.js,同時(shí)包含進(jìn)了自己對(duì)職責(zé)分離,表現(xiàn)與行為分離這兩方面的一些思考,歡迎閱讀與交流。

演示效果:

注:由于演示的代碼都是靜態(tài)的,所以文件上傳的組件是用setTimeout模擬的,不過它的調(diào)用方式跟我自己在實(shí)際工作中用上傳組件完全相同,所以演示效果的代碼實(shí)現(xiàn)完全符合真實(shí)的功能需求。

按照我以前博客的思路,先來介紹下這個(gè)上傳預(yù)覽功能的需求。

1. 需求分析

根據(jù)前面的演示效果圖,分析需求如下:

1)初始時(shí)上傳區(qū)域只顯示一個(gè)可點(diǎn)擊上傳的按鈕,當(dāng)點(diǎn)擊該按鈕后,將上傳成功的圖片顯示在后面的預(yù)覽區(qū)域

2)上傳的圖片添加到預(yù)覽區(qū)域以后,可以通過刪除按鈕來移除

3)當(dāng)已上傳的圖片總數(shù)達(dá)到一定限制之后,比如演示中已上傳的限制為4,就把上傳按鈕給移除掉;

4)當(dāng)已上傳的圖片總數(shù)達(dá)到一定限制之時(shí),如果通過刪除操作移除了某張圖片,還得再把上傳按鈕給顯示出來。

以上需求是看的見的,根據(jù)經(jīng)驗(yàn),還可以分析得出的需求如下:

1)如果頁面是編輯狀態(tài),也就是從數(shù)據(jù)庫中查詢出來的狀態(tài),只要圖片列表不為空,初始時(shí)還得把圖片顯示出來;而且還要根據(jù)查出來的圖片列表的長(zhǎng)度跟上傳限制去控制上傳按鈕是否顯示;

2)如果當(dāng)前頁面是一種只能看不能改的狀態(tài),那么在初始時(shí)一定要把上傳按鈕和刪除按鈕移除掉。

需求分析完畢,接下來說明一下我的實(shí)現(xiàn)思路。

2. 實(shí)現(xiàn)思路

由于這是個(gè)表單頁面,所以圖片上傳完以后如果要提交到后臺(tái),肯定得需要一個(gè)文本域,所以我在做靜態(tài)頁面的時(shí)候就把這個(gè)文本域考慮進(jìn)去了,當(dāng)上傳完新的圖片以及刪除了圖片之后都得去修改這個(gè)文本域的值。當(dāng)時(shí)做靜態(tài)頁時(shí)這部分的結(jié)構(gòu)如下:

<div class="holy-layout-am appForm-group appForm-group-img-upload clearfix">
<label class="holy-layout-al">法人身份證電子版</label>
<div class="holy-layout-m">
<input id="legalPersonIDPic-input" name="legalPersonIDPic" class="form-control form-field"
type="hidden">
<ul id="legalPersonIDPic-view" class="image-upload-view clearfix">
<li class="view-item-add"><a class="view-act-add" href="javascript:;" title="點(diǎn)擊上傳">+</a>
</li>
</ul>
<p class="img-upload-msg">
請(qǐng)確保圖片清晰,文字可辨
<a href="#" title="查看示例"><i class="fa fa-question-circle"></i> 查看示例</a>
</p>
</div>
</div>

從這個(gè)結(jié)構(gòu)還可以看出,我把整個(gè)上傳區(qū)域都放在一個(gè)ul里面,然后把ul的第一個(gè)li作為上傳按鈕來使用。為了完成這個(gè)功能,我們主要的任務(wù)是:上傳及上傳后的回調(diào),新增或刪除圖片預(yù)覽以及文本域值的管理。從這一點(diǎn),結(jié)合職責(zé)分離的思想,這個(gè)功能至少需要三個(gè)組件,一個(gè)負(fù)責(zé)文件上傳,一個(gè)負(fù)責(zé)圖片預(yù)覽的管理,一個(gè)負(fù)責(zé)文本域值的管理。千萬不能把這三個(gè)功能,兩兩或者全部都封裝在一起,那樣的話功能耦合太強(qiáng),寫出來的組件可擴(kuò)展性可重用性不高。如果這三個(gè)組件之間需要交互,我們只要借助回調(diào)函數(shù)或者發(fā)布-訂閱模式定義它們給外部調(diào)用的接口即可。

不過文本域值的管理本身就很簡(jiǎn)單,寫不寫成組件都關(guān)系不大,但是至少函數(shù)級(jí)別的封裝是得有的;文件上傳組件雖然不是本文的重點(diǎn),但是網(wǎng)上有很多現(xiàn)成的開源插件,比如webuploader,不管是直接用還是做二次封裝都可以應(yīng)用進(jìn)來;圖片預(yù)覽的功能是本文的核心內(nèi)容,ImageUploadView這個(gè)組件就是對(duì)它的封裝,從需求來看,這個(gè)組件有語義的實(shí)例方法無非就是三個(gè),分別是render, append, delItem,其中render用來在初始化完成之后顯示初始的預(yù)覽列表,append用來在上傳成功后添加新的圖片預(yù)覽,delItem用來刪除已有的圖片預(yù)覽,按照這個(gè)基本思路,我們只需要再結(jié)合需求和組件開發(fā)的經(jīng)驗(yàn)為它設(shè)計(jì)好options和事件即可。

從前面的需求我們發(fā)現(xiàn),這個(gè)ImageUploadView組件的render會(huì)受到頁面狀態(tài)的影響,當(dāng)頁面為查看模式時(shí),這個(gè)組件不能做上傳和刪除的操作,所以可以考慮給它加一個(gè)readonly的option。同時(shí)它的上傳和刪除操作還會(huì)影響到上傳按鈕的UI邏輯,這個(gè)跟上傳限制有關(guān)系,為了靈活性,也得把上傳限制作為一個(gè)option。從前一段提到的三個(gè)實(shí)例方法來說,按照自己以前定義事件的經(jīng)驗(yàn),一般一個(gè)實(shí)例方法會(huì)定義一對(duì)事件,就像bootstrap的插件的做法一樣,比如render方法,可以定義一個(gè)render.before,這個(gè)事件在render的主要邏輯執(zhí)行前觸發(fā),如果外部監(jiān)聽器調(diào)用了這個(gè)事件的preventDefault()方法,那么render的主要邏輯都不會(huì)執(zhí)行;還有一個(gè)render.after事件,這個(gè)事件在render的主要邏輯執(zhí)行后觸發(fā)。這種成對(duì)定義事件的好處是,既給外部提供擴(kuò)展組件功能的方法,又能增加組件默認(rèn)行為的管理。

最后從我之前的工作經(jīng)驗(yàn)來說,除了有上傳圖片進(jìn)行預(yù)覽這樣的功能,我曾經(jīng)還做過上傳視頻,上傳音頻,上傳普通文檔等類似的,所以這一次碰到這個(gè)功能的時(shí)候我就覺得應(yīng)該把這些功能里面相似的東西抽取出來,作為一個(gè)基類,圖片上傳,視頻上傳等分別繼承這個(gè)基類去實(shí)現(xiàn)各自的邏輯。這個(gè)基類還有一個(gè)好處,就是能夠讓那些通用的邏輯完全與HTML結(jié)構(gòu)分離,在這個(gè)基類里面只做一些通用的事情,比如options與組件行為(render, append, delItem)的定義,以及通用事件的監(jiān)聽和觸發(fā),它只要留有固定的接口留給子類來實(shí)現(xiàn)即可。在后面的實(shí)現(xiàn)中,我定義了一個(gè)FileUploadBaseView組件來完成這個(gè)基類的功能,這個(gè)基類不包含任何html或css處理的邏輯,它只是抽象了我們要完成的功能,不處理任何業(yè)務(wù)邏輯。根據(jù)業(yè)務(wù)邏輯實(shí)現(xiàn)的子類會(huì)受html結(jié)構(gòu)的限制,所以子類的適用范圍小;而基類因?yàn)樽龅搅伺chtml結(jié)構(gòu)完全分離,所以有更大的適用范圍。

3. 實(shí)現(xiàn)細(xì)節(jié)

從第2部分的實(shí)現(xiàn)思路,要實(shí)現(xiàn)的類有:FileUploadBaseView和ImageUploadView,前者是后者的基類。同時(shí)考慮到要給組件提供事件管理的功能,所以要用到上一篇博客的eventBase.js,F(xiàn)ileUploadBaseView得繼承該庫的EventBase組件;考慮到要有類的定義和繼承,還要用到之前寫的繼承庫class.js來定義組件以及組件的繼承關(guān)系。相關(guān)組件的繼承關(guān)系為:ImageUploadView extend FileUploadBaseView extend EventBase。

(注:以下相關(guān)代碼中模塊化用的是seajs。)

FileUploadBaseView所做的事情有:

1)定義通用的option以及通用的事件管理

在該組件的DEFAULTS配置中可以看到所有的通用option和通用事件的定義:

var DEFAULTS = {
data: [], //要展示的數(shù)據(jù)列表,列表元素必須是object類型的,如[{url: 'xxx.png'},{url: 'yyyy.png'}]
sizeLimit: 0, //用來限制BaseView中的展示的元素個(gè)數(shù),為0表示不限制
readonly: false, //用來控制BaseView中的元素是否允許增加和刪除
onBeforeRender: $.noop, //對(duì)應(yīng)render.before事件,在render方法調(diào)用前觸發(fā)
onRender: $.noop, //對(duì)應(yīng)render.after事件,在render方法調(diào)用后觸發(fā)
onBeforeAppend: $.noop, //對(duì)應(yīng)append.before事件,在append方法調(diào)用前觸發(fā)
onAppend: $.noop, //對(duì)應(yīng)append.after事件,在append方法調(diào)用后觸發(fā)
onBeforeDelItem: $.noop, //對(duì)應(yīng)delItem.before事件,在delItem方法調(diào)用前觸發(fā)
onDelItem: $.noop //對(duì)應(yīng)delItem.after事件,在delItem方法調(diào)用后觸發(fā)
};

在該組件的init方法中可以看到對(duì)通用option和事件管理的初始化邏輯:

init: function (element, options) {
//通過this.base調(diào)用父類EventBase的init方法
this.base(element);
//實(shí)例屬性
var opts = this.options = this.getOptions(options);
this.data = resolveData(opts.data);
delete opts.data;
this.sizeLimit = opts.sizeLimit;
this.readOnly = opts.readOnly;
//綁定事件
this.on('render.before', $.proxy(opts.onBeforeRender, this));
this.on('render.after', $.proxy(opts.onRender, this));
this.on('append.before', $.proxy(opts.onBeforeAppend, this));
this.on('append.after', $.proxy(opts.onAppend, this));
this.on('delItem.before', $.proxy(opts.onBeforeDelItem, this));
this.on('delItem.after', $.proxy(opts.onDelItem, this));
},

2)定義組件的行為,預(yù)留可供子類實(shí)現(xiàn)的接口:

render: function () {
/**
* render是一個(gè)模板,子類不需要重寫render方法,只需要重寫_render方法
* 當(dāng)調(diào)用子類的render方法時(shí)調(diào)用的是父類的render方法
* 但是執(zhí)行到_render方法時(shí),調(diào)用的是子類的_render方法
* 這樣就能把before跟after事件的觸發(fā)操作統(tǒng)一起來
*/
var e;
this.trigger(e = $.Event('render.before'));
if (e.isDefaultPrevented()) return;
this._render();
this.trigger($.Event('render.after'));
},
//子類需實(shí)現(xiàn)_Render方法
_render: function () {
},
append: function (item) {
var e;
if (!item) return;
item = resolveDataItem(item);
this.trigger(e = $.Event('append.before'), item);
if (e.isDefaultPrevented()) return;
this.data.push(item);
this._append(item);
this.trigger($.Event('append.after'), item);
},
//子類需實(shí)現(xiàn)_append方法
_append: function (data) {
},
delItem: function (uuid) {
var e, item = this.getDataItem(uuid);
if (!item) return;
this.trigger(e = $.Event('delItem.before'), item);
if (e.isDefaultPrevented()) return;
this.data.splice(this.getDataItemIndex(uuid), 1);
this._delItem(item);
this.trigger($.Event('delItem.after'), item);
},
//子類需實(shí)現(xiàn)_delItem方法
_delItem: function (data) {
}

為了統(tǒng)一處理行為前后的事件派發(fā)邏輯,將render, append ,delItem的主要邏輯抽出來成為需被子類實(shí)現(xiàn)的方法_render, _append和_delItem。當(dāng)調(diào)用子類的render方法時(shí),調(diào)用的實(shí)際上父類的方法,但是當(dāng)父類執(zhí)行到_render方法時(shí),執(zhí)行的就是子類的方法,另外兩個(gè)方法也是類似的處理。需要注意的是子類不能去覆蓋render, append ,delItem三個(gè)方法,否則就得自己去處理相關(guān)事件的觸發(fā)邏輯。

FileUploadBaseView整體實(shí)現(xiàn)如下:

define(function (require, exports, module) {
var $ = require('jquery');
var Class = require('mod/class');
var EventBase = require('mod/eventBase');
var DEFAULTS = {
data: [], //要展示的數(shù)據(jù)列表,列表元素必須是object類型的,如[{url: 'xxx.png'},{url: 'yyyy.png'}]
sizeLimit: 0, //用來限制BaseView中的展示的元素個(gè)數(shù),為0表示不限制
readonly: false, //用來控制BaseView中的元素是否允許增加和刪除
onBeforeRender: $.noop, //對(duì)應(yīng)render.before事件,在render方法調(diào)用前觸發(fā)
onRender: $.noop, //對(duì)應(yīng)render.after事件,在render方法調(diào)用后觸發(fā)
onBeforeAppend: $.noop, //對(duì)應(yīng)append.before事件,在append方法調(diào)用前觸發(fā)
onAppend: $.noop, //對(duì)應(yīng)append.after事件,在append方法調(diào)用后觸發(fā)
onBeforeDelItem: $.noop, //對(duì)應(yīng)delItem.before事件,在delItem方法調(diào)用前觸發(fā)
onDelItem: $.noop //對(duì)應(yīng)delItem.after事件,在delItem方法調(diào)用后觸發(fā)
};
/**
* 數(shù)據(jù)處理,給data的每條記錄都添加一個(gè)_uuid的屬性,方便查找
*/
function resolveData(data) {
var time = new Date().getTime();
return $.map(data, function (d) {
return resolveDataItem(d, time);
});
}
function resolveDataItem(data, time) {
time = time || new Date().getTime();
data._uuid = '_uuid' + time + Math.floor(Math.random() * 100000);
return data;
}
var FileUploadBaseView = Class({
instanceMembers: {
init: function (element, options) {
//通過this.base調(diào)用父類EventBase的init方法
this.base(element);
//實(shí)例屬性
var opts = this.options = this.getOptions(options);
this.data = resolveData(opts.data);
delete opts.data;
this.sizeLimit = opts.sizeLimit;
this.readOnly = opts.readOnly;
//綁定事件
this.on('render.before', $.proxy(opts.onBeforeRender, this));
this.on('render.after', $.proxy(opts.onRender, this));
this.on('append.before', $.proxy(opts.onBeforeAppend, this));
this.on('append.after', $.proxy(opts.onAppend, this));
this.on('delItem.before', $.proxy(opts.onBeforeDelItem, this));
this.on('delItem.after', $.proxy(opts.onDelItem, this));
},
getOptions: function (options) {
return $.extend({}, this.getDefaults(), options);
},
getDefaults: function () {
return DEFAULTS;
},
getDataItem: function (uuid) {
//根據(jù)uuid獲取dateItem
return this.data.filter(function (item) {
return item._uuid === uuid;
})[0];
},
getDataItemIndex: function (uuid) {
var ret;
this.data.forEach(function (item, i) {
item._uuid === uuid && (ret = i);
});
return ret;
},
render: function () {
/**
* render是一個(gè)模板,子類不需要重寫render方法,只需要重寫_render方法
* 當(dāng)調(diào)用子類的render方法時(shí)調(diào)用的是父類的render方法
* 但是執(zhí)行到_render方法時(shí),調(diào)用的是子類的_render方法
* 這樣就能把before跟after事件的觸發(fā)操作統(tǒng)一起來
*/
var e;
this.trigger(e = $.Event('render.before'));
if (e.isDefaultPrevented()) return;
this._render();
this.trigger($.Event('render.after'));
},
//子類需實(shí)現(xiàn)_Render方法
_render: function () {
},
append: function (item) {
var e;
if (!item) return;
item = resolveDataItem(item);
this.trigger(e = $.Event('append.before'), item);
if (e.isDefaultPrevented()) return;
this.data.push(item);
this._append(item);
this.trigger($.Event('append.after'), item);
},
//子類需實(shí)現(xiàn)_append方法
_append: function (data) {
},
delItem: function (uuid) {
var e, item = this.getDataItem(uuid);
if (!item) return;
this.trigger(e = $.Event('delItem.before'), item);
if (e.isDefaultPrevented()) return;
this.data.splice(this.getDataItemIndex(uuid), 1);
this._delItem(item);
this.trigger($.Event('delItem.after'), item);
},
//子類需實(shí)現(xiàn)_delItem方法
_delItem: function (data) {
}
},
extend: EventBase,
staticMembers: {
DEFAULTS: DEFAULTS
}
});
return FileUploadBaseView;
});

ImageUploadView 的實(shí)現(xiàn)就比較簡(jiǎn)單了,跟填空差不多,有幾個(gè)點(diǎn)需要說明一下:

1)這個(gè)類的DEFAULTS需要擴(kuò)展父類的DEFAULTS,以便添加這個(gè)子類的默認(rèn)options,同時(shí)還保留父類默認(rèn)options的定義;根據(jù)靜態(tài)頁面結(jié)構(gòu),新增了一個(gè)onAppendClick事件,外部可在這個(gè)事件中調(diào)用文件上傳組件的相關(guān)方法:

//繼承并擴(kuò)展父類的默認(rèn)DEFAULTS
var DEFAULTS = $.extend({}, FileUploadBaseView.DEFAULTS, {
onAppendClick: $.noop //點(diǎn)擊上傳按鈕時(shí)候的回調(diào)
});

2)在init方法中,需要調(diào)用父類的init方法,才能完成那些通用的邏輯處理;同時(shí)在init的最后還得手動(dòng)調(diào)用一下render方法,以便在組件實(shí)例化之后就能看到效果:

其它實(shí)現(xiàn)純粹是業(yè)務(wù)邏輯實(shí)現(xiàn),跟第2部分的需求密切相關(guān)。

ImageUploadView的整體實(shí)現(xiàn)如下:

define(function (require, exports, module) {
var $ = require('jquery');
var Class = require('mod/class');
var FileUploadBaseView = require('mod/fileUploadBaseView');
//繼承并擴(kuò)展父類的默認(rèn)DEFAULTS
var DEFAULTS = $.extend({}, FileUploadBaseView.DEFAULTS, {
onAppendClick: $.noop //點(diǎn)擊上傳按鈕時(shí)候的回調(diào)
});
var ImageUploadView = Class({
instanceMembers: {
init: function (element, options) {
var $element = this.$element = $(element);
var opts = this.getOptions(options);
//調(diào)用父類的init方法完成options獲取,data解析以及通用事件的監(jiān)聽處理
this.base(this.$element, options);
//添加上傳和刪除的監(jiān)聽器及觸發(fā)處理
if (!this.readOnly) {
var that = this;
that.on('appendClick', $.proxy(opts.onAppendClick, this));
$element.on('click.append', '.view-act-add', function (e) {
e.preventDefault();
that.trigger('appendClick');
});
$element.on('click.remove', '.view-act-del', function (e) {
var $this = $(e.currentTarget);
that.delItem($this.data('uuid'));
e.preventDefault();
});
}
this.render();
},
getDefaults: function () {
return DEFAULTS;
},
_setItemAddHtml: function () {
this.$element.prepend($('<li class="view-item-add"><a class="view-act-add" href="javascript:;" title="點(diǎn)擊上傳">+</a></li>'));
},
_clearItemAddHtml: function ($itemAddLi) {
$itemAddLi.remove();
},
_render: function () {
var html = [], that = this;
//如果不是只讀的狀態(tài),并且還沒有達(dá)到上傳限制的話,就添加上傳按鈕
if (!(this.readOnly || (this.sizeLimit && this.sizeLimit <= this.data.length))) {
this._setItemAddHtml();
}
this.data.forEach(function (item) {
html.push(that._getItemRenderHtml(item))
});
this.$element.append($(html.join('')));
},
_getItemRenderHtml: function (item) {
return [
'<li id="',
item._uuid,
'"><a class="view-act-preview" href="javascript:;"><img alt="" src="',
item.url,
'">',
this.readOnly ? '' : '<span class="view-act-del" data-uuid="',
item._uuid,
'">刪除</span>',
'</a></li>'
].join('');
},
_dealWithSizeLimit: function () {
if (this.sizeLimit) {
var $itemAddLi = this.$element.find('li.view-item-add');
//如果已經(jīng)達(dá)到上傳限制的話,就移除上傳按鈕
if (this.sizeLimit && this.sizeLimit <= this.data.length && $itemAddLi.length) {
this._clearItemAddHtml($itemAddLi);
} else if (!$itemAddLi.length) {
this._setItemAddHtml();
}
}
},
_append: function (data) {
this.$element.append($(this._getItemRenderHtml(data)));
this._dealWithSizeLimit();
},
_delItem: function (data) {
$('#' + data._uuid).remove();
this._dealWithSizeLimit();
}
},
extend: FileUploadBaseView
});
return ImageUploadView;
});

4. 演示說明

演示的項(xiàng)目結(jié)構(gòu)為:

框起來的就是演示的核心代碼。其中fileUploadBaserView.js和imageUploadView.js是前面實(shí)現(xiàn)的兩個(gè)核心組件。fileUploader.js是用來模擬上傳組件的,它的實(shí)例有一個(gè)onSuccess的回調(diào),表示上傳成功;還有一個(gè)openChooseFileWin用來模擬真實(shí)的打開選擇文件窗口并上傳的這個(gè)過程:

define(function(require, exports, module) {
return function() {
var imgList = ['../img/1.jpg','../img/2.jpg','../img/3.jpg','../img/4.jpg'], i = 0;
var that = this;
that.onSuccess = function(uploadValue){}
this.openChooseFileWin = function(){
setTimeout(function(){
that.onSuccess(imgList[i++]);
if(i == imgList.length) {
i = 0;
}
},1000);
}
}
});

app/regist.js是演示頁面的邏輯代碼,關(guān)鍵的部分已用注釋進(jìn)行說明:

define(function (require, exports, module) {
var $ = require('jquery');
var ImageUploadView = require('mod/imageUploadView');
var FileUploader = require('mod/fileUploader');//這是用異步任務(wù)模擬的文件上傳組件
//$legalPersonIDPic,用來存儲(chǔ)已上傳的文件信息,上傳組件上傳成功之后以及ImageUploadView組件刪除某個(gè)item之后會(huì)對(duì)$legalPersonIDPic的值產(chǎn)生影響
var $legalPersonIDPic = $('#legalPersonIDPic-input'),
data = JSON.parse($legalPersonIDPic.val() || '[]');//data是初始值,比如當(dāng)前頁面有可能是從數(shù)據(jù)庫加載的,需要用ImageUploadView組件呈現(xiàn)出來
//在文件上傳成功之后,將剛上傳的文件保存到$legalPersonIDPic的value中
//$legalPersonIDPic以json字符串的形式存儲(chǔ)
var appendImageInputValue = function ($input, item) {
var value = JSON.parse($input.val() || '[]');
value.push(item);
$input.val(JSON.stringify(value));
};
//當(dāng)調(diào)用ImageUploadView組件刪除某個(gè)item之后,要同步把$legalPersonIDPic中已存儲(chǔ)的信息清掉
var removeImageInputValue = function ($input, uuid) {
var value = JSON.parse($input.val() || '[]'), index;
value.forEach(function (item, i) {
if (item._uuid === uuid) {
index = i;
}
});
value.splice(index, 1);
$input.val(JSON.stringify(value));
};
var fileUploader = new FileUploader();
fileUploader.onSuccess = function (uploadValue) {
var item = {url: uploadValue};
legalPersonIDPicView.append(item);
appendImageInputValue($legalPersonIDPic, item);
};
var legalPersonIDPicView = new ImageUploadView('#legalPersonIDPic-view', {
data: data,
sizeLimit: 4,
onAppendClick: function () {
//打開選擇文件的窗口
fileUploader.openChooseFileWin();
},
onDelItem: function (data) {
removeImageInputValue($legalPersonIDPic, data._uuid);
}
});
});

5. 本文總結(jié)

ImageUploadView這個(gè)組件最終實(shí)現(xiàn)起來并不難,但是我也花了不少時(shí)間去琢磨它及其它父類的實(shí)現(xiàn)方法,大部分時(shí)間都花在對(duì)職責(zé)分離和行為分離的抽象過程中。我在本文表達(dá)的關(guān)于這兩方面編程思想的觀點(diǎn)也只是自己個(gè)人的實(shí)際體會(huì),因?yàn)槌橄髮用娴臇|西,每個(gè)人的思考方式不同最終理解的成果也就不會(huì)相同,所以我也不能直接說我的對(duì)還是不對(duì),寫出來的目的就是為了分享和交流,看看有沒有其他有經(jīng)驗(yàn)的朋友也愿意把自己在這方面的想法拿出來跟大家說一說,相信每個(gè)人看多了別人的思路之后,也會(huì)對(duì)自己的編程思想方面的鍛煉帶來幫助。

相關(guān)文章

最新評(píng)論