vue自定義組件總結(jié)

組件系統(tǒng)是Vue.js其中一個重要的概念溜在,它提供了一種抽象硬毕,讓我們可以使用獨立可復(fù)用的小組件來構(gòu)建大型應(yīng)用,任意類型的應(yīng)用界面都可以抽象為一個組件樹考蕾。

一耸携、四個核心組成

1、props 2辕翰、自定義事件 event 3、插槽及作用域插槽 slot 4狈谊、組件方法 method喜命。
任何組件均離不開以上4點,我們在開發(fā)過程中河劝,以這4點入手壁榕,封裝我們想要的組件。

以element-ui table組件為例

Table Attributes 指的是 props
props data 顯示的數(shù)據(jù)

Table Events 指的是 自定義事件
自定義事件 selection-change 當(dāng)選擇項發(fā)生變化時會觸發(fā)該事件

Table Slot 插槽
append 插入至表格最后一行之后的內(nèi)容赎瞎,如果需要對表格的內(nèi)容進行無限滾動操作牌里,可能需要用到這個 slot。若表格有合計行务甥,該 slot 會位于合計行之上牡辽。

Table-column Scoped Slot 插槽及作用域插槽 slot
Table-column 是 el-table-column組件,有一個默認插槽 自定義列的內(nèi)容敞临,參數(shù)為 { row, column, $index }

我們通常這樣使用

<el-table-column
    fixed="right"
    label="操作"
    width="100">
      <template slot-scope="scope">
        <el-button @click="handleClick(scope.row)" type="text" size="small">查看</el-button>
        <el-button type="text" size="small">編輯</el-button>
      </template>
</el-table-column>

slot-scope="scope" 父組件通過scope訪問子組件作用域态辛。
Table Methods 指的是 組件方法
組件方法 clearSelection 用于多選表格,清空用戶的選擇 挺尿。 組件方法是通過 添加ref 索引奏黑,獲取組件實例后調(diào)用炊邦。this.$refs.組件ref標(biāo)識.組件方法

以上是組件核心概念。

二熟史、組件注冊

1馁害、組件名
組件名應(yīng)該始終是多個單詞的,根組件 App 除外

這樣做可以避免跟現(xiàn)有的以及未來的 HTML 元素相沖突蹂匹,因為所有的 HTML 元素名稱都是單個單詞的碘菜。

單文件組件的文件名應(yīng)該要么始終是單詞大寫開頭 (PascalCase),要么始終是橫線連接 (kebab-case)

混用文件命名方式有的時候會導(dǎo)致大小寫不敏感的文件系統(tǒng)的問題怒详,這也是橫線連接命名同樣完全可取的原因

使用 kebab-case
當(dāng)使用 kebab-case (短橫線分隔命名) 定義一個組件時炉媒,你也必須在引用這個自定義元素時使用 kebab-case,例如 <my-component-name>

Vue.component('my-component-name', { /* ... */ })

使用 PascalCase
當(dāng)使用 PascalCase (駝峰式命名) 定義一個組件時昆烁,你在引用這個自定義元素時兩種命名法都可以使用吊骤。也就是說 <my-component-name> 和 <MyComponentName> 都是可接受的。注意静尼,盡管如此白粉,直接在 DOM (即非字符串的模板) 中使用時只有 kebab-case 是有效的

Vue.component('MyComponentName', { /* ... */ })

2、全局注冊
以上方法都屬于全局注冊, 也就是說它們在注冊之后可以用在任何新創(chuàng)建的 Vue 根實例 (new Vue) 的模板中, 比如

HTML

<div id="app">
  <component-a></component-a>
  <component-b></component-b>
  <component-c></component-c>
</div>

JS

Vue.component('component-a', { /* ... */ })
Vue.component('component-b', { /* ... */ })
Vue.component('component-c', { /* ... */ })
 
 
new Vue({ el: '#app' })

在所有子組件中也是如此鼠渺,也就是說這三個組件在各自內(nèi)部也都可以相互使用.

3鸭巴、局部注冊

如果不需要全局注冊,或者是讓組件使用在其它組件內(nèi)拦盹,可以用選項對象的 components 屬性實現(xiàn)局部注冊, 這里不做詳述鹃祖。

三、父子組件通信

在vue組件通信中其中最常見通信方式就是父子組件之中的通信普舆,而父子組件的設(shè)定方式在不同情況下又各有不同恬口。最常見的就是父組件為控制組件子組件為視圖組件。父組件傳遞數(shù)據(jù)給子組件使用沼侣,遇到業(yè)務(wù)邏輯操作時子組件觸發(fā)父組件的自定義事件祖能。無論哪種組織方式父子組件的通信方式都是大同小異

父組件到子組件通訊

父組件到子組件的通訊主要為:子組件接受使用父組件的數(shù)據(jù),這里的數(shù)據(jù)包括屬性和方法(String, Number, Boolean, Object, Array, Function)蛾洛。vue提倡單項數(shù)據(jù)流养铸,因此在通常情況下都是父組件傳遞數(shù)據(jù)給子組件使用,子組件觸發(fā)父組件的事件轧膘,并傳遞給父組件所需要的參數(shù)

通過 props 傳遞數(shù)據(jù) (推薦)

父子通訊中最常見的數(shù)據(jù)傳遞方式就是通過props傳遞數(shù)據(jù)钞螟,就好像方法的傳參一樣,父組件調(diào)用子組件并傳入數(shù)據(jù)谎碍,子組件接受到父組件傳遞的數(shù)據(jù)進行驗證使用

props 可以是數(shù)組或?qū)ο笊冈玻糜诮邮諄碜愿附M件的數(shù)據(jù)。props 可以是簡單的數(shù)組椿浓,或者使用對象作為替代太援,對象允許配置高級選項闽晦,如類型檢測、自定義校驗和設(shè)置默認值

prop 的定義應(yīng)該盡量詳細提岔,至少需要指定其類型

<!-- 父組件 -->
<template>
    <div>
        <my-child :parentMessage="parentMessage"></my-child>
    </div>
</template>
 
<script>
    import MyChild from '@components/common/MyChild'
 
    export default {
        components: {
            MyChild
        },
        data() {
            return {
                parentMessage: "我是來自父組件的消息"
            }
        }
    }
</script>
 
<!-- 子組件 -->
<template>
    <div>
        <span>{{ parentMessage }}</span>
    </div>
</template>
 
<script>
    export default {
        props: {
            parentMessage: {
                type: String,
                default: '默認顯示的信息'
                // require: true // 必填
            }
        }
    }
</script>
子組件到父組件通訊

子組件到父組件的通訊主要為父組件如何接受子組件之中的數(shù)據(jù)仙蛉。這里的數(shù)據(jù)包括屬性和方法(String, Number, Boolean, Object, Array, Function)

通過 $emit 傳遞父組件數(shù)據(jù) (推薦)

與父組件到子組件通訊中的$on配套使用,可以向父組件中觸發(fā)的方法傳遞參數(shù)供父組件使用

<!-- 父組件 -->
<template>
    <div>
        <my-child @childEvent="parentMethod"></my-child>
    </div>
</template>
 
<script>
    import MyChild from '@components/common/MyChild'
 
    export default {
        components: {
            MyChild
        },
        data() {
            return {
                parentMessage: '我是來自父組件的消息'
            }
        },
        methods: {
            parentMethod({ name, age }) {
                console.log(this.parentMessage, name, age)
            }
        }
    }
</script>
 
 
<!-- 子組件 -->
<template>
    <div>
        <h3>子組件</h3>
    </div>
</template>
 
<script>
    export default {
        mounted() {
            this.$emit('childEvent', { name: 'zhangsan', age:  10 })
        }
    }
</script>
不推薦的通信方式

this.parent this.children
this.$refs

四碱蒙、兄弟組件通信

1荠瘪、vuex
Vuex 是一個專為 Vue.js 應(yīng)用程序開發(fā)的狀態(tài)管理模式。它采用集中式存儲管理應(yīng)用的所有組件的狀態(tài)赛惩,它是響應(yīng)式的哀墓,狀態(tài)發(fā)生變化,組件會更新喷兼。

vuex實現(xiàn)兄弟組件通信非常簡單篮绰,組件A引用vuex數(shù)據(jù),組件B通過方法改變vuex數(shù)據(jù)季惯,vuex狀態(tài)是響應(yīng)式的吠各,數(shù)據(jù)放生變化,組件A會更新勉抓。

2贾漏、eventBus又稱為事件總線
在vue中可以使用eventBus來作為溝通橋梁, 就像是所有組件共用相同的事件中心,可以向該中心注冊發(fā)送事件或接收事件藕筋, 所有組件都可以通知其他組件纵散。

初始化

首先需要創(chuàng)建一個事件總線并將其導(dǎo)出, 以便其他模塊可以使用或者監(jiān)聽它。

我們在src/components/目錄下新建文件bus.js隐圾。

import Vue from 'vue'
export default new Vue()

發(fā)送事件

假設(shè)你有兩個兄弟組件: ComA和ComB困食,ComA發(fā)送消息給ComB。

ComA這樣

<template>
    <div>
        <button @click="sendMsg">給組件B發(fā)送消息</button> 
    </div>
</template>
 
<script>
import bus from './bus'
 
export default {
    name: 'comA',
    data () {
        return {
             
        }
    },
     
    methods: {
        sendMsg() {
            bus.$emit('fromA', {
                phone: 13800138000
            })
        }
    }
}
</script>

很顯然翎承,ComA中使用bus.$emit(事件名,數(shù)據(jù));向事件中心注冊發(fā)送事件。

接收事件

ComB接受ComA發(fā)送過來的消息符匾。

<template>
    <div>
        <p>{{fromA}}</p>
    </div>
</template>
 
<script>
import bus from './bus'
 
export default {
    name: 'comB',
    data () {
        return {
            fromA: '',
        }
    },
    mounted() {
        bus.$on('fromA', param => {
            this.fromA = param.phone;
        })
    }
}
</script>

于是叨咖,當(dāng)ComA發(fā)送了一個手機號碼phone給ComB時,comB就會接收并顯示啊胶。

父組件

在父組件中調(diào)用ComA和ComB兩個兄弟組件甸各。

<template>
  <div>
    <comA></comA>
    <comB></comB>
  </div>
</template>
 
<script>
import ComA from './ComA.vue'
import ComB from './ComB.vue'
 
export default {
    components: {
       ComA,
       ComB
    },
}
</script>

五、多層級組件通訊

1焰坪、vuex
2趣倾、eventBus
3、provide / inject

provide 和 inject 主要在開發(fā)高階插件/組件庫時使用某饰。并不推薦用于普通應(yīng)用程序代碼中儒恋。

這對選項需要一起使用善绎,以允許一個祖先組件向其所有子孫后代注入一個依賴,不論組件層次有多深诫尽,并在其上下游關(guān)系成立的時間里始終生效禀酱。

// 父級組件提供 'foo'
var Provider = {
  provide: {
    foo: 'bar'
  },
  // ...
}
 
// 子組件注入 'foo'
var Child = {
  inject: ['foo'],
  created () {
    console.log(this.foo) // => "bar"
  }
  // ...
}

六、作用域插槽

有時讓插槽內(nèi)容能夠訪問子組件中才有的數(shù)據(jù)是很有用的牧嫉。例如剂跟,設(shè)想一個帶有如下模板的 <current-user> 組件:

<span>
  <slot>{{ user.lastName }}</slot>
</span>

我們可能想換掉備用內(nèi)容,用名而非姓來顯示酣藻。如下:

<current-user>
  {{ user.firstName }}
</current-user>

然而上述代碼不會正常工作曹洽,因為只有 <current-user> 組件可以訪問到 user 而我們提供的內(nèi)容是在父級渲染的。

為了讓 user 在父級的插槽內(nèi)容中可用辽剧,我們可以將 user 作為 <slot> 元素的一個 attribute 綁定上去:

<span>
  <slot v-bind:user="user">
    {{ user.lastName }}
  </slot>
</span>

綁定在 <slot> 元素上的 attribute 被稱為插槽 prop∷拖現(xiàn)在在父級作用域中,我們可以使用帶值的 v-slot 來定義我們提供的插槽 prop 的名字:

<current-user>
  <template v-slot:default="slotProps">
    {{ slotProps.user.firstName }}
  </template>
</current-user>

在這個例子中抖仅,我們選擇將包含所有插槽 prop 的對象命名為 slotProps坊夫,但你也可以使用任意你喜歡的名字。

七撤卢、組件的方法

組件方法环凿,就是我們寫組件時,在methods選項里邊定義的一些方法放吩,他通常是對數(shù)據(jù)的CURD智听。
element-ui我們常用的有

this.refs[formName].resetFields(); form表單重置 this.refs.[treeName].getCheckedKeys() tree 返回目前被選中的節(jié)點的 key 所組成的數(shù)組

八、vue 語法糖

1渡紫、v-model
v-model可以實現(xiàn)數(shù)據(jù)雙向的綁定到推,自動為組件添加了props 名為 value 和 自定義事件 名為 input。

<input type="text" v-model="name">

實際上,上面的代碼是下面代碼的語法糖惕澎。

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

自定義組件的 v-model

一個組件上的 v-model 默認會利用名為 value 的 prop 和名為 input 的事件莉测,但是像單選框、復(fù)選框等類型的輸入控件可能會將 value attribute 用于不同的目的唧喉。model 選項可以用來避免這樣的沖突:

Vue.component('base-checkbox', {
  model: {
    prop: 'checked',
    event: 'change'
  },
  props: {
    checked: Boolean
  },
  template: `
    <input
      type="checkbox"
      v-bind:checked="checked"
      v-on:change="$emit('change', $event.target.checked)"
    >
  `
})

現(xiàn)在在這個組件上使用 v-model 的時候:

<base-checkbox v-model="lovingVue"></base-checkbox>

這里的 lovingVue 的值將會傳入這個名為 checked 的 prop捣卤。同時當(dāng) <base-checkbox> 觸發(fā)一個 change 事件并附帶一個新的值的時候,這個 lovingVue 的 property 將會被更新八孝。
2董朝、.sync 修飾符
在有些情況下,我們可能需要對一個 prop 進行“雙向綁定”干跛。不幸的是子姜,真正的雙向綁定會帶來維護上的問題,因為子組件可以變更父組件楼入,且在父組件和子組件都沒有明顯的變更來源哥捕。

這也是為什么我們推薦以 update:myPropName 的模式觸發(fā)事件取而代之牧抽。舉個例子,在一個包含 title prop 的假設(shè)的組件中扭弧,我們可以用以下方法表達對其賦新值的意圖:

this.$emit('update:title', newTitle)

然后父組件可以監(jiān)聽那個事件并根據(jù)需要更新一個本地的數(shù)據(jù) property阎姥。例如:

<text-document
  v-bind:title="doc.title"
  v-on:update:title="doc.title = $event"
></text-document>

為了方便起見,我們?yōu)檫@種模式提供一個縮寫鸽捻,即 .sync 修飾符:

<text-document v-bind:title.sync="doc.title"></text-document>

九呼巴、組件選項推薦順序

<script>
  export default {
    el: '#app', // 只在由 new 創(chuàng)建的實例中遵守。
     
    // 全局感知
    name: 'name', // 組件name
    parent: VueInstance, // 指定父實例
 
    // 組件類型
    functional: false, // 沒有data 實例 沒有上下文
 
    // 模板修改器
    delimiters: ['${', '}'], // 分隔符變成了 ES6 模板字符串的風(fēng)格
    comments: false, // 當(dāng)設(shè)為 true 時御蒲,將會保留且渲染模板中的 HTML 注釋衣赶。默認行為是舍棄它們。
 
    // 模板依賴
    components: {}, // 子組件
    directives: {}, // 自定義指令
    filters: {}, // 自定義過濾器
 
    // 組合
    extends: CompA, // 擴展另一個組件 和 mixins 類似
    mixins: [tableEvents], // 混入選項對象厚满, 混入實例對象可以像正常的實例對象一樣
 
    // 接口
    inheritAttrs: true,
    model: { // 自定義組件在使用 v-model 時定制 prop 和 event
      prop: 'checked',
      event: 'change'
    },
    propsData: { // 只用于 new 創(chuàng)建的實例中府瞄。   創(chuàng)建實例時傳遞 props。
 
    },
 
    // 本地狀態(tài)
    data: () => ({ // 本地狀態(tài)
 
    }),
    computed: { // 計算屬性
 
    },
 
    // 事件 生命周期鉤子
    watch: {
 
    },
 
    // 生命周期鉤子
    beforeCreate() {
 
    },
    created() {
 
    },
    beforeMount() {
 
    },
    mounted() {
 
    },
    beforeUpdate() {
 
    },
    updated() {
 
    },
    activated() {
 
    },
    deactivated() {
 
    },
    beforeDestroy() {
 
    },
    destroyed() {
 
    },
 
    // 非響應(yīng)式的屬性 (不依賴響應(yīng)系統(tǒng)的實例屬性)
    methods() {
 
    },
 
    // 渲染 (組件輸出的聲明式描述)
    template: '<div>demo</div>', // 渲染模板
    render: function (createElement) {
      return createElement(
        'h' + this.level,   // 標(biāo)簽名稱
        this.$slots.default // 子節(jié)點數(shù)組
      )
    },
    renderError (h, err) { // 只在開發(fā)者環(huán)境下工作碘箍。
      return h('pre', { style: { color: 'red' }}, err.stack)
    }
     
  }
</script>

十遵馆、組件樣式推薦使用CSS 作用域

<style scoped>
    
</style>
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市丰榴,隨后出現(xiàn)的幾起案子货邓,更是在濱河造成了極大的恐慌,老刑警劉巖四濒,帶你破解...
    沈念sama閱讀 222,104評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件换况,死亡現(xiàn)場離奇詭異,居然都是意外死亡盗蟆,警方通過查閱死者的電腦和手機戈二,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,816評論 3 399
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來喳资,“玉大人觉吭,你說我怎么就攤上這事∑偷耍” “怎么了鲜滩?”我有些...
    開封第一講書人閱讀 168,697評論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長宏赘。 經(jīng)常有香客問我,道長黎侈,這世上最難降的妖魔是什么察署? 我笑而不...
    開封第一講書人閱讀 59,836評論 1 298
  • 正文 為了忘掉前任,我火速辦了婚禮峻汉,結(jié)果婚禮上贴汪,老公的妹妹穿的比我還像新娘脐往。我一直安慰自己,他們只是感情好扳埂,可當(dāng)我...
    茶點故事閱讀 68,851評論 6 397
  • 文/花漫 我一把揭開白布业簿。 她就那樣靜靜地躺著,像睡著了一般阳懂。 火紅的嫁衣襯著肌膚如雪梅尤。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,441評論 1 310
  • 那天岩调,我揣著相機與錄音巷燥,去河邊找鬼。 笑死号枕,一個胖子當(dāng)著我的面吹牛缰揪,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播葱淳,決...
    沈念sama閱讀 40,992評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼钝腺,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了赞厕?” 一聲冷哼從身側(cè)響起艳狐,我...
    開封第一講書人閱讀 39,899評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎坑傅,沒想到半個月后僵驰,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,457評論 1 318
  • 正文 獨居荒郊野嶺守林人離奇死亡唁毒,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,529評論 3 341
  • 正文 我和宋清朗相戀三年蒜茴,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片浆西。...
    茶點故事閱讀 40,664評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡粉私,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出近零,到底是詐尸還是另有隱情诺核,我是刑警寧澤,帶...
    沈念sama閱讀 36,346評論 5 350
  • 正文 年R本政府宣布久信,位于F島的核電站窖杀,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏裙士。R本人自食惡果不足惜入客,卻給世界環(huán)境...
    茶點故事閱讀 42,025評論 3 334
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧桌硫,春花似錦夭咬、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,511評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至膀钠,卻和暖如春掏湾,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背托修。 一陣腳步聲響...
    開封第一講書人閱讀 33,611評論 1 272
  • 我被黑心中介騙來泰國打工忘巧, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人睦刃。 一個月前我還...
    沈念sama閱讀 49,081評論 3 377
  • 正文 我出身青樓砚嘴,卻偏偏與公主長得像,于是被迫代替她去往敵國和親涩拙。 傳聞我的和親對象是個殘疾皇子际长,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,675評論 2 359

推薦閱讀更多精彩內(nèi)容