vue pc端網站專案開發坑點與難度記錄

vbyzc發表於2018-11-30

背景

在一pc端的web專案裡,由於某些特性需要由動態語言處理,所以只在有需要使用vue來處理資料的頁面,直接引入vue.js來處理。
由於剛開始並沒有打算使用前端來渲染資料和處理互動,所以使用了一些非vue的ui和外掛,導致後來衝突坑點不少。
非vue模組化下使用vue,雖然不能import vue檔案,使用元件方式也有點噁心,但處理一些事情還是不錯的。


使用formdata提交表單資料

先上程式碼

        var that           = this;
        var myForm         = document.getElementById("form_add");
        var submitFormData = new FormData(myForm);
        submitFormData.append('action', this.action);//新增自定義的引數,這裡是動作,新增或者修改
        layer.load(0,{time:500});
        $.ajax({
            url         : apiAddressAdd,
            type        : 'POST',
            dataType    : 'json',
            cache       : false,
            processData : false,
            contentType : false,
            data        : submitFormData
        })複製程式碼

有2個引數是必須設定processData 和 contentType

這裡要說的是contentType,經實踐,不管是否有包括file上傳檔案或圖片,則必須設定為false, 設定為true或不設定,後臺都不能獲取


jquery賦值不響應input使用v-model繫結的值

在做某個修改資料功能的時候,由於表單的所有資料,使用v-model繫結的, 包括地址。

地址使用了一個jquery地址選擇器, 當選擇器選擇好地址的時候,只是賦值給input,並沒有觸發v-model繫結的資料

檢視了一篇文章,賦值之後,需要觸發input的原生input事件,才會響應v-model:方式如下

$("#city-picker")[0].dispatchEvent(new Event('input'))複製程式碼


商品篩選之引數組選擇元件

這是很常見的一個功能,本處只是記錄一下思路過程,以防日後老年痴呆,請看下圖

如圖中,有4個引數組,每個引數組只能選定一個引數,選中的引數在下面以標籤,點選X可以去掉相應已選擇的標籤

但由於引數組是從後臺輸出的介面得到的,也就是說,不同的種類的商品,有不同的引數組,有的可能只有1組引數,也有可能有4組

本篇實現此處功能的前提,資料庫表應該設計為:

引數組為單獨一張表,如上面的是選擇了茶具種類,有:分類、材質 、風格、擺放空間,四種引數組(不同的商品種類可能會有相同的引數組,但統一新增到此表中,即唯一id值不會重複)
引數組的引數項為單獨一張表,關聯引數組表,和上面情況一樣,有可能和別的商品種類的一樣的引數組中有相同的引數項(名字就算相同,但是同表中唯一id值不會重複)

這2點也是實現本篩選功能的基礎。

以下為程式碼的實現思路:

先看json資料結構

如圖所示,和上面的篩選元件截圖對應,4個引數組,每個引數組不同的id,所有引數項的id也不同,即便name相同也沒有關係。

請求到引數組的時候,做如下處理

res.data.paramGroup.forEach(function(item){
   vm.$set(vm_data.param_group_active,'active_'+item.gid,0);
})

//更新資料
that.dataParamsGroup = res.data.paramGroup;複製程式碼

把引數組所有資料原始格式放到一個叫param_group_active中

這個物件,用來標識當前哪組引數選中的哪項引數項,0,當然就是預設沒有選中

然後並遍歷引數組,以引數組的唯一id為標識,建立一個響應式的物件,值為0 (注意,這裡說的是引數組,非引數組下面的引數項)

得到如下物件

然後看引數組dom結構 :

裡面的A標籤,就是引數的詳細項,啟用的狀態,就是常見的tab的那個做法

選中當前標籤,當然是以class來表示了,上面繫結的class,取決於引數項自己的id,對應 param_group_active組中,啟用的值

點選引數項的時候:

引數帶入:引數組和id,當前點選的引數項的id,並且vue的set方法來設定響應資料

比如當我選擇風格中的花鳥之後,風格的唯一id是14,而花鳥是12

很明瞭了,可以理解成動態tab。。。

接下來,選中的引數,都要顯示在下排,並可以取消。結構如下:

根據我們的啟用引數項的資料param_group_active迴圈出來,大於0,當然是有了選擇,

然後你會看到paramsFlattening[item]這個東西,很明顯這是一個object,item一看就知道是當前選中的引數項的id值,

這裡是要顯示所選中的引數項的名稱,所以,這個paramsFlattening裡面肯定放了引數項的資料

但ahax取回來的資料是一個二維object,暫且這麼叫,我們想一個辦法,我們在這例子中暫時叫引數扁平化

看程式碼:

也就是把所有引數項,放到一個新的object中 (注意,我們這裡的paramsFlattening是一個計算屬性)

以引數項的id為鍵名,中文名稱為值,遍歷放進去,得到了這麼個物件:

所以我們在dom結構中直接以插值方式呼叫:{{paramsFlattening[item]}} ,便可以顯示所選中的標籤的對應中文名稱。

接下來是取消選中的標籤

從上面的截圖中可以看到點選了i 標籤(是一個x圖示)呼叫了deleteParam,並帶進了引數item, 是引數項的id

來看這個方法:

遍歷存放啟用狀態的物件,這裡的key,就是這串:

看哪個物件(每個引數組)的id(記得這裡存的是啟用的引數項的id)值 和帶進來的id值一致,就設為0,

這樣,選中的標籤那個地方,是依賴這裡值大於0才顯示的,設為0就不顯示了

最後你可能會問,選中是選中了,但怎麼提交這些引數資料

在本例中,老衲把這些選中的引數項id值,堆成一塊,用,號分隔,開來,當然後臺查詢的時候還要處理這個資料


封裝一個不完美的圖片上傳類

我們暫且稱它為類,雖然不是用es6 class...此處只當充數字量記錄一下,沒什麼難度
使用場景:多個地方需要上傳圖片,於是搞了這麼個東西,有可能直接點file元,也有可能點選的是別的觸發元素,比如換頭像的時候。

依賴jquery和layer訊息,使用formdata資料來當ajax傳送的資料,好像有file元素,就要設定這2項:

contentType : false,
processData : false
複製程式碼

由於專案中api介面直接統一寫進配置檔案,則這裡不做成引數帶進方式

/**
 * [圖片上傳類,統一上傳地址]
 * @param {[type]}   params [description]
 * @param {Function} cb     [description]
 */
function ClassUploadImage(params,cb){
    this.__proxyEl      = params.proxyEl;
    this.__imgFileInput = params.imgFileInput;
    this.__module       = params.module;
    this.__cb           = cb ;
}
//初始化過程
ClassUploadImage.prototype.init = function(){
    var that = this

    //先判斷是否有layer和jquery
    if(!window.$ || !window.jQuery){alert('沒有jquery!'); return false;}
    if(typeof layer == 'undefined'){alert('沒有引入layer!'); return false;}

    //繫結代理解發file事件的元素
    $(that.__proxyEl).on("click",this,function(){
        $(that.__imgFileInput).trigger('click');
    })

    //繫結檔案表單的選擇事件,當選擇了檔案,立即執行上傳
    $(that.__imgFileInput).change(function(){
        var files   = $(this)[0].files[0];
        var formObj = new FormData();
        formObj.append('image', files);
        formObj.append('module', that.__module);
        that.upload(formObj);
    });
}
//上傳過程
ClassUploadImage.prototype.upload = function(formObj){
    var that = this;
    console.log('執行上傳!');
    layer.load(0, {shade: false,time:300});
    $.ajax({
        url         : apiImageUpload,
        type        : 'post',
        dataType    : 'json',
        data        : formObj,
        cache       : false,
        contentType : false,
        processData : false
    })
    .done(function(res) {
        //此處未對返回的報文進行狀態碼判斷
        $.lightTip.success(res.msg);
        that.__cb(res);
    })
    .fail(function(e) {
        console.log('不知發生了什麼錯誤...');
    })
}複製程式碼

使用:

   //上傳圖片初始化
    var myUploadImg = new ClassUploadImage({
        proxyEl:'#proxyuploadbutton,#proxyuploadimg',
        imgFileInput:'#image',
        module:'headimg'
    },function(res){
        $(".header_original_img").val(res.img);
        $("#proxyuploadimg").attr('src',res.imgurl)
    });
    myUploadImg.init();複製程式碼
引數__proxyEl為代理input的點選事件元素,如果忽略此引數,就只能直接點選file元素

複製程式碼


data 裡的Object變數中的Array型別屬性值坑人記錄

場景: 產品詳情頁資料返回的物件中,其中有一個是陣列型別,是產品的相簿

{
    "code": 0,
    "msg": "資料正常!",
    "data": {
        "id": 1,
        "img": "http://dummyimage.com/360x360",
        "name": "唐五代耀州窯剔刻蓮瓣水注",
        "artist": "藝術家名字",
        "authorId": 93,
        "price": "250000",
        "dsc": "鐮田先生的天目已經燒造幾十年,作品風格古樸自然 ,口部自然露胎,和傳統油滴建盞有很多相似之處。微距下,斑紋底部透明有反射膜 ,膜上斑紋大而立體,表面微有有觸感。胎體輕盈,色為棕,表面略泛光,喝茶之佳物。",
        "view": 779,
        "pcid": 2,
        "album": [
            "http://lorempixel.com/600/600/technics/",
            "http://lorempixel.com/600/600/technics/",
            "http://lorempixel.com/600/600/technics/"
        ],
        "birth": "1986-11-16",
        "birthplace": "安徽省 宿州市 埇橋區",
        "birthtype": 2,
        "awidth": "30",
        "aheight": "80",
        "liked": 57,
        "detail": "事拉我道象特據片四信廠華。種海點支育容量作積鬥眾運進。南界眼參派傳我真音例活術者所。持人較方觀切度題始可做習列。主萬適等自件教相全門話取用。低金色其命麼放從特長拉線經便。",
        "selled": 0,
        "favorite": 1
    }
}複製程式碼

如程式碼中的album,

如果在檢視中直接使用:<img :src="dataProduct.album[0]"/>

可以正常顯示圖片,但是會報錯,並且頁面中其它地方某些純粹的html結構出不來:

如果使用計算屬性:

<div>{{albumFirstImg}}</div>

一樣會報上面那個錯誤

開發工具中檢視,確實是陣列沒錯:

總結應該因為Vue資料包裝的問題,沒有學習研究過vue原始碼,不知怎麼回事,先放一邊
解決辦法:直接把返回資料中的album再賦值到data根物件下的album即可正常使用



文章結束

要不,加老衲微信做個朋友?


相關文章