在 Vue2 中集成kendoDropDownList——如何在 Vue2 中集成 KendoUI

回顧


上一篇文章中,我們搭建了 KendoUI 和 Vue.js 的集成開發(fā)環(huán)境,
并且提出了一個 kendoDropDownList 的集成方案:

  1. 父組件通過 props 傳遞相關配置到我們包裝的 component
  2. 子組件通過觸發(fā)事件來進行

現(xiàn)在,我們可以將該方案完善一下:

  1. 父組件通過 props 傳遞相關配置到 我們包裝的 component
  2. 通過 v-model 對數(shù)據(jù)進行雙向綁定

那么如何使用 v-model 指令呢?
仔細查閱Vue2的文檔,會發(fā)現(xiàn):

<input v-model="something">

只是

<input v-bind:value="something" v-on:input="something = $event.target.value">

的語法糖。

在Vue2的組件中,我們可以將以上寫法簡寫為:

<custom-input v-bind:value="something" v-on:input="something = arguments[0]"></custom-input>

所以如果我們想讓組件接受 v-model 指令,必須滿足:

  1. 必須接受 value 屬性
  1. 組件內(nèi)部需要使用 input 事件把新的值帶出來

所以現(xiàn)在就非常簡單了:

  1. 使用 Node.js express 生成一個簡單的數(shù)據(jù)源
  2. 我們希望在 kendoDropDownList 組件中調用 kendoDropDownList 模塊的 init 方法,傳入的option應該包括:dataSource的描述(url,httpMethod 或者直接是datavalueField,textField),當前的 element(this.$el),value
  3. kendoDropDownListinit 方法中添加相應的初始化方法
  4. kendoDropDownList 的值改變的時候應該觸發(fā)input事件,并帶上新的值
  5. 需要對組件中的value進行watch。當value改變時,需要將該值帶回 kendoDropDownList

所以我們希望以如下方式調用我們的組件

<drop-down-list v-model="selectedValues.firstSelectValue" v-bind:dataSource="dropDownListOptions.dataSource"></drop-down-list>

使用 Node.js express 準備我們的數(shù)據(jù)源


首先,你需要新建一個express應用程序

然后添加以下路由:

router.get('/dropDownListData', function (req, res, next) {
    let data = [
        {key: "option1", value: 1},
        {key: "option2", value: 2}
    ];

    setTimeout(()=>{res.json(data);}, 1000)
});

router.get('/dropDownListData2', function (req, res, next) {
    let data = [
        {key: "option3", value: 3},
        {key: "option4", value: 4}
    ];

    setTimeout(()=>{res.json(data);}, 1000)
});

setTimeout意為一個比較費時的取數(shù)據(jù)的操作。

然后你需要使用 cors 允許你的express應用程序接受跨域請求

啟動該應用。

包裝 kendoDataSource 和 kendoDropDownList


本來本節(jié)只有包裝 kendoDropDownList,但是代碼寫了一半發(fā)現(xiàn),KendoUI 的組件有很多都需要 kendoDataSource 來提供數(shù)據(jù)源,所以我們也需要寫一個 kendoDataSource的工廠來生成配置的 dataSource 部分。
代碼如下:

//文件:src/modules/kendoUi/kendoDataSource.js
function getKendoDataSource(dataSource){
  let result = dataSource.url ?
    _generateKendoRemoteDataSource(dataSource)  :
    _generateKendoObjectDataSource(dataSource);

  return result;
}

function _generateKendoObjectDataSource(dataSource){
  return dataSource.data;

}

function _generateKendoRemoteDataSource(dataSource){

  return {
    transport: {
      read: {
        type: dataSource.method,
        dataType: "json",
        url: dataSource.url,
      }
    }
  }
}

export default {
  getKendoDataSource
}

所以我們可以這樣初始化kendoDropDownList:

//文件:src/modules/kendoDropDownList.js
import 'kendoUiStyles/kendo.common.min.css'
import 'kendoUiStyles/kendo.bootstrap.min.css'
import kendoDropDownList from 'kendoUi/kendo.dropdownlist.min'
import $ from 'jquery'
import kendoDataSource from "./kendoDataSource"

function init(option) {
  let el = option.el;

  let dropDownList = option.dataSource.url ? initWithDataSource(option) : initWithDataObject(option);

  dropDownList.data("kendoDropDownList").value(option.value);
}

function initWithDataSource({dataSource, el, onValueChanged}) {

  let kendoDropDownListOption = {
    dataTextField: dataSource.dataTextField,
    dataValueField: dataSource.dataValueField,
    optionLabel: "---請選擇---",
    change: function (e) {
      onValueChanged(this.value());
    },
    dataSource: kendoDataSource.getKendoDataSource(dataSource)
  };

  return $(el).kendoDropDownList(kendoDropDownListOption);
}

function initWithDataObject({dataSource, el, onValueChanged}) {
  let kendoDropDownListOption = {
    dataTextField: dataSource.dataTextField,
    dataValueField: dataSource.dataValueField,
    optionLabel: "---請選擇---",
    change: function (e) {
      onValueChanged(this.value());
    },
    dataSource: kendoDataSource.getKendoDataSource(dataSource)
  };

  return $(el).kendoDropDownList(kendoDropDownListOption);
}

function updateSelectedValue({el, value}){
  $(el).data("kendoDropDownList").value(value);
}

function updateDataSource({el, dataSource}){
  console.log($(el).data("kendoDropDownList"));

  let ds = kendoDataSource.getKendoDataSource(dataSource);
  $(el).data("kendoDropDownList").setDataSource(ds)
}

export default {
  init,
  updateSelectedValue,
  updateDataSource
}

其中,el 代表從 vue component 那邊傳來的當前的元素。

??該文件只會執(zhí)行一次(第一次被import的時候),所以不要在文件內(nèi)部寫全局變量。

??代碼還有重構的余地

構建自定義組件

于是,我們就可以在自定義組件中這樣調用:

<!--文件: src/components/kendoDropDownList.vue-->
<template>
  <div></div>
</template>

<script>
  import kendoDropDownList from "../modules/kendoUi/kendoDropDownList"

  function onValueChanged(value){
    this.$emit("input", value);
  }

  function onMounted() {
    let {dataSource,  value} = this;
    onValueChanged = onValueChanged.bind(this);

    let option = {
      dataSource,
      value,
      el: this.$el,
      onValueChanged
    };

    console.log(option);

    kendoDropDownList.init(option);
  }

  let props = {
    data: Array,
    dataSource: Object,
    value: {}
  };

  function updateValue(newValue){
    let el = this.$el;
    let value = newValue;
    kendoDropDownList.updateSelectedValue({el, value})
  }

  function updateDataSource(newDataSource){
    let el = this.$el;
    let dataSource = newDataSource;
    kendoDropDownList.updateDataSource({el, dataSource})
  }

  export default {
    name: "dropDownList",
    mounted: onMounted,
    props,
    watch:{
      value: updateValue,
      dataSource: updateDataSource
    }
  }
</script>


至此,我們的第一個KendoUI組件就完成了。你可以這樣調用它:

<template>
  <div id="app">
    <!--![](./assets/logo.png)-->
    <!--<hello></hello>-->
    <drop-down-list v-model="selectedValues.firstSelectValue" v-bind:dataSource="dropDownListOptions.dataSource"></drop-down-list>
    <drop-down-list v-model="selectedValues.secondSelectedValue" v-bind:dataSource="dropDownListOpts2.dataSource"></drop-down-list>
    <button v-on:click="changeFirstValue">修改第一個select的值為2</button>
    <button v-on:click="changeFirstDataSource">將第一個的數(shù)據(jù)源修改為 /dropDownListData2</button>
  </div>
</template>

<script>

  import dropDownList from "./components/kendoDropDownList.vue"

  let dropDownListOptions = {
    value: 2,
    dataSource: {
      url: "http://localhost:3000/dropDownListData",
      method: "GET",
      dataTextField: "key",
      dataValueField: "value"
    }
  };

  let dropDownListOpts2 = {
    dataSource: {
      data: [
        {key: "option1", value: 1},
        {key: "option2", value: 2}
      ],
      dataTextField: "key",
      dataValueField: "value"
    },
    value: 2
  };

  let selectedValues = {
    firstSelectValue :1,
    secondSelectedValue: 2
  };

  let data = function () {
    return {
      dropDownListOptions,

      dropDownListOpts2,
      selectedValues
    }
  };

  function changeFirstValue(){
    this.selectedValues.firstSelectValue = 2;
  }

  function changeFirstDataSource(){
    this.dropDownListOptions.dataSource = {
      url: "http://localhost:3000/dropDownListData2",
      method: "GET",
      dataTextField: "key",
      dataValueField: "value"
    }
  }

  export default {
    name: 'app',
    components: {
      dropDownList
    },
    methods: {
      changeFirstValue,
      changeFirstDataSource
    },
    data
  }
</script>

那么,效果應該是這樣的:

kendoDropDownList最終效果

在這個例子中,我們使用了v-model,實現(xiàn)了子組件與父組件數(shù)據(jù)的雙向綁定,很簡單,是不是?

之后筆者還會對KendoUI的其他組件進行擴充,事實上,還有很多事情我們沒有做。比如,如果我們要使用kendoUI的Template功能,就可能還要做一些事情,把Template給放出來。

其實也簡單,開發(fā)出來一些預置的Template,然后要用的時候往里面丟就可以了。

后續(xù)


kendoDropDownList 相比,kendoGrid封裝起來可能會稍微復雜一些(主子列表、特殊標記某一列等),可能也需要舍棄一些功能,但是工作流程都是一樣的:

  1. 寫一個專門初始化 kendoGrid 的模塊,該模塊需要根據(jù)當前的DOM對象(el)生成一個kendoGrid
  1. 新建一個Vue組件,引入該模塊,并初始化好kendoGrid
  2. ??需要注意的是,kendoGrid需要頻繁變化數(shù)據(jù)源(比如做篩選操作的時候),所以需要用一個巧妙的方式來解決這個問題(最好不要破壞后臺的RESTFul架構)。

歡迎討論??

導航:

基礎環(huán)境搭建
在 Vue2 中集成kendoDropDownList

最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

  • 這篇筆記主要包含 Vue 2 不同于 Vue 1 或者特有的內(nèi)容,還有我對于 Vue 1.0 印象不深的內(nèi)容。關于...
    云之外閱讀 5,187評論 0 29
  • 雙十一光棍節(jié)前一天,有朋友和我聊天,怨叨著這次又得獨自過光棍節(jié)啦。這個時代,光棍節(jié)、圣誕節(jié)、婦女節(jié)等等所有節(jié)...
    如曉夢閱讀 2,438評論 17 17
  • 明月幾時有?把酒問青天。不知天上宮闕,今夕是何年。我欲乘風歸去,又恐瓊樓玉宇,高處不勝寒。起舞弄清影,何似在人家?...
    珍珠貝閱讀 384評論 1 1
  • 又到月底了,10月結束,意味這這一年也快結束了?;仡?0月的工作與學習,收獲還是挺多的。 一、個人成長 1.讀書 ...
    瞌睡的貓80閱讀 711評論 0 0
  • 鹿邑八景,指鹿邑的八處風景名勝,古人用《八景詩》概括,具體指太清宮隱山遺址、太清宮等。 隱隱青山愛戴煙, ...
    蒙主閱讀 1,445評論 0 0

友情鏈接更多精彩內(nèi)容