不容錯(cuò)過的Vue2.0組件開發(fā)

簡述


(本文針對于有Vue有一定基礎(chǔ)的人學(xué)習(xí)了解,環(huán)境搭建等入門教程網(wǎng)上很多,大家自行學(xué)習(xí),也可留言,我會(huì)給出一些不錯(cuò)的教程博客供大家學(xué)習(xí)。)

一、通過一個(gè)小demo,讓大家深入了解組件開發(fā)。并將教會(huì)大家以下知識(shí)。
  1. (特色) v-model 在自定義組件中的使用。在送索引擎中,搜索 v-model 相關(guān)知識(shí),絕大部分都是如何使用v-model這個(gè)指令進(jìn)行數(shù)據(jù)雙向綁定。然而,如何自定義一個(gè)組件,并且使用這個(gè)組件時(shí)可以用v-model,讓自己的組件也支持?jǐn)?shù)據(jù)雙向綁定,是一個(gè)問題,也很少有教程。

2.自定義組件,組件的使用。這部分內(nèi)容網(wǎng)絡(luò)上的教程很多,不作為重點(diǎn)介紹。

3.組件間的通訊。本章中將會(huì)使用$emit進(jìn)行父子組件中的通訊。并且提供工具類,降低耦合性。

4.<strong>(特色)兩個(gè)組件配合使用,完成特定功能</strong>兩個(gè)組件嵌套使用,完成效果和對數(shù)據(jù)的管理。

二、demo 說明

廢話不多說,先上效果圖。

demo.png
demo.gif

實(shí)現(xiàn)思路,自定義兩個(gè)組件,一個(gè)標(biāo)簽組件“seltipoption”,方便使用v-for進(jìn)行渲染,一個(gè)父組件"seltiplist",管理v-model,接收"seltipoption"事件等。

編寫

1 新建組件“seltipoption.vue”

該組件需要完成的功能是:顯示標(biāo)簽內(nèi)容、響應(yīng)點(diǎn)擊事件、高亮顯示是否被選中。

<template>
  <span class="tip" @click="selectOptionClick" :class="{'active':itemSelected }">{{currentLabel}}</span>
</template>
<script type="text/ecmascript-6">
  import Emitter from "../emitter";
  var underscore = require("../underscore-min");
  export default{
    mixins: [Emitter],
    componentName: "seltipoption",
    props: {
      value: {
        required: true
      },
      label: [String, Number],
    },
    //屬性計(jì)算
    computed: {
      currentLabel() {
        return this.label || ((typeof this.value === 'string' || typeof this.value === 'number') ? this.value : '');
      },
      parent() {
        let result = this.$parent;
        while (!result.istipSelect) {
          result = result.$parent;
        }
        return result;
      },
      itemSelected() {
        if (!this.parent.multiple) {
//由于現(xiàn)實(shí)問題,此處underscore..isEqual中間為下劃線_
           return underscore._.isEqual( this.parent.value, this.value);
        } else {
          let isSelected = false;
          this.parent.value.forEach((item, index) => {
//由于現(xiàn)實(shí)問題,此處underscore..isEqual中間為下劃線_
            if (underscore._.isEqual(item, this.value)) {
              isSelected = true;
            }
          });
          return isSelected;
        }
      },
    },
    methods: {
      selectOptionClick(){
        this.dispatch('seltiplist', 'handleOptionClick', this.value);
      }
    }
  }
</script>

2 新建組件 “seltiplist.vue”

該組件需要實(shí)現(xiàn)的功能:子組件內(nèi)容分發(fā)、響應(yīng)子組件“seltipoption”選中和取消選中事件、實(shí)現(xiàn)v-model的數(shù)據(jù)雙向綁定。

<template>
  <div>
    <slot></slot>
  </div>
</template>
<script type="text/ecmascript-6">
 import Emitter from "../emitter";
var underscore = require("../underscore-min");
export
default {
        mixins:[Emitter],
        componentName: "seltiplist",//組件名稱,自定義字段。方便用這個(gè)屬性進(jìn)行組件間交流
        data() {
            return {
                istipSelect: true
            }
        },
        props: {
            value: {},
            multiple: {
                type: Boolean,
                default:false
            }//屬性標(biāo)識(shí)篩選條件是單選項(xiàng)還是多選項(xiàng)

        },

        mounted() {
            this.$on('handleOptionClick', this.handleOptionSelect);
        },
        methods: {
            handleOptionSelect(val) {
//由于現(xiàn)實(shí)問題,此處underscore..isArray中間為下劃線
                if (this.multiple && underscore._.isArray(this.value) )  {
                    this.value.forEach( (item, index ) => {
//由于現(xiàn)實(shí)問題,此處underscore..isEqual中間為下劃線_
                        if (underscore._.isEqual(item, val)) {
                            optionIndex = index;
                        }
                    });
                    if (optionIndex < 0) {
                        this.value.push(val);
                    } else {
                        this.value.splice(optionIndex, 1)
                    }
                } else {
                    if (val != this.value) {
                        this.$emit('input', val);
                    } else {
                        this.$emit('input', "");
                    }
                }

            }
        }
    }
</script>
</code>
3 組件使用
 <div class="selectlist">
        <div class="title">地區(qū)</div>
        <div class="select-box">
          <seltiplist  v-model="loacl_select">
            <seltipoption v-for=" item in local " :label="item.label" :value="item"></seltipoption>
          </seltiplist>
        </div>
      </div>
      <div class="selectlist">
        <div class="title">薪資要求</div>
        <div class="select-box">
          <seltiplist  v-model="salary_select">
            <seltipoption v-for=" item in salary " :label="item.label" :value="item"></seltipoption>
          </seltiplist>
        </div>
      </div>
      <div class="selectlist">
        <div class="title">福利待遇</div>
        <div class="select-box">
          <seltiplist :multiple="true"  v-model="treatment_select">
            <seltipoption v-for=" item in treatment " :label="item.label" :value="item"></seltipoption>
          </seltiplist>
        </div>
      </div>
<script>
  import seltiplist from "./seltiplist.vue";
  import seltipoption from "./seltipoption.vue";

  export default{
    components: {
      seltiplist,
      seltipoption
    },
    data(){
      return{
        loacl_select:"",
        treatment_select:[{
          id:4,
          label:"項(xiàng)目獎(jiǎng)金"
        }],
        salary_select:"",
        local:[{
          id:1,
          label:"北京"
        },{
          id:2,
          label:"安徽"
        },{
          id:3,
          label:"上海"
        },{
          id:4,
          label:"廣州"
        }],
        treatment:[{
          id:1,
          label:"五險(xiǎn)一金"
        },{
          id:2,
          label:"交通補(bǔ)助"
        },{
          id:3,
          label:"帶薪年假"
        },{
          id:4,
          label:"項(xiàng)目獎(jiǎng)金"
        }],
        salary:[{
          id:1,
          label:"4000以下"
        },{
          id:2,
          label:"4000-6000"
        },{
          id:3,
          label:"6000-8000"
        },{
          id:4,
          label:"8000以上"
        }]
      }
    },
    methods: {}
  }
</script>
4 代碼解讀

1,如何實(shí)現(xiàn)的自定義組件v-model數(shù)據(jù)雙向綁定?
如果要讓組件的 v-model 生效,則這個(gè)組件它必須:

  • 接受一個(gè) value 屬性
  • 在有新的 value 時(shí)觸發(fā) input 事件,直接賦值給this.value是無效的,無法觸發(fā)更新。
  • 當(dāng)為多選項(xiàng)時(shí),更新seltiplist組件的value數(shù)組即可,但是當(dāng)為單選項(xiàng)時(shí),需要使用this.$emit('input', val);來觸發(fā)更新。

2,父子組件通訊。
我加入了一個(gè)minx混合,也就是組件中看到引入的Emitter

function broadcast(componentName, eventName, params) {
  this.$children.forEach(child => {
    var name = child.$options.componentName;
    if (name === componentName) {
      child.$emit.apply(child, [eventName].concat(params));
    } else {
      broadcast.apply(child, [componentName, eventName].concat(params));
    }
  });
}
export default {
  methods: {
//事件向上傳播,參數(shù):接收事件組件的componentName屬性,事件名稱,傳入的參數(shù)
    dispatch(componentName, eventName, params) {
      var parent = this.$parent || this.$root;
      var name = parent.$options.componentName;
//根據(jù)組件的componentName值,找到父組件
      while (parent && (!name || name !== componentName)) {
        parent = parent.$parent;
        if (parent) {
          name = parent.$options.componentName;
        }
      }
///父組件觸發(fā)$emit回調(diào)
      if (parent) {
        parent.$emit.apply(parent, [eventName].concat(params));
      }
    },
//事件向下傳播,參數(shù):接收事件組件的componentName屬性,事件名稱,傳入的參數(shù)(原理同上)
    broadcast(componentName, eventName, params) {
      broadcast.call(this, componentName, eventName, params);
    }
  }
};

當(dāng) seltipoption.vue 響應(yīng)click事件后,通過this.dispatch('seltiplist', 'handleOptionClick', this.value);
觸發(fā)父組件 seltiplist.vue 的監(jiān)聽this.$on('handleOptionClick', this.handleOptionSelect);實(shí)現(xiàn)組件間的通訊。并且在一定程度上可以起到解耦的作用。

3, seltipoption 的選擇狀態(tài)判斷
當(dāng)為單選項(xiàng)時(shí) ,判斷seltipoption的value是否等于seltiplist的value;
當(dāng)為多選項(xiàng)時(shí),seltipoption的value存在于seltiplist value的數(shù)組中。
為了判斷兩個(gè)value是否值相等。此處引入工具underscore
github:https://github.com/jashkenas/underscore
文檔:http://underscorejs.org/

總結(jié)

代碼量不多,也沒有對每個(gè)方法進(jìn)行說明,但是非常適合準(zhǔn)備入手自定義組件同行們。提供了一些組件開發(fā)的思路,有很多時(shí)候組件配合使用更為便捷。
demo的代碼已上傳至github,以便參考學(xué)習(xí)。
github:https://github.com/DevilLeven/select_tip

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

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

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