vue組件間傳值的6種方法總結(jié)
一、 vue組件間傳值
1. 父組件向子組件進(jìn)行傳值 props
父組件代碼:
<template> <div> 父組件: <input type="text" v-model="name"> <br> <br> <!-- 引入子組件 --> <child :inputName="name"></child> </div> </template> <script> import child from './child' export default { components: { child }, data () { return { name: '' } } } </script>
子組件代碼:
<template> <div> 子組件: <span>{{ inputName }}</span> </div> </template> <script> export default { // 接受父組件的值 props: { inputName: String } } </script>
頁面顯示:
2. 子組件向父組件傳值 $emit
子組件代碼:
<template> <div> 子組件: <span>{{ childValue }}</span> <!-- 定義一個(gè)子組件傳值的方法 --> <input type="button" value="點(diǎn)擊觸發(fā)" @click="childClick"> </div> </template> <script> export default { data () { return { childValue: '我是子組件的數(shù)據(jù)' } }, methods: { childClick () { // childByValue是在父組件on監(jiān)聽的方法 // 第二個(gè)參數(shù)this.childValue是需要傳的值 this.$emit('childByValue', this.childValue) } } } </script>
父組件代碼:
<template> <div> 父組件: <span>{{name}}</span> <br> <br> <!-- 引入子組件 定義一個(gè)on的方法(簡寫@)監(jiān)聽子組件的狀態(tài)--> <child @childByValue="childByValue"></child> </div> </template> <script> import child from './child' export default { components: { child }, data () { return { name: '' } }, methods: { childByValue (childValue) { // childValue就是子組件傳過來的值 this.name = childValue } } } </script>
頁面顯示:
父子組件傳值原理:父子組件的關(guān)系可以總結(jié)為 prop 向下傳遞,事件向上傳遞。父組件通過 prop 給子組件下發(fā)數(shù)據(jù),子組件通過事件給父組件發(fā)送消息,如下圖所示:
3. $parent / $children && ref
- ref:如果在普通的 DOM 元素上使用,引用指向的就是 DOM 元素;如果用在子組件上,引用就指向組件實(shí)例
- $parent / $children:訪問父 / 子實(shí)例
兩種都是直接得到組件實(shí)例,使用后可以直接調(diào)用組件的方法或訪問數(shù)據(jù)。
ref
使用代碼:
// component-a 子組件 export default { data () { return { title: 'Vue.js' } }, methods: { sayHello () { window.alert('Hello'); } } } // 父組件 <template> <component-a ref="comA"></component-a> </template> <script> export default { mounted () { const comA = this.$refs.comA; console.log(comA.title); // Vue.js comA.sayHello(); // 彈窗 } } </script>
$parent/$children
使用代碼:
// child 子組件 export default { data () { return { name: '我是子組件的數(shù)據(jù)' } }, created() { console.log(this.$parent, ''獲取父組件的實(shí)例對象") }, methods: { sayName () { window.alert('我是子組件的方法'); } } } // 父組件 <template> <child /> </template> <script> export default { data() { return { parentName: '我是父組件的數(shù)據(jù)" } }, created() { console.log(this.$children, ''獲取子組件的實(shí)例對象') }, methods: { parentFun() { console.log("我的父組件的方法") } } } </script>
4. 總線機(jī)制 bus
這種方法通過一個(gè)空的Vue實(shí)例作為中央事件總線(事件中心),用它來觸發(fā)事件和監(jiān)聽事件,巧妙而輕量地實(shí)現(xiàn)了任何組件間的通信,包括父子、兄弟、跨級。
公共bus.js:
//bus.js import Vue from 'vue' export default new Vue()
組件A代碼:
<template> <div> A組件: <span>{{elementValue}}</span> <input type="button" value="點(diǎn)擊觸發(fā)" @click="elementByValue"> </div> </template> <script> // 引入公共的bus,來做為中間傳達(dá)的工具 import Bus from './bus.js' export default { data () { return { elementValue: 4 } }, methods: { elementByValue() { // 使用$emit來傳遞參數(shù) Bus.$emit('sendVal', this.elementValue) } } } </script>
組件B代碼:
<template> <div> B組件: <input type="button" value="點(diǎn)擊觸發(fā)" @click="getData"> <span>{{num}}</span> </div> </template> <script> import Bus from './bus.js' export default { data () { return { num: 0 } }, mounted() { var vm = this // 用$on事件來接收參數(shù) Bus.$on('sendVal', (data) => { console.log(data) vm.num= data }) }, methods: { getData() { this.num++ } }, destroyed () { // 取消對bus事件的監(jiān)聽 // 事件訂閱是通過Bus對象完成的 與組件無關(guān) Bus.$off('sendVal') } } </script>
4. vuex
PMT知識庫地址:vuex
5. $attrs / $listeners
- $attrs:包含了父作用域中不被 prop 所識別 (且獲取) 的屬性 (class 和 style 除外)。當(dāng)一個(gè)組件沒有聲明任何 prop 時(shí),這里會(huì)包含所有父作用域的屬性 (class 和 style 除外),并且可以通過 v-bind="$attrs" 傳入內(nèi)部組件。通常配合 interitAttrs 選項(xiàng)一起使用。
- $listeners:包含了父作用域中的 (不含 .native 修飾器的) v-on 事件監(jiān)聽器。它可以通過 v-on="$listeners" 傳入內(nèi)部組件。
接下來我們看個(gè)跨級通信( $attrs
)的例子:
index.vue:
//index.vue <template> <div> <h2>浪里行舟</h2> <child-com1 :foo="foo" :boo="boo" :coo="coo" :doo="doo" title="前端工匠" ></child-com1> </div> </template> <script> import childCom1 from "./childCom1.vue"; export default { components: { childCom1 }, data() { return { foo: "javascript", boo: "Html", coo: "Css", doo: "Vue" }; }, methods: { outputMsg() { console.log('我是父組件的方法'); } } }; </script>
childCom1.vue:
//childCom1.vue <template> <div> <p>foo:{{ foo }}</p> <p>childCom1的$attrs:{{ $attrs }}</p> <child-com2 v-bind="$attrs"></child-com2> </div> </template> <script> import childCom2 from "./childCom2.vue"; export default { components: { childCom2 }, inheritAttrs: false, // 不會(huì)顯示在子組件的dom元素上 props: { foo: String }, // foo作為props屬性綁定 created() { console.log(this.$attrs); // { "boo": "Html", "coo": "CSS", "doo": "Vue", "title": "前端工匠" } } }; </script>
childCom2.vue:
//childCom2.vue <template> <div> <p>boo:{{ boo }}</p> <p>childCom2的$attrs:{{ $attrs }}</p> </div> </template> <script> export default { inheritAttrs: false, // 不會(huì)顯示在子組件的dom元素上 props: { boo: String }, // boo作為props屬性綁定 created() { console.log(this.$attrs); // { "coo": "CSS", "doo": "Vue", "title": "前端工匠" } } }; </script>
inheritAttrs為 false
的情況:不會(huì)顯示在子組件的dom元素上
inheritAttrs為 true
的情況(默認(rèn)):會(huì)顯示在子組件的dom元素上
$listeners
例子:
// 父組件 <template> <my-input required placeholder class="theme-dark" @focue="onFocus" @input="onInput" > </my-input> </template> <script> import MyInput from './child' export default { components: { MyInput }, methods: { onFocus (e) { console.log(e.target.value) }, onInput (e) { console.log(e.target.value) } } } </script>
// 子組件 <template> <div> <input type="text" v-bind="$attrs" class="form-control" @focus="$emit('focus', $event)" @input="$emit('input', $event)" /> </div> </template> <script> export default { name: 'MyInput', inheritAttrs: false } </script>
這樣綁定原生事件很麻煩,每一個(gè)原生事件都需要綁定,但用v-on="$listeners"就會(huì)省事很多。
<input type="text" v-bind="$attrs" class="form-control" + v-on="$listeners" - @focus="$emit('focus', $event)" - @input="$emit('input', $event)" />
6. provide / inject
- 成對出現(xiàn):provide和inject是成對出現(xiàn)的;
- 作用:用于父組件向子孫組件傳遞數(shù)據(jù);
- 使用方法:provide在父組件中返回要傳給下級的數(shù)據(jù),inject在需要使用這個(gè)數(shù)據(jù)的子輩組件或者孫輩等下級組件中注入數(shù)據(jù);
- 使用場景:由于vue有$parent屬性可以讓子組件訪問父組件。但孫組件想要訪問祖先組件就比較困難。通過provide/inject可以輕松實(shí)現(xiàn)跨級訪問父組件的數(shù)據(jù)。
父組件定義:
<script> export default { // 父組件通過provide將自己的數(shù)據(jù)以對象形式傳出去 provide(){ return { parentValue:"我是父組件的值啊" // 也可以從data中拿值 } } }; </script>
子孫組件接受方式:
<script> export default { // inject:["parentValue"], // 使用一個(gè)注入的值作為數(shù)據(jù)入口: inject:{ // 使用一個(gè)默認(rèn)值使其變成可選項(xiàng) parentValue: { // 健名 from: 'parentValue', // 來源 default: '我是默認(rèn)值' // 默認(rèn)值 } } } </script>
注意:provide并不是響應(yīng)式的,當(dāng)子組件inject的時(shí)候已經(jīng)丟失了響應(yīng)式功能
要希望整個(gè)數(shù)據(jù)都是響應(yīng)式的—provide提供一個(gè)函數(shù)。
函數(shù)內(nèi)部返回一個(gè)響應(yīng)式的數(shù)據(jù)。此時(shí)整條數(shù)據(jù)的響應(yīng)式的狀態(tài)并不會(huì)丟失。
//父組件傳值的定義個(gè)回調(diào)函數(shù) <template> <div> <a-input v-model="parentValue"/> </div> </template> <script> export default { data() { return { parentValue: "我是父組件的值啊" }; }, provide() { return { getParentVal: () => ({ parentValue: this.parentValue }) } } }; </script>
//子組件用計(jì)算屬性取值,watch監(jiān)聽 export default { inject: ['getParentVal'], computed: { actConfig() { this.parentValue= this.getParentVal().parentValue // 獲取初始時(shí)父組件傳過來的值 return this.getParentVal(); }, }, watch: { actConfig(val) { console.log("組件監(jiān)聽到的值", val); this.parentValue= val.parentValue }, }, data() { return { parentValue: '' } }, }; </script>
總結(jié)
常見使用場景可以分為三類:
- 父子通信: 父向子傳遞數(shù)據(jù)是通過
props
,子向父是通過 events($emit
);通過父鏈 / 子鏈也可以通信($parent
/$children
);ref 也可以訪問組件實(shí)例;provide
/inject
;$attrs
/$listeners
- 兄弟通信:
Bus
;Vuex
- 跨級通信:
Bus
;Vuex
;provide
/inject
、$attrs
/$listeners
到此這篇關(guān)于vue組件間傳值的6種方法總結(jié)的文章就介紹到這了,更多相關(guān)vue組件間傳值內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
利用vue-router實(shí)現(xiàn)二級菜單內(nèi)容轉(zhuǎn)換
這篇文章主要介紹了如何利用vue-router實(shí)現(xiàn)二級菜單內(nèi)容轉(zhuǎn)換,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-11-11vue實(shí)現(xiàn)頁面自適應(yīng)的常用4種方法
前端頁面自適應(yīng)有很多方法可以實(shí)現(xiàn),本文小編將為大家詳細(xì)介紹四種常用的方法,并提供相應(yīng)的代碼示例,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2023-10-10如何解決sass-loader和node-sass版本沖突的問題
這篇文章主要介紹了如何解決sass-loader和node-sass版本沖突的問題,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-04-04vue-cli 3.0 引入mint-ui報(bào)錯(cuò)問題及解決
這篇文章主要介紹了vue-cli 3.0 引入mint-ui報(bào)錯(cuò)問題及解決方案,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-05-05vue+springboot用戶注銷功能實(shí)現(xiàn)代碼
這篇文章主要介紹了vue+springboot用戶注銷功能,本文通過示例代碼給大家介紹的非常詳細(xì),感興趣的朋友跟隨小編一起看看吧2024-05-05vue截圖轉(zhuǎn)base64轉(zhuǎn)文件File異步獲取方式
這篇文章主要介紹了vue截圖轉(zhuǎn)base64轉(zhuǎn)文件File異步獲取方式,具有很好的參考價(jià)值,希望對大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-03-03Vue3+TypeScript實(shí)現(xiàn)遞歸菜單組件的完整實(shí)例
Vue.js中的遞歸組件是一個(gè)可以調(diào)用自己的組件,遞歸組件一般用于博客上顯示評論,形菜單或者嵌套菜單,文章主要給大家介紹了關(guān)于Vue3+TypeScript實(shí)現(xiàn)遞歸菜單組件的相關(guān)資料,需要的朋友可以參考下2021-08-08