Vue自定義組件以及組件通信的幾種方式


本帖子來源:小賢筆記

功能

組件 (Component) 是 Vue.js 最強大的功能之一。組件可以擴展 HTML 元素,封裝可重用的代碼。在較高層面上,組件是自定義元素,Vue.js 的編譯器為它添加特殊功能。在有些情況下,組件也可以表現為用 is 特性進行了擴展的原生 HTML 元素。所有的 Vue 組件同時也都是 Vue 的實例,所以可接受相同的選項對象 (除了一些根級特有的選項) 並提供相同的生命周期鈎子

組件注冊

組件名

組件名應該始終是多個單詞的,根組件 App 除外

這樣做可以避免跟現有的以及未來的 HTML 元素相沖突,因為所有的 HTML 元素名稱都是單個單詞的

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

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

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

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

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

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

全局注冊

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

  • HTML

<divid="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' })

在所有子組件中也是如此,也就是說這三個組件在各自內部也都可以相互使用

 

局部注冊

如果不需要全局注冊,或者是讓組件使用在其它組件內,可以用選項對象的 components 屬性實現局部注冊, 這里不做詳述

ps:具體參考博客vue由淺入深組件的其他內容

父子組件通信

: 本節引用歲月如同馬匹 - 簡書

在vue組件通信中其中最常見通信方式就是父子組件之中的通性,而父子組件的設定方式在不同情況下又各有不同。最常見的就是父組件為控制組件子組件為視圖組件。父組件傳遞數據給子組件使用,遇到業務邏輯操作時子組件觸發父組件的自定義事件。無論哪種組織方式父子組件的通信方式都是大同小異

父組件到子組件通訊

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

通過 props 傳遞數據 (推薦)

父子通訊中最常見的數據傳遞方式就是通過props傳遞數據,就好像方法的傳參一樣,父組件調用子組件並傳入數據,子組件接受到父組件傳遞的數據進行驗證使用

props 可以是數組或對象,用於接收來自父組件的數據。props 可以是簡單的數組,或者使用對象作為替代,對象允許配置高級選項,如類型檢測、自定義校驗和設置默認值

prop 的定義應該盡量詳細,至少需要指定其類型

<!-- 父組件 -->

<template>

<div>

<my-child:parentMessage="parentMessage"></my-child>

</div>

</template>

 

<script>

import MyChild from'@components/common/MyChild'

 

exportdefault {

components: {

            MyChild

        },

        data() {

return {

parentMessage: "我是來自父組件的消息"

            }

        }

    }

</script>

<!-- 子組件 -->

<template>

<div>

<span>{{ parentMessage }}</span>

</div>

</template>

 

<script>

exportdefault {

props: {

parentMessage: {

type: String,

default: '默認顯示的信息'

// require: true // 必填

            }

        }

    }

</script>

//父組件顯示:我是來自父組件的消息。

 

通過 $on 傳遞父組件方法

通過$on傳遞父組件方法是組件通信中常用的方法傳遞方式。它可以與通過props傳遞方法達到相同的效果。相比於props傳遞function,它更加的直觀和顯示的表現出了調用關系

<!-- 父組件 -->

<template>

<div>

<my-child @childEvent="parentMethod"></my-child>

</div>

</template>

 

<script>

import MyChild from'@components/common/MyChild'

 

exportdefault {

components: {

            MyChild,

        },

        data() {

return {

parentMessage: '我是來自父組件的消息',

            }

        },

methods: {

            parentMethod() {

                alert(this.parentMessage)

            }

        }

    }

</script>

<!-- 子組件 -->

<template>

<div>

<h3>子組件</h3>

</div>

</template>

 

<script>

exportdefault{

        mounted() {

this.$emit('childEvent')

        }

    }

</script>

//先彈出一個窗口顯示  我是來自父組件的消息,然后父組件顯示文本是子組件

獲取父組件然后使用父組件中的數據(不推薦)

准確來說這種方式並不屬於數據的傳遞而是一種主動的查找。父組件並沒有主動的傳遞數據給子組件,而是子組件通過與父組件的關聯關系,獲取了父組件的數據
該方法雖然能實現獲取父組件中的數據但是不推薦這種方式,因為vue提倡單向數據流,只有父組件交給子組件的數據子組件才有使用的權限,不允許子組件私自獲取父組件的數據進行使用。在父與子的關系中子應當是處於一種被動關系

// 此處的this為子組件實例

this.$parent

子組件到父組件通訊

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

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

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

<!-- 父組件 -->

<template>

<div>

<my-child @childEvent="parentMethod"></my-child>

</div>

</template>

 

<script>

import MyChild from'@components/common/MyChild'

 

exportdefault {

components: {

            MyChild

        },

        data() {

return {

parentMessage: '我是來自父組件的消息'

            }

        },

methods: {

            parentMethod({ name, age }) {

console.log(this.parentMessage, name, age)

            }

        }

    }

</script>

<!-- 子組件 -->

<template>

<div>

<h3>子組件</h3>

</div>

</template>

 

<script>

exportdefault {

        mounted() {

this.$emit('childEvent', { name: 'zhangsan', age:  10 })

        }

    }

</script>

//父組件顯示文本為子組件,控制台輸出:我是來自父組件的消息  zhangsan 10

refs 獲取

可以通過在子組件添加ref屬性,然后可以通過ref屬性名稱獲取到子組件的實例。准確來說這種方式和 this.$parent 一樣並不屬於數據的傳遞而是一種主動的查找。

盡量避免使用這種方式。因為在父子組件通信的過程中。父組件是處於高位是擁有控制權,而子組件在多數情況下應該為純視圖組件,只負責視圖的展示和自身視圖的邏輯操作。對外交互的權利應該由父組件來控制。所以應當由父組件傳遞視圖數據給子組件,子組件負責展示。而子組件的對外交互通過$emit觸發父組件中相應的方法,再由父組件處理相應邏輯

<!-- 父組件 -->

<template>

<div>

<my-child ref="child"></my-child>

</div>

</template>

 

<script>

import MyChild from'@components/common/MyChild'

 

exportdefault {

components: {

            MyChild

        },

        mounted() {

console.log(this.$refs['child'].getData());

        }

    }

</script>

<!-- 子組件 -->

<script>

exportdefault {

methods: {

            getData() {

// do something...

            }

        }

    }

</script>

//子組件在getdata函數中傳輸的會顯示在父組件,並且會返回getdata函數

組件樣式修改

參考文章CSS 作用域

如果你希望 scoped 樣式中的一個選擇器能夠作用得“更深”,例如影響子組件,你可以使用 >>> 操作符:

<style scoped>

.a>>>.b { /* ... */ }

</style>

上述代碼將會編譯成:

.a[data-v-f3f3eg9].b { /* ... */ }

有些像 Sass 之類的預處理器無法正確解析 >>>。這種情況下你可以使用 /deep/ 操作符取而代之——這是一個 >>> 的別名,同樣可以正常工作

<style scoped>

    .a /deep/ .b { /* ... */ }

</style>

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM