1. 程式人生 > >vue+iview 實現可編輯表格

vue+iview 實現可編輯表格

先簡單說明一下,這個Demo引入的vue,iview的方式是標籤引入的,沒有用到webpack之類的構建工具... 畢竟公司還在用angularjs+jq. 這也是我第一次寫文章,大家看看思路就行了,要是有大佬指點指點就更好了

話不多說,先來個效果圖

我們再看下極為簡單的目錄結構

IViewEditTable                ## vue+iview 實現的可編輯表格
└── index.html                ## 首頁
└── js
    └── editTable.js          ## 首頁JS
└── ivew                      ## iview相關
└── vue ├── axios.min.js ## axios (ajax) ├── util.js ## 與業務無關的純工具函式包 └── vue.min.js ## vue (2.x) 複製程式碼

首頁html:

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8"
/>
<title>可編輯表格</title> <link href="iview/iview.css" rel="stylesheet" /> </head> <body style="background-color: #f0f3f4;"> <div id="editTableCtrl"> <i-table :loading="loading" border :data="dataList" :columns="columnsList" stripe size="small"></i-table
>
</div> <script src="vue/axios.min.js"></script> <script src="vue/vue.min.js"></script> <script src="iview/iview.min.js"></script> <script src="vue/util.js"></script> <script src="js/editTable.js"></script> </body> </html> 複製程式碼

首頁沒什麼說的,都是基本的架子. 這是需要渲染的資料及其說明:

{
  "Status": 1,
  "Total": 233,
  "Items": [{
    "ID": 1,
    "PID": 3,
    "PRJCODE": "2018-001",                                          //專案編號  不可編輯
    "PRJNAME": "淡化海水配套泵站",                                  //專案名稱  文字輸入框
    "PRJTYPE": "基礎設施",                                          //專案型別  下拉選項
    "JSUNIT": "投資公司",                                           //建設單位  文字輸入框
    "FLOW_TYPE_CODE":"A02",                                         //流程分類  下拉選項,與資料庫以code形式互動
    "DATE_START": "2018-12-1",                                      //開工時間  日期選擇
    "DATE_END": "2019-12-1",                                        //竣工時間  日期選擇
    "CONTENT": "建設淡化海水配套泵站一座,佔地面積約8500平方米",    //建設內容  多行輸入框
    "INVEST_ALL": "1000"                                            //總投資    數字輸入框
  }]
}
複製程式碼

還有editTable.js的基本架子,$http是我為了方便在utils最後一行加入的 (angularjs用多了,習慣用$http)

Vue.prototype.utils = utils
window.$http = axios
複製程式碼

editTable.js :

var vm = new Vue({
  el: '#editTableCtrl',
  data: function() {
    return {
      loading: true,
      //表格的資料來源
      dataList: [],
      // 列
      columnsList: [],
      // 增加編輯狀態, 儲存狀態, 用於操作資料 避免干擾原資料渲染
      cloneDataList: []
    }
  },
  methods: {
    getData: function() {
      var self = this;
      self.loading = true;
      $http.get('json/editTable.txt').then(function(res) {
        self.dataList = res.data.Items;
        self.loading = false;
      });
    },
  },
  created: function() {
    this.getData();
  }
});
複製程式碼

我們再來按照iview的規則編寫渲染的列:

//...

      /**
       * @name columnsList (瀏覽器 渲染的列)  
       * @author catkin
       * @see https://www.iviewui.com/components/table
       * @param 
       * { 
       *  titleHtml : 渲染帶有html的表頭 列: '資金<em class="blue" style="color:red">來源</em>'
       *  editable  : true,可編輯的列 必須有欄位 
       *  option    : 渲染的下拉框列表,如果需要與資料庫互動的值與顯示的值不同,須使用[{value:'value',label:'label'}]的形式,下面有例子
       *  date      : 渲染成data型別 ,可選引數: 
       *              date | daterange: yyyy-MM-dd (預設)
       *              datetime | datetimerange: yyyy-MM-dd HH:mm:ss
       *              year: yyyy
       *              month: yyyy-MM
       *  input     : 渲染input型別 ,可選引數為html5所有型別 (額外增加 textarea 屬性), 預設text
       *  handle    : 陣列型別, 渲染操作方式,目前只支援 'edit', 'delete'
       * }
       * @version 0.0.1
       */

columnsList: [{
    width: 80,
    type: 'index',
    title: '序號',
    align: 'center'
}, {
    align: 'center',
    title: '專案編號',
    key: 'PRJCODE'
}, {
    align: 'center',
    title: '專案名稱',
    titleHtml: '專案名稱 <i class="ivu-icon ivu-icon-edit"></i>',
    key: 'PRJNAME',
    editable: true
}, {
    align: 'center',
    title: '專案分類',
    titleHtml: '專案分類 <i class="ivu-icon ivu-icon-edit"></i>',
    key: 'PRJTYPE',
    option: ['產業專案', '基礎設施', '民生專案', '住宅專案'],
    editable: true
}, {
    align: 'center',
    title: '建設單位',
    titleHtml: '建設單位 <i class="ivu-icon ivu-icon-edit"></i>',
    key: 'JSUNIT',
    editable: true
}, {
    align: 'center',
    title: '流程分類',
    titleHtml: '流程分類 <i class="ivu-icon ivu-icon-edit"></i>',
    key: 'FLOW_TYPE_CODE',
    option: [{
      value: 'A01',
      label: '建築-出讓'
    }, {
      value: 'A02',
      label: '建築-劃撥'
    }, {
      value: 'B01',
      label: '市政-綠化'
    }, {
      value: 'B02',
      label: '市政-管線'
    }],
    editable: true
}, {
    align: 'center',
    title: '開工時間',
    titleHtml: '開工時間 <i class="ivu-icon ivu-icon-edit"></i>',
    key: 'DATE_START',
    //這裡在後面處理的時候會分割成['month','yyyy-MM']的陣列,分別代表iview的DatePicker元件選擇日期的格式與資料庫傳過來時頁面顯示的格式
    date: 'month_yyyy-MM',   
    editable: true
}, {
    align: 'center',
    title: '竣工時間',
    titleHtml: '竣工時間 <i class="ivu-icon ivu-icon-edit"></i>',
    key: 'DATE_END',
    date: 'month_yyyy-MM',
    editable: true
}, {
    align: 'center',
    title: '建設內容',
    titleHtml: '建設內容 <i class="ivu-icon ivu-icon-edit"></i>',
    key: 'CONTENT',
    input: 'textarea',
    editable: true
}, {
    align: 'center',
    title: '總投資(萬元)',
    titleHtml: '總投資<br />(萬元) <i class="ivu-icon ivu-icon-edit"></i>',
    key: 'INVEST_ALL',
    input: 'number',
    editable: true
}, {
    title: '操作',
    align: 'center',
    width: 150,
    key: 'handle',
    handle: ['edit', 'delete']
}]

//...
複製程式碼

此時頁面應該已經可以渲染出表格了

既然要編輯資料,並且我的需求是整行整行的編輯,而編輯的同時就會同步更新資料,那麼問題來了

vue中, 資料更新,檢視會隨之更新. 想象一下,我在輸入框中屬於一個值,觸發了資料更新,接著又觸發了檢視更新,那麼我每次輸入時,這個input都會失焦,毫無使用者體驗. 所以我們把可編輯的動態內容用cloneDataList渲染,靜態顯示的用dataList渲染

//...
self.dataList = res.data.Items;
// 簡單的深拷貝,雖然map會返回新陣列,但是陣列元素也是引用型別,不能直接改,所以先深拷貝一份
self.cloneDataList = JSON.parse(JSON.stringify(self.dataList)).map(function(item) {
  // 給每行新增一個編輯狀態 與 儲存狀態, 預設都是false
  item.editting = false;
  item.saving = false;
  return item;
});
//...
複製程式碼

接下來,我們要根據columnsList做一次迴圈判斷,根據相應的key寫出不同的render函式

//全域性新增
//根據value值找出陣列中的物件元素
function findObjectInOption(value) {
  return function(item) {
    return item.value === value;
  }
}
//動態新增編輯按鈕
var editButton = function(vm, h, currentRow, index) {
  return h('Button', {
    props: {
      size: 'small',
      type: currentRow.editting ? 'success' : 'primary',
      loading: currentRow.saving
    },
    style: {
      margin: '0 5px'
    },
    on: {
      click: function() {
        // 點選按鈕時改變當前行的編輯狀態, 當資料被更新時,render函式會再次執行,詳情參考https://cn.vuejs.org/v2/api/#render
        // handleBackdata是用來刪除當前行的editting屬性與saving屬性
        var tempData = vm.handleBackdata(currentRow)
        if (!currentRow.editting) {
          currentRow.editting = true;
        } else {
          // 這裡也是簡單的點選編輯後的資料與原始資料做對比,一致則不做操作,其實更好的應該遍歷所有屬性並判斷
          if (JSON.stringify(tempData) == JSON.stringify(vm.dataList[index])) {
            console.log('未更改');
            return currentRow.editting = false;
          }
          vm.saveData(currentRow, index)
          currentRow.saving = true;
        }
      }
    }
  }, currentRow.editting ? '儲存' : '編輯');
};
//動態新增 刪除 按鈕
var deleteButton = function(vm, h, currentRow, index) {
  return h('Poptip', {
      props: {
        confirm: true,
        title: currentRow.WRAPDATASTATUS != '刪除' ? '您確定要刪除這條資料嗎?' : '您確定要對條資料撤銷刪除嗎?',
        transfer: true,
        placement: 'left'
      },
      on: {
        'on-ok': function() {
          vm.deleteData(currentRow, index)
        }
      }
    },
    [
      h('Button', {
        style: {
          color: '#ed3f14',
          fontSize: '18px',
          padding: '2px 7px 0',
          border: 'none',
          outline: 'none',
          focus: {
            '-webkit-box-shadow': 'none',
            'box-shadow': 'none'
          }
        },
        domProps: {
          title: '刪除'
        },
        props: {
          size: 'small',
          type: 'ghost',
          icon: 'android-delete',
          placement: 'left'
        }
      })
    ]);
};


//methods中新增
init: function() {
  console.log('init');
  var self = this;
  self.columnsList.forEach(function(item) {
    // 使用$set 可以觸發檢視更新
    // 如果含有titleHtml屬性 將其值填入表頭
    if (item.titleHtml) {
      self.$set(item, 'renderHeader', function(h, params) {
        return h('span', {
          domProps: {
            innerHTML: params.column.titleHtml
          }
        });
      });
    }
    // 如果含有操作屬性 新增相應按鈕
    if (item.handle) {
      item.render = function(h, param) {
        var currentRow = self.cloneDataList[param.index];
        var children = [];
        item.handle.forEach(function(item) {
          if (item === 'edit') {
            children.push(editButton(self, h, currentRow, param.index));
          } else if (item === 'delete') {
            children.push(deleteButton(self, h, currentRow, param.index));
          }
        });
        return h('div', children);
      };
    }
    //如果含有editable屬性並且為true
    if (item.editable) {
      item.render = function(h, params) {
        var currentRow = self.cloneDataList[params.index];
        // 非編輯狀態
        if (!currentRow.editting) {
          // 日期型別單獨 渲染(利用工具暴力的formatDate格式化日期)
          if (item.date) {
            return h('span', self.utils.formatDate(currentRow[item.key], item.date.split('_')[1]))
          }
          // 下拉型別中value與label不一致時單獨渲染
          if (item.option && self.utils.isArray(item.option)) {
            // 我這裡為了簡單的判斷了第一個元素為object的情況,其實最好用every來判斷所有元素
            if (typeof item.option[0] === 'object') {
              return h('span', item.option.find(findObjectInOption(currentRow[item.key])).label);
            }
          }
          return h('span', currentRow[item.key]);
        } else {
        // 編輯狀態
          //如果含有option屬性
          if (item.option && self.utils.isArray(item.option)) {
            return h('Select', {
              props: {
                // ***重點***:  這裡要寫currentRow[params.column.key],繫結的是cloneDataList裡的資料
                value: currentRow[params.column.key]
              },
              on: {
                'on-change': function(value) {
                  self.$set(currentRow, params.column.key, value)
                }
              }
            }, item.option.map(function(item) {
              return h('Option', {
                props: {
                  value: item.value || item,
                  label: item.label || item
                }
              }, item.label || item);
            }));
          } else if (item.date) {
            //如果含有date屬性
            return h('DatePicker', {
              props: {
                type: item.date.split('_')[0] || 'date',
                clearable: false,
                value: currentRow[params.column.key]
              },
              on: {
                'on-change': function(value) {
                  self.$set(currentRow, params.column.key, value)
                }
              }
            });
          } else {
            // 預設input
            return h('Input', {
              props: {
                // type型別也是自定的屬性
                type: item.input || 'text',
                // rows只有在input 為textarea時才會起作用
                rows: 3,
                value: currentRow[params.column.key]
              },
              on: {
                'on-change'(event) {
                  self.$set(currentRow, params.column.key, event.target.value)
                }
              }
            });
          }
        }
      };
    }
  });
},
// 還原資料,用來與原始資料作對比的
handleBackdata: function(object) {
  var clonedData = JSON.parse(JSON.stringify(object));
  delete clonedData.editting;
  delete clonedData.saving;
  return clonedData;
}
複製程式碼

到這裡完成已經差不多了,補上儲存資料與刪除資料的函式

// 儲存資料
saveData: function(currentRow, index) {
  var self = this;
  // 修改當前的原始資料, 就不需要再從服務端獲取了
  this.$set(this.dataList, index, this.handleBackdata(currentRow))
  // 需要儲存的資料
  // 模擬ajax
  setTimeout(function() {
    充值編輯與儲存狀態
    currentRow.saving = false;
    currentRow.editting = false;
    self.$Message.success('儲存完成');
    console.log(self.dataList);
  }, 1000)
},
// 刪除資料
deleteData: function(currentRow, index) {
  var self = this;
  console.log(currentRow.ID);
  setTimeout(function() {
    self.$delete(self.dataList, index)
    self.$delete(self.cloneDataList, index)
    vm.$Message.success('刪除成功');
  }, 1000)
},
複製程式碼

完整的editTable.js程式碼

// 根據資料中下拉的值找到對應的物件
function findObjectInOption(name) {
  return function(item) {
    return item.value === name;
  }
}
var editButton = function(vm, h, currentRow, index) {
  return h('Button', {
    props: {
      size: 'small',
      type: currentRow.editting ? 'success' : 'primary',
      loading: currentRow.saving
    },
    style: {
      margin: '0 5px'
    },
    on: {
        click: function() {
          // 點選按鈕時改變當前行的編輯狀態,當資料被更新時,render函式會再次執行,詳情參考https://cn.vuejs.org/v2/api/#render
          // handleBackdata是用來刪除當前行的editting屬性與saving屬性
          var tempData = vm.handleBackdata(currentRow)
          if (!currentRow.editting) {
            currentRow.editting = true;
          } else {
            // 這裡也是簡單的點選編輯後的資料與原始資料做對比,一致則不做操作,其實更好的應該遍歷所有屬性並判斷
            if (JSON.stringify(tempData) == JSON.stringify(vm.dataList[index])) {
              console.log('未更改');
              return currentRow.editting = false;
            }
            vm.saveData(currentRow, index)
            currentRow.saving = true;
          }
        }
    }
  }, currentRow.editting ? '儲存' : '編輯');
};
//動態新增 刪除 按鈕
var deleteButton = function(vm, h, currentRow, index) {
  return h('Poptip', {
      props: {
        confirm: true,
        title: currentRow.WRAPDATASTATUS != '刪除' ? '您確定要刪除這條資料嗎?' : '您確定要對條資料撤銷刪除嗎?',
        transfer: true,
        placement: 'left'
      },
      on: {
        'on-ok': function() {
          vm.deleteData(currentRow, index)
        }
      }
    },
    [
      h('Button', {
        style: {
          color: '#ed3f14',
          fontSize: '18px',
          padding: '2px 7px 0',
          border: 'none',
          outline: 'none',
          focus: {
            '-webkit-box-shadow': 'none',
            'box-shadow': 'none'
          }
        },
        domProps: {
          title: '刪除'
        },
        props: {
          size: 'small',
          type: 'ghost',
          icon: 'android-delete',
          placement: 'left'
        }
      })
    ]);
};
var vm = new Vue({
  el: '#editTableCtrl',
  data: function() {
    return {
      loading: true,
      //表格的資料來源
      dataList: [],
      /**
       * @name columnsList (瀏覽器 渲染的列)  
       * @author ch
       * @see https://www.iviewui.com/components/table
       * @param 
       * { 
       *  titleHtml : 渲染帶有html的表頭 列: '資金<em class="blue" style="color:red">來源</em>'
       *  editable  : true,可編輯的列 必須有欄位 
       *  option    : 渲染的下拉框列表
       *  date      : 渲染成data型別 ,可選引數: 
       *              date | daterange: yyyy-MM-dd (預設)
       *              datetime | datetimerange: yyyy-MM-dd HH:mm:ss
       *              year: yyyy
       *              month: yyyy-MM
       *  input     : 渲染input型別 ,可選引數為html5所有型別 (額外增加 textarea 屬性), 預設text
       *  handle    : 陣列型別, 渲染操作方式,目前只支援 'edit', 'delete'
       * }
       * @version 0.0.1
       */
      columnsList: [{
        width: 80,
        type: 'index',
        title: '序號',
        align: 'center'
      }, {
        align: 'center',
        title: '專案編號',
        key: 'PRJCODE'
      }, {
        align: 'center',
        title: '專案名稱',
        titleHtml: '專案名稱 <i class="ivu-icon ivu-icon-edit"></i>',
        key: 'PRJNAME',
        editable: true
      }, {
        align: 'center',
        title: '專案分類',
        titleHtml: '專案分類 <i class="ivu-icon ivu-icon-edit"></i>',
        key: 'PRJTYPE',
        option: ['產業專案', '基礎設施', '民生專案', '住宅專案'],
        editable: true
      }, {
        align: 'center',
        title: '建設單位',
        titleHtml: '建設單位 <i class="ivu-icon ivu-icon-edit"></i>',
        key: 'JSUNIT',
        editable: true
      }, {
        align: 'center',
        title: '流程分類',
        titleHtml: '流程分類 <i class="ivu-icon ivu-icon-edit"></i>',
        key: 'FLOW_TYPE_CODE',
        option: [{
          value: 'A01',
          label: '建築-出讓'
        }, {
          value: 'A02',
          label: '建築-劃撥'
        }, {
          value: 'B01',
          label: '市政-綠化'
        }, {
          value: 'B02',
          label: '市政-管線'
        }],
        editable: true
      }, {
        align: 'center',
        title: '開工時間',
        titleHtml: '開工時間 <i class="ivu-icon ivu-icon-edit"></i>',
        key: 'DATE_START',
        //這裡在後面處理的時候會分割成['month','yyyy-MM']的陣列,分別代表iview的DatePicker元件選擇日期的格式與資料庫傳過來時頁面顯示的格式
        date: 'month_yyyy-MM',
        editable: true
      }, {
        align: 'center',
        title: '竣工時間',
        titleHtml: '竣工時間 <i class="ivu-icon ivu-icon-edit"></i>',
        key: 'DATE_END',
        date: 'month_yyyy-MM',
        editable: true
      }, {
        align: 'center',
        title: '建設內容',
        titleHtml: '建設內容 <i class="ivu-icon ivu-icon-edit"></i>',
        key: 'CONTENT',
        input: 'textarea',
        editable: true
      }, {
        align: 'center',
        title: '總投資(萬元)',
        titleHtml: '總投資<br />(萬元) <i class="ivu-icon ivu-icon-edit"></i>',
        key: 'INVEST_ALL',
        input: 'number',
        editable: true
      }, {
        title: '操作',
        align: 'center',
        width: 150,
        key: 'handle',
        handle: ['edit', 'delete']
      }],
      // 增加編輯狀態, 儲存狀態, 用於操作資料 避免干擾原資料渲染
      cloneDataList: []
    }
  },
  methods: {
    getData: function() {
      var self = this;
      self.loading = true;
      $http.get('json/editTable.txt').then(function(res) {
        // 給每行新增一個編輯狀態 與 儲存狀態
        self.dataList = res.data.Items;
        self.cloneDataList = JSON.parse(JSON.stringify(self.dataList)).map(function(item) {
          item.editting = false;
          item.saving = false;
          return item;
        });
        self.loading = false;
      });
    },
    //初始化資料
    //methods中新增
    init: function() {
      console.log('init');
      var self = this;
      self.columnsList.forEach(function(item) {
        // 使用$set 可以觸發檢視更新
        // 如果含有titleHtml屬性 將其值填入表頭
        if (item.titleHtml) {
          self.$set(item, 'renderHeader', function(h, params) {
            return h('span', {
              domProps: {
                innerHTML: params.column.titleHtml
              }
            });
          });
        }
        // 如果含有操作屬性 新增相應按鈕
        if (item.handle) {
          item.render = function(h, param) {
            var currentRow = self.cloneDataList[param.index];
            var children = [];
            item.handle.forEach(function(item) {
              if (item === 'edit') {
                children.push(editButton(self, h, currentRow, param.index));
              } else if (item === 'delete') {
                children.push(deleteButton(self, h, currentRow, param.index));
              }
            });
            return h('div', children);
          };
        }
        //如果含有editable屬性並且為true
        if (item.editable) {
          item.render = function(h, params) {
            var currentRow = self.cloneDataList[params.index];
            // 非編輯狀態
            if (!currentRow.editting) {
              // 日期型別單獨 渲染(利用工具暴力的formatDate格式化日期)
              if (item.date) {
                return h('span', self.utils.formatDate(currentRow[item.key], item.date.split('_')[1]))
              }
              // 下拉型別中value與label不一致時單獨渲染
              if (item.option && self.utils.isArray(item.option)) {
                // 我這裡為了簡單的判斷了第一個元素為object的情況,其實最好用every來判斷所有元素
                if (typeof item.option[0] === 'object') {
                  return h('span', item.option.find(findObjectInOption(currentRow[item.key])).label);
                }
              }
              return h('span', currentRow[item.key]);
            } else {
              // 編輯狀態
              //如果含有option屬性
              if (item.option && self.utils.isArray(item.option)) {
                return h('Select', {
                  props: {
                    // ***重點***:  這裡要寫currentRow[params.column.key],繫結的是cloneDataList裡的資料
                    value: currentRow[params.column.key]
                  },
                  on: {
                    'on-change': function(value) {
                      self.$set(currentRow, params.column.key, value)
                    }
                  }
                }, item.option.map(function(item) {
                  return h('Option', {
                    props: {
                      value: item.value || item,
                      label: item.label || item
                    }
                  }, item.label || item);
                }));
              } else if (item.date) {
                //如果含有date屬性
                return h('DatePicker', {
                  props: {
                    type: item.date.split('_')[0] || 'date',
                    clearable: false,
                    value: currentRow[params.column.key]
                  },
                  on: {
                    'on-change': function(value) {
                      self.$set(currentRow, params.column.key, value)
                    }
                  }
                });
              } else {
                // 預設input
                return h('Input', {
                  props: {
                    // type型別也是自定的屬性
                    type: item.input || 'text',
                    // rows只有在input 為textarea時才會起作用
                    rows: 3,
                    value: currentRow[params.column.key]
                  },
                  on: {
                    'on-change'(event) {
                      self.$set(currentRow, params.column.key, event.target.value)
                    }
                  }
                });
              }
            }
          };
        }
      });
    },
    saveData: function(currentRow, index) {
      var self = this;
      // 修改當前的原始資料, 就不需要再從服務端獲取了
      this.$set(this.dataList, index, this.handleBackdata(currentRow))
      // 需要儲存的資料
      // 模擬ajax
      setTimeout(function() {
        // 重置編輯與儲存狀態
        currentRow.saving = false;
        currentRow.editting = false;
        self.$Message.success('儲存完成');
        console.log(self.dataList);
      }, 1000)
    },
    // 刪除資料
    deleteData: function(currentRow, index) {
      var self = this;
      console.log(currentRow.ID);
      setTimeout(function() {
        self.$delete(self.dataList, index)
        self.$delete(self.cloneDataList, index)
        vm.$Message.success('刪除成功');
      }, 1000)
    },
    // 還原資料,用來與原始資料作對比的
    handleBackdata: function(object) {
      var clonedData = JSON.parse(JSON.stringify(object));
      delete clonedData.editting;
      delete clonedData.saving;
      return clonedData;
    }
  },
  created: function() {
    this.getData();
    this.init();
  }
});
複製程式碼

總結

兩三天的時間搞的這些,剛開始也是各種懵逼.期間也試過用插槽來實現,但還是沒有這個方法來的清晰(隊友都能看懂), 總的來說就是在columnsList自定義一些屬性,後面根據這些屬性,在render函式裡return不同的值,思路還是很簡單的.

第一次寫文章,並且我也是vue初學者,寫的湊合看吧 ^_^ ,歡迎留言指正

本demo 連同之前學習vue時寫的demo一起放在的我的github上,歡迎star...

github: github.com/catkinmu/vu…

參考