記一次開發過程當中,iview遇到的一些坑以及解決辦法

寫在開頭:本次項目採用的是vue2.0+iview3.0,最近公司沒啥事,來總結一下開發過程當中遇到的問題。前端

 

一、Modal關閉問題vue

需求背景:modal框裏面是個form表單,點擊肯定以後,先驗證form表單,驗證經過則關閉modal框,驗證不成功則提示用戶,不關閉。ajax

問題描述:原本剛開始想經過modal框v-model綁定的值(true或false)來進行控制,手動改以後,報錯。後端

解決辦法:api

       官方iview的modal組件的api裏面有個loading屬性,可經過控制loading的值來進行控制modal的顯示。數組

      

       舉例說明:app

      

     

     注意: refuseLoading剛開始必定要設置爲true。less

    

   這樣的話就能夠解決問題了。iview

   衍生出來的問題:當關閉模態框以後,再次打開時,表單數據沒有重置,仍是上一次的數據。ide

   解決辦法:this.$refs[name].resetFields();    重置表單數據,在關閉模態框的時候調用這個方法可解決。

 

二、同時驗證多個表單問題

需求背景:一個頁面有多個表單,提交的時候須要驗證多個表單,都驗證成功才能進行下一步操做

解決辦法:用一個數組來存放每一個表單的驗證結果(true驗證經過,false驗證不經過),最後循環這個數組若是值都爲true,說明驗證經過。

               舉例說明:頁面有3個表單,須要同時驗證,主要代碼以下:

<template>
    <div class="hello">
        <Form ref="formValidate1" :model="formValidate1" :rules="ruleValidate">
            <FormItem label="Name" prop="name">
                <Input v-model="formValidate1.name" placeholder="Enter your name"></Input>
            </FormItem>
        </Form>
        <Form ref="formValidate2" :model="formValidate2" :rules="ruleValidate">
            <FormItem label="Name" prop="name">
                <Input v-model="formValidate2.name" placeholder="Enter your name"></Input>
            </FormItem>
        </Form>
        <Form ref="formValidate3" :model="formValidate3" :rules="ruleValidate">
            <FormItem label="Name" prop="name">
                <Input v-model="formValidate3.name" placeholder="Enter your name"></Input>
            </FormItem>
        </Form>
        <Button @click="submit">提交</Button>
    </div>
</template>

<script>
    export default {
        name: 'HelloWorld',
        data() {
            return {
                formValidate1: {
                    name: ''
                },
                formValidate2: {
                    name: ''
                },
                formValidate3: {
                    name: ''
                },
                ruleValidate: {
                    name: [
                        { required: true, message: 'The name cannot be empty', trigger: 'blur' }
                    ]
                },
                arr: []
            }
        },
        methods: {
            check(name){  // 驗證表單是否經過
                this.$refs[name].validate((valid) => {
                    if(valid) {
                        this.arr.push(true);  // arr 這個數組是用來存放單個表單的驗證狀態
                    } else {
                        this.arr.push(false);
                    }
                })
            },
            submit(){  // 提交
                this.arr = [];  // 重置數組
                // 同時驗證多個表單
                this.check('formValidate1');
                this.check('formValidate2');
                this.check('formValidate3');
                var flag = null;
                for(var i = 0; i < this.arr.length; i++) {
                    if(this.arr[i]) { // 單個表單驗證經過,繼續驗證下個表單
                        flag = true;
                        continue;
                    } else { // 單個表單驗證不經過,結束
                        flag = false;
                        break;
                    }
                }
                if(flag){  // 驗證表單成功
                    alert("驗證成功");
                }else{
                    alert("驗證失敗")
                }
            }
        }
    }
</script>

<style scoped></style>

 

三、Select 內的 Option 動態改變時,有時選中值未更新的問題

       需求背景:Select的下拉數組是由後臺返回的,選中的值也是後臺返回的。正確賦值以後,select選中的值未更新。

       解決辦法:剛開始一直在不停的調試,有時候可能正確顯示,有時候又不行。這個隨機事件真的。。。。最後查閱官方文檔,好吧,這是官方的坑,更新到iview最新版本後,問題得以解決。

                         這也給我之後很好的警示,有時候一些異常狀況,能夠先看哈官方的更新日誌,由於咱們剛開始作項目的時候,版本只是當時的最新版,一些問題可能官方後面已經修復了,因此應及時更新版本。

                        

 

 4、Table相關問題

       (1)render函數的運用

                          

                 參數解讀:

                  h:  vue  Render函數的別名(全名 createElement)即 Render函數

                  params: table 該行內容的對象

                  props:設置建立的標籤對象的屬性

                  style:設置建立的標籤對象的樣式

                  on:爲建立的標籤綁定事件

                  scopedSlots:顯示做用域插槽

 

                   a、Switch 開關

                    {
                        title: "可控開關",
                        key: "isOpen",
                        align: "center",
                        width: 100,
                        render:(h, params) => {
                            return h('i-switch', {
                                props: {
                                    value: params.row.isOpen ? params.row.isOpen : false,  // 指定當前是否選中  Boolean類型  (isOpen後端返回字段,根據本身接口返回數據,自行修改)
                                },
                                scopedSlots:{
                                    open: () => h('span', 'on'),  // 自定義顯示打開時的內容
                                    close: () => h('span', 'off')  // 自定義顯示關閉時的內容
                                },
                                on: {
                                    /*
                                     * 觸發事件是on-change
                                     * 參數value是回調值  Boolean類型                                    
                                    */ 
                                    'on-change': (value) => { 
                                        this.data[params.index].isOpen = value;  // 賦值  data:表格數據
                                    }
                                }
                            })
                        }
                    }

       

              b、Button按鈕

                    {
                        title: '操做',
                        key: 'action',
                        width: 150,
                        align: 'center',
                        render: (h, params) => {  // 按鈕操做
                            return h('div', [
                                h('Button', {
                                    props: {
                                        type: 'primary',
                                        size: 'small'
                                    },
                                    style: {  // 自定義樣式
                                        marginRight: '5px'
                                    },
                                    on: {  // 自定義事件
                                        click: () => {
                                            this.show(params.index)  // params.index是拿到table的行序列,能夠取到對應的表格值
                                        }
                                    }
                                }, '查看'),
                                h('Button', {
                                    props: {
                                        type: 'error',
                                        size: 'small'
                                    },
                                    on: {
                                        click: () => {
                                            this.remove(params.index)
                                        }
                                    }
                                }, '刪除')
                            ]);
                        }
                    }

 

                 c、Input 輸入框

                    {
                        title: "input輸入框",
                        key: "inputText",
                        align: "center",
                        render:(h, params) => {
                            return h('Input', {
                                props: {
                                    value: params.row.inputText ? params.row.inputText : '',
                                    size: 'small'
                                },
                                on: {
                                    'on-blur': (event) => {  // 輸入框失去焦點時觸發
                                        this.data[params.index].inputText = event.target.value;  // 賦值   data:表格數據
                                    }
                                }
                            });
                        }
                    }

              

                       d、Select 下拉框

                    {
                        title: 'select下拉框',
                        key: 'selectText',
                        align: 'center',
                        render: (h, params) => {
                            return h('Select',{
                                    props:{
                                        value: params.row.selectText ? params.row.selectText : '',
                                        size: 'small'
                                    },
                                    on: {
                                        'on-change':(value) => {  //  下拉框選定的值
                                            this.data[params.index].selectText = value;
                                        }
                                    }
                                },
                                /**
                                 * this.selectAction   下拉框Option數組
                                 * selectAction:[
                                        {
                                            value: '01',
                                            name:'select_1'
                                        },
                                        {
                                            value: '02',
                                            name:'select_2'
                                        }
                                    ]
                                 */
                                this.selectAction.map((item) =>{  // 下拉選項
                                    return h('Option', {
                                        props: {
                                            value: item.value,
                                            label: item.name
                                        }
                                    })
                                })
                            )
                        }
                    }

            

                    e、Rate評分

                    {
                        title: "評分",
                        key: "rate",
                        align: "center",
                        render:(h, params) => {
                            return h('Rate', {
                                props: {
                                    value: Number(params.row.rate),  // 當前 star 數   Number類型
                                    'allow-half': true,  // 能夠選中半星
                                    disabled: false  // 是否只讀
                                },
                                on: {
                                    'on-change': (value) => {   // 評分改變時觸發
                                        this.data[params.index].rate = value;  // 賦值  data:表格數據
                                    }
                                }
                            })
                        }
                    }

 

                   f、Img圖片

                  {
                        title: "頭像",
                        key: "avatar",
                        align: "center",
                        width: 100,
                        render:(h, params) => {
                            return h('Avatar', {  // 也可用原生img標籤代替
                                style: {  
                                    width: '30px',
                                    height: '30px',
                                    'border-radius': '50%'
                                },
                                attrs: {
                                    src: 'https://i.loli.net/2017/08/21/599a521472424.jpg'
                                }
                            })
                        }
                    }

 

                  g、DatePicker時間選擇器

                    {
                        title: "時間選擇器",
                        key: "date",
                        align: "center",
                        render:(h, params) => {
                            return h('DatePicker', {
                                props: {
                                    value: params.row.date,
                                    size: 'small',
                                    type: 'datetime'
                                },
                                on: {
                                    'on-change': (value) => {  // 輸入框失去焦點時觸發
                                        this.data[params.index].date = value;  // 賦值   data:表格數據
                                    }
                                }
                            });
                        }
                    }

 

                     h、對數據進行處理

                            好比,後端返回時間是時間戳格式,展現給用戶看的確定不能是時間戳,這時候就須要咱們對數據進行處理              

                   {
                        title: "申請年份",
                        align: "center",
                        key: "applyDate",
                        render: (h, params) => {
                            return h('span', {
                                    
                            }, new Date(params.row.applyDate).getFullYear())  // 對後端返回的時間戳進行處理,返回頁面須要展現的格式
                        }
                    }

 

                        差很少就總結了這幾個,寫多了就發現,是同樣的模板,直接套到render函數裏面就是了。想要更多的學習render函數相關的,能夠本身前往官網學習。

                        完整代碼:

<template>
    <div class="hello">
        <Table border :columns="columns" :data="data"></Table>
    </div>
</template>

<script>
    export default {
        name: 'HelloWorld',
        data() {
            return {
                columns: [  // 表格列的配置描述
                    {
                        title: "頭像",
                        key: "avatar",
                        align: "center",
                        width: 100,
                        render:(h, params) => {
                            return h('Avatar', {  // 也可用原生img標籤代替
                                style: {  
                                    width: '30px',
                                    height: '30px',
                                    'border-radius': '50%'
                                },
                                attrs: {
                                    src: 'https://i.loli.net/2017/08/21/599a521472424.jpg'
                                }
                            })
                        }
                    },
                    {
                        title: "時間選擇器",
                        key: "date",
                        align: "center",
                        render:(h, params) => {
                            return h('DatePicker', {
                                props: {
                                    value: params.row.date,
                                    size: 'small',
                                    type: 'datetime'
                                },
                                on: {
                                    'on-change': (value) => {  // 輸入框失去焦點時觸發
                                        this.data[params.index].date = value;  // 賦值   data:表格數據
                                    }
                                }
                            });
                        }
                    },
                    {
                        title: "input輸入框",
                        key: "inputText",
                        align: "center",
                        render:(h, params) => {
                            return h('Input', {
                                props: {
                                    value: params.row.inputText ? params.row.inputText : '',
                                    size: 'small'
                                },
                                on: {
                                    'on-blur': (event) => {  // 輸入框失去焦點時觸發
                                        this.data[params.index].inputText = event.target.value;  // 賦值   data:表格數據
                                    }
                                }
                            });
                        }
                    },
                    {
                        title: 'select下拉框',
                        key: 'selectText',
                        align: 'center',
                        render: (h, params) => {
                            return h('Select',{
                                    props:{
                                        value: params.row.selectText ? params.row.selectText : '',
                                        size: 'small'
                                    },
                                    on: {
                                        'on-change':(value) => {  //  下拉框選定的值
                                            this.data[params.index].selectText = value;
                                        }
                                    }
                                },
                                /**
                                 * this.selectAction   下拉框Option數組
                                 * selectAction:[
                                        {
                                            value: '01',
                                            name:'select_1'
                                        },
                                        {
                                            value: '02',
                                            name:'select_2'
                                        }
                                    ]
                                 */
                                this.selectAction.map((item) =>{  // 下拉選項
                                    return h('Option', {
                                        props: {
                                            value: item.value,
                                            label: item.name
                                        }
                                    })
                                })
                            )
                        }
                    },
                    {
                        title: "申請年份",
                        align: "center",
                        key: "applyDate",
                        render: (h, params) => {
                            return h('span', {
                                    
                            }, new Date(params.row.applyDate).getFullYear())  // 對後端返回的時間戳進行處理,返回頁面須要展現的格式
                        }
                    },
                    {
                        title: "可控開關",
                        key: "isOpen",
                        align: "center",
                        width: 100,
                        render:(h, params) => {
                            return h('i-switch', {
                                props: {
                                    value: params.row.isOpen ? params.row.isOpen : false,  // 指定當前是否選中  Boolean類型  (isOpen後端返回字段,根據本身接口返回數據,自行修改)
                                },
                                scopedSlots:{
                                    open: () => h('span', 'on'),  // 自定義顯示打開時的內容
                                    close: () => h('span', 'off')  // 自定義顯示關閉時的內容
                                },
                                on: {
                                    /*
                                     * 觸發事件是on-change
                                     * 參數value是回調值  Boolean類型                                    
                                    */ 
                                    'on-change': (value) => { 
                                        this.data[params.index].isOpen = value;  // 賦值  data:表格數據
                                    }
                                }
                            })
                        }
                    },
                    {
                        title: "評分",
                        key: "rate",
                        align: "center",
                        render:(h, params) => {
                            return h('Rate', {
                                props: {
                                    value: Number(params.row.rate),  // 當前 star 數   Number類型
                                    'allow-half': true,  // 能夠選中半星
                                    disabled: false  // 是否只讀
                                },
                                on: {
                                    'on-change': (value) => {   // 評分改變時觸發
                                        this.data[params.index].rate = value;  // 賦值  data:表格數據
                                    }
                                }
                            })
                        }
                    },
                    {
                        title: '操做',
                        key: 'action',
                        width: 150,
                        align: 'center',
                        render: (h, params) => {  // 按鈕操做
                            return h('div', [
                                h('Button', {
                                    props: {
                                        type: 'primary',
                                        size: 'small'
                                    },
                                    style: {  // 自定義樣式
                                        marginRight: '5px'
                                    },
                                    on: {  // 自定義事件
                                        click: () => {
                                            this.show(params.index)  // params.index是拿到table的行序列,能夠取到對應的表格值
                                        }
                                    }
                                }, '查看'),
                                h('Button', {
                                    props: {
                                        type: 'error',
                                        size: 'small'
                                    },
                                    on: {
                                        click: () => {
                                            this.remove(params.index)
                                        }
                                    }
                                }, '刪除')
                            ]);
                        }
                    }
                ],
                data: [  // 表格數據
                    {
                        inputText: '18',
                        isOpen: false,
                        selectText : '02',
                        rate: 4,
                        date: '2019-02-03 00:08:45',
                        applyDate: 1551835636920
                    },
                    {
                        inputText: '',
                        isOpen: true,
                        selectText : '01',
                        rate: 1.5,
                        date: '',
                        applyDate: 1506124800000
                    }
                ],
                selectAction:[
                    {
                        value: '01',
                        name:'select_1'
                    },
                    {
                        value: '02',
                        name:'select_2'
                    }
                ]
                
            }
        },
        methods: {
            show (index) {  // 查看
                this.$Modal.info({
                    title: '查看',
                    content: '查看詳情'
                })
            },
            remove (index) {  // 刪除
                this.data.splice(index, 1);
            }
        }
    }
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
    .hello{
        width: 90%;
        margin: 0 auto;
        padding: 20px 50px 0;
    }
</style>
View Code

                        

          (2)selection的多選來作單選:

                     經過給 columns 數據設置一項,指定 type: 'selection',便可自動開啓多選功能,可是有些產品以爲iview的單選效果很差,非要用selection的來作單選。如下是解決方案:

 

                     {
                        title: '選擇',
                        align:'center',
                        key: 'checkBox',
                        width: 80,
                        render:(h,params)=>{
                            return h('div',[
                                h('Checkbox',{
                                    props:{
                                        value: params.row.checkBox
                                    },
                                    on:{
                                        'on-change':(e)=>{
                                            this.data.forEach((item)=>{ // 先取消全部對象的勾選,checkBox設置爲false
                                                this.$set(item, 'checkBox', false);
                                            });
                                            this.data[params.index].checkBox = e;  // 再將勾選的對象的checkBox設置爲true
                                        }
                                    }
                                })
                            ])
                        }
                    }

     

             (3)結合Page分頁組件一塊兒使用

                   通常來說,在表格數據比較多的狀況下,會對錶格進行分頁展現

<Table border :columns="columns" :data="data"></Table>
<Page style="float: right;margin-top:20px" :total="page.total" :current="page.current" :page-size="page.size" @on-change="changePage"  @on-page-size-change="changePageSize" show-total show-elevator show-sizer />

               

                 分頁通常有2種:前端分頁、後端分頁。前端分頁就是前端一次性拿到全部數據,再對拿到的數據進行分頁展現。後端分頁就是前端一次只拿一頁的數據展現,分頁的時候再次請求後端。

        mounted(){
            this.changeTableData();
        },
        methods: {
            changePage(current){  // 頁碼改變的回調,返回改變後的頁碼
                this.page.current = current;
                this.changeTableData();
            },
            changePageSize(size){  // 切換每頁條數時的回調,返回切換後的每頁條數
                this.page.current = 1;
                this.page.size = size;
                this.changeTableData();
            },
            changeTableData(){
                /**
                 * page定義
                 * page: {
                        total: 0, 總數
                        current: 1, // 當前頁碼
                        size: 10  // 每頁個數
                    }
                 *
                 *
                 * data: 表格展現數據
                 * tableData: 後端返回的全部數據
                 *  
                 */

                // 前端分頁
                let _start, _end;
                let page = this.page;
                _start = (page.current - 1) * page.size;
                _end = page.current * page.size;
                this.data = this.tableData.slice(_start, _end);
                page.total = this.tableData.length;

                // 後端分頁
                // ajax請求後端接口,從新獲取數據
            }
        }

 

                使用了type=index,分頁以後,索引仍是從1開始,如何實現累加呢?

                使用render函數可解決:

                  {
                        title: '序號',
                        align:'center',
                        type: 'index2',
                        width: 80,
                        render: (h, params) => {
                            return h('span', params.index + (this.page.current - 1) * this.page.size + 1);
                        }
                    }

 

                在翻頁以後,如何記住checkbox多選的選中和未選中狀態?

                用一個數組checkData來裝選中的數據,在每次表格數據改變時,經過比對數據來進行回填選中狀態。

<Table border :columns="columns" :data="data" @on-select="changeSelect" @on-select-cancel="changeSelectCancel" @on-select-all="changeSelectAll" @on-select-all-cancel="changeSelectAllCancel"></Table>
         methods: {
            changeSelect(data, val){  // 選中某個數據
                /**
                 * checkData  多選框選中的數組
                 * id  每條數據的惟一標識
                 */
                for(let i in this.checkData){
                    if(val.id === this.checkData[i].id){
                        this.checkData.splice(i, 1);
                        break;
                    }
                }
                this.checkData.push(val);
            },
            changeSelectCancel(data, val){  // 取消某個數據
                for(let i in this.checkData){
                    if(val.id === this.checkData[i].id){
                        this.checkData.splice(i, 1);
                        break;
                    }
                }
            },
            changeSelectAll(data){  // 多選選中
                let arr = [];
                for(let i in data){
                    let flag = true;
                    for(let y in this.checkData){
                        if(data[i].id === this.checkData[y].id){ // 已有數據
                            flag = false;
                            break;
                        }else{
                            continue;
                        }
                    }
                    if(flag){  // 添加新數據
                        arr.push(data[i]); 
                    }
                }  
                this.checkData = this.checkData.concat(arr); 
            },
            changeSelectAllCancel(data){  // 多選取消
                for(let i in this.data){ // 取消當前頁的內容
                    for(let y in this.checkData){
                        if(this.data[i].id === this.checkData[y].id){
                            this.checkData.splice(y, 1);
                            break;
                        }
                    }
                }
            },
        },
        watch:{
            'data':{
                handler:function(newValue, oldValue){
                    this.data = newValue;
                    for(let i in this.data){
                        let flag = false;
                        for(let y in this.checkData){
                            if(this.data[i].id === this.checkData[y].id){
                                flag = true;
                                break;
                            }else{
                                continue;
                            }
                        }
                        if(flag){  // 回填選中狀態
                            this.data[i]._checked = true;
                        }else{
                            this.data[i]._checked = false;
                        }
                    }
                },
                deep:true
            }
        }

 

5、定製iview主題

 

     按照官網,一步一步作的,最後卻報錯:

    

   那是由於less的版本太高,從新卸載,安裝3.0如下的版本(好比2.7.3版本),便可解決問題。

相關文章
相關標籤/搜索