vue組件封裝指南

目錄

vue組件三要素

  1. props參數
  2. slot定製插槽
  3. event自定義事件

基本用法

在使用 vue-cli 建立的項目中,組件的建立很是方便,只須要新建一個 .vue 文件,而後在 template 中寫好 HTML 代碼,一個簡單的組件就完成了 一個完整的組件,除了 template 之外,還有 script和 stylecss

<template>
  <div class="headComponent">
    子組件{{{myData}}
  </div>
</template>

<script>
export default {
    props:['data','type'],
    inheritAttrs: false,
    data(){
        return{
            myData:'',
        }
    },
    mounted(){

    },
    methods:{
       
    }
}
</script>
<style scoped>

</style>
複製代碼

而後在其餘文件的 js 裏面引入並註冊,就能直接使用這個組件了html

import list from '../components/headComponent.vue'
複製代碼

1、props:數據父組件傳入子組件

父對子傳參,就須要用到 props,一般的 props 是這樣的:vue

props:['data','type']
複製代碼

可是通用組件的的應用場景比較複雜,對 props 傳遞的參數應該添加一些驗證規則,經常使用格式以下:ajax

props: {
    // 基礎類型檢測 (`null` 意思是任何類型均可以)
    propA: Number,
    // 多種類型
    propB: [String, Number],
    // 必傳且是字符串
    propC: {
      type: String,
      required: true
    },
    // 數字,有默認值
    propD: {
      type: Number,
      default: 100
    },
    // 數組/對象的默認值應當由一個工廠函數返回
    propE: {
      type: Object,
      default: function () {
        return { message: 'hello' }
      }
    },
    // 自定義驗證函數
    propF: {
      validator: function (value) {
        return value > 10
      }
    }
  }
複製代碼

對於經過 props 傳入的參數,不建議對其進行操做,由於會同時修改父組件裏面的數據 // vue2.5已經針對 props 作出優化,這個問題已經不存在了 若是必定須要有這樣的操做,能夠這麼寫:vue-router

let copyData = JSON.parse(JSON.stringify(this.data))
複製代碼

爲何不直接寫 let myData = this.data 呢? 由於直接賦值,對於對象和數組而言只是淺拷貝,指向的是同一個內存地址,其中一個改變另外一個也會改變。而經過 JSON顛倒轉換以後,實現了深拷貝,則能夠互不影響。vue-cli

2、子組件觸發父組件事件

在通用組件中,一般會須要有各類事件,好比複選框的 change 事件,或者組件中某個按鈕的 click 事件,有時子組件須要觸發一個事件,並傳遞給父組件數組

// 子組件方法:觸發父組件方法,並傳遞參數data到父組件
handleSubmit(data){
    this.$emit('submitToParent', data)
}
複製代碼
// 父組件調用子組件
<child-component @submitToParent="parentSubmit"></child-component>
... ...
// 父組件中被觸發的方法,接受到子組件傳來的參數
parentSubmit(data){
    // 父組件的邏輯處理
}
複製代碼

父組件中的邏輯要放在父組件處理,子組件基於父組件的數據作的邏輯放在子組件中處理; 這樣既下降了耦合性,也保證了各自的數據不被污染。bash

3、記得留一個 slot

一個通用組件,每每不可以完美的適應全部應用場景 因此在封裝組件的時候,只須要完成組件 80% 的功能,剩下的 20% 讓父組件經過 solt 解決session

上面是一個通用組件,在某些場景中,右側的按鈕是 「處理」 和 「委託」。在另外的場景中,按鈕須要換成 「查看」 或者 「刪除」 在封裝組件的時候,就不用寫按鈕,只須要在合適的位置留一個 slot,將按鈕的位置留出來,而後在父組件寫入按鈕函數

子組件
<div class="child-btn">
    <!-- 具名插槽 -->
    <slot name="button"></slot>
    <!-- 匿名插槽(每一個組件只能有一個) -->
    <slot><slot>
</div>

父組件
<child>
    <!-- 對應子組件中button的插槽 -->
    <button slot="button">slot按鈕</button>
</child>
複製代碼

開發通用組件的時候,只要不是獨立性很高的組件,建議都留一個 slot,即便還沒想好用來幹什麼。

再來個例子:

開發過程當中,經常須要在子組件內添加新的內容,這時候能夠在子組件內部留一個或者多個插口

而後在調用這個子組件的時候加入內容

添加的內容就會分發到對應的 slot 中

slot 中還能夠做爲一個做用域,在子組件中定義變量,而後在父組件中自定義渲染的方式 子組件:

父組件:

這個示例中,首先在子組件中添加 slot,並在子組件中定義了數組變量 navs 而後在父組件中以做用域 template 添加內容,其中 scope 是固有屬性,它的值對應一個臨時變量 props 而 props 將接收從父組件傳遞給子組件的參數 navs

關於slot的用法還可查看:juejin.im/post/5cc856…

4、Vuex:巧用但不要濫用

子組件向子組件傳遞數據

Vue 沒有直接子對子傳參的方法,建議將須要傳遞數據的子組件,都合併爲一個組件。若是必定須要子對子傳參,能夠先從傳到父組件,再傳到子組件。 父子組件之間是經過 props 和 自定義事件來傳參,非父子組件一般會採用 Vuex 傳參 Vuex設計初衷是用來管理組件狀態,也能夠用於複雜組件的參數傳遞

可是 Vuex 的雖然能夠用來傳參,但並不推薦;由於 Vuex 相似於一個全局變量,會一直佔用內存 在寫入數據龐大的 state 的時候,就會產生內存泄露(人是活的,不能由於事物有弊端就不使用,合理利用便可)。 Tips: 當頁面刷新的時候,Vuex 會初始化,同時也會丟失編輯過的數據 若是刷新頁面時須要保留數據,能夠經過 url 或者 sessionstorage 保存 id,而後 ajax 請求數據

5、組件的css:合理運用 scoped 控制樣式做用域

在編寫組件的時候,能夠在 style 標籤中添加 scoped,讓標籤中的樣式只對當前組件生效 可是一味的使用 scoped,確定會產生大量的重複代碼 因此在開發的時候,應該避免在組件中寫樣式 當全局樣式寫好以後,再針對每一個組件,經過 scoped 屬性添加組件樣式

6、動態組件

Vue 還能夠將多個子組件,都掛載在同一個位置,經過變量來切換組件,實現 tab 菜單這樣的效果

這樣的功能能夠經過路由 vue-router 實現,但路由更適合較大的組件,並且 url 會有相應的改變 Vue 自身保留的 元素,能夠將組件動態綁定到 is 特性上,從而很方便的實現動態組件切換
上例中,當 tabView 的值改變,component 就會渲染對應的組件,和路由的效果十分相似,可是地址欄並無發生改變,但這樣一來,每次切換組件都會從新渲染,沒法保留組件上的數據。這時可使用 ** keep-alive ** 將組件保留在內存中,避免從新渲染

7、遞歸組件

當組件擁有 name 屬性的時候,就能夠在它的模板內遞歸的調用本身,這在開發樹形組件的時候十分有效

上面是一個子組件,定義了 name 爲 simple03,而後在模板中調用自身,結合 v-for 實現遞歸 爲了防止出現死循環,在調用自身的時候,加入了 v-if 做爲斷定條件 父組件中調用的時候,須要經過 props 傳入一個 tree:

最終渲染結果:

其餘狀況

子組件改變父組件的數據

在vue2.0以後的版本中,不容許子組件直接改變父組件的數據,在1.0的版本中能夠這樣操做的,可是每每項目需求須要改變父組件的數據,那咱們如何變通呢? 當咱們把父元素的數據給子組件時,要傳一個非基礎類型,即傳遞對象or數組,子組件經過訪問對象中的屬性操做數據,由於對象和數組是傳引用,因此在子組件中修改的時候,父組件也會同步改變,以下:

// 父組件要props傳遞給子組件的數據
myData:{
    info:'父組件信息'
}

// 子組件
 <template id="tpl">
    <div>
        <button @click="change">change</button>
        <p>{{data.info}}</p>
    </div>
</template>
... 省略部分無關代碼 ...
props:['data'],
methods:{
    change(){
        this.data.info = 'change info'
    }
}
複製代碼

當子組件點擊change按鈕改變數據的時候,父組件也會同步改變

若是不想影響父組件的值,咱們也能夠用文章開頭講的JSON顛倒轉換的方式,在mounted方法中進行深拷貝,在data中初始化數據時用另外一個變量做爲承載,這樣才承載變量改變,就不會影響父組件該變量的值了。

參考博客: www.cnblogs.com/wisewrong/p… www.cnblogs.com/yesyes/p/66…

相關文章
相關標籤/搜索