一、 vue組件間傳值
1. 父組件向子組件進行傳值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>
<!-- 定義一個子組件傳值的方法 -->
<input type="button" value="點擊觸發(fā)" @click="childClick">
</div>
</template>
<script>
export default {
data () {
return {
childValue: '我是子組件的數(shù)據(jù)'
}
},
methods: {
childClick () {
// childByValue是在父組件on監(jiān)聽的方法
// 第二個參數(shù)this.childValue是需要傳的值
this.$emit('childByValue', this.childValue)
}
}
}
</script>
父組件代碼:
<template>
<div>
父組件:
<span>{{name}}</span>
<br>
<br>
<!-- 引入子組件 定義一個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 元素;如果用在子組件上,引用就指向組件實例
- $parent / $children:訪問父 / 子實例
兩種都是直接得到組件實例,使用后可以直接調(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, ''獲取父組件的實例對象")
},
methods: {
sayName () {
window.alert('我是子組件的方法');
}
}
}
// 父組件
<template>
<child />
</template>
<script>
export default
{
data() {
return {
parentName: '我是父組件的數(shù)據(jù)"
}
},
created() {
console.log(this.$children, ''獲取子組件的實例對象')
},
methods: {
parentFun() {
console.log("我的父組件的方法")
}
}
}
</script>
4. 總線機制bus
這種方法通過一個空的Vue實例作為中央事件總線(事件中心),用它來觸發(fā)事件和監(jiān)聽事件,巧妙而輕量地實現(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="點擊觸發(fā)" @click="elementByValue">
</div>
</template>
<script>
// 引入公共的bus,來做為中間傳達的工具
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="點擊觸發(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 除外)。當一個組件沒有聲明任何 prop 時,這里會包含所有父作用域的屬性 (class 和 style 除外),并且可以通過v-bind="$attrs"
傳入內(nèi)部組件。通常配合interitAttrs
選項一起使用。 -
$listeners
:包含了父作用域中的 (不含 .native 修飾器的) v-on 事件監(jiān)聽器。它可以通過v-on="$listeners"
傳入內(nèi)部組件。
接下來我們看個跨級通信($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, // 不會顯示在子組件的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, // 不會顯示在子組件的dom元素上
props: { boo: String }, // boo作為props屬性綁定
created() {
console.log(this.$attrs); // { "coo": "CSS", "doo": "Vue", "title": "前端工匠" }
}
};
</script>
- inheritAttrs為
false
的情況:不會顯示在子組件的dom元素上 - inheritAttrs為
true
的情況(默認):會顯示在子組件的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>
這樣綁定原生事件很麻煩,每一個原生事件都需要綁定,但用v-on="$listeners"就會省事很多。
<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在需要使用這個數(shù)據(jù)的子輩組件或者孫輩等下級組件中注入數(shù)據(jù);
- 使用場景:由于vue有$parent屬性可以讓子組件訪問父組件。但孫組件想要訪問祖先組件就比較困難。通過provide/inject可以輕松實現(xiàn)跨級訪問父組件的數(shù)據(jù)。
父組件定義:
<script>
export default {
// 父組件通過provide將自己的數(shù)據(jù)以對象形式傳出去
provide(){
return {
parentValue:"我是父組件的值啊" // 也可以從data中拿值
}
}
};
</script>
子孫組件接受方式:
<script>
export default {
// inject:["parentValue"], // 使用一個注入的值作為數(shù)據(jù)入口:
inject:{
// 使用一個默認值使其變成可選項
parentValue: { // 健名
from: 'parentValue', // 來源
default: '我是默認值' // 默認值
}
}
}
</script>
注意:provide并不是響應式的,當子組件inject的時候已經(jīng)丟失了響應式功能
要希望整個數(shù)據(jù)都是響應式的—provide提供一個函數(shù)。
函數(shù)內(nèi)部返回一個響應式的數(shù)據(jù)。此時整條數(shù)據(jù)的響應式的狀態(tài)并不會丟失。
//父組件傳值的定義個回調(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>
//子組件用計算屬性取值,watch監(jiān)聽
export default {
inject: ['getParentVal'],
computed: {
actConfig() {
this.parentValue= this.getParentVal().parentValue // 獲取初始時父組件傳過來的值
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 也可以訪問組件實例;provide
/inject
;$attrs
/$listeners
-
兄弟通信:
Bus
;Vuex
文章來源:http://www.zghlxwxcb.cn/news/detail-610879.html -
跨級通信:
Bus
;Vuex
;provide
/inject
、$attrs
/$listeners
文章來源地址http://www.zghlxwxcb.cn/news/detail-610879.html
到了這里,關(guān)于vue組件間傳值的六種方法的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!