Vue組件參數傳遞問題
組件中的data為什么是函數?
組件中的數據是保存在哪里呢?頂層的Vue實例中嗎?並不是的,組件無法訪問Vue實例中的data。即使可以訪問,如果所有組件的數據都在頂級Vue實例中,那么Vue中的data會十分的臃腫。組件中的數據應該由自己管理。
組件是一個單獨功能模塊的封裝,這個模塊有屬於自己的HTML模板,也應該有屬於自己的數據data,不過這個data是一個函數。這是為什么呢?
這是為了保證組件復用時,屬性之間的隔離。利用方法都會重新開辟內存空間的機制。當創建多個相同組件實例時,不同組件實例之間的data必須保證不被共享
父子組件通訊之props(父->子)
需求1:在頁面中,父組件請求得到的數據需要在子組件中展示。
需求2:子組件很多,每次創建都要向后他發送數據,在父組件中進行請求,將數據傳遞給子組件展示。
Vue中提供了props用於父組件向子組件中傳遞數據
在子組件中,使用props聲明需要從父級接收到的數據
props的值有兩種方式:
- 方式一:字符串數組,數組中的字符串就是傳遞時的屬性名稱。
- 方式二:對象,對象可以設置傳遞時的類型,也可以設置默認值等。
數組形式的傳遞
1、在父組件中創建數據
data() {
return {
userId: "rayfoo",
name:'rayfoo',
hobby: ['抽煙','喝酒','燙頭']
};
}
2、在子組件中創建props
props: ['name','hobby']
3、在子組件中使用屬性
<h2 v-text="name"></h2>
4、在父組件中導入並使用子組件
import News from "./views/home/news";
components: {
News
}
<News :name="name" />
對象形式的傳遞
對象參數的傳遞需要指定對象類數據類型、[默認值]、[是否必傳]等參數
支持的類型類型
- String
- Number
- Boolean
- Object
- Data
- Function
- Symbol
props:{
title:{
//數據類型 參數可以指定多個[String,Number,...]
type: String,
//默認值,在沒有引入傳遞參數時渲染
default: 'Message',
//是否為必傳參數
required: false
},
hobby:{
type: Array,
default: function(){
return ['抽煙','喝酒']
}
}
}
需要注意的時,當類型如果是Object或者Array,默認值必須是一個函數。
子組件向父組件傳遞數據
子組件中配置事件發送:
template:
<button @click="giveAdvice">我是一個小按鈕</button>
methods:
methods: {
giveAdvice: function(){
this.$emit('give-advice',this.title);
}
}
父組件中監聽
template:
<News :name="name" @give-advice="showAdvice" />
methods:
showAdvice: function (advice) {
alert(advice)
}
需要注意的是,事件如果傳遞的是駝峰式,需要使用下划線形式發射。具體的操作可以參考官方API
https://cn.vuejs.org/v2/api/#vm-emit
參數同步問題
如果父子間傳遞的參數需要實時的進行雙向綁定,該如何做?
如果修改了props中的值,父組件中的內容不會修改。Vue不推薦在子組件中直接修改props的值。
如果需要修改props中的值,可以在子組件中創建一個data或者computed副本
使用@input事件實現雙向綁定
子組件代碼:
1、在子組件中聲明props,由父組件傳遞。
2、創建props的副本,當props的副本
3、使用v-model綁定props副本的值
4、監聽控件的@input,當值發生改變,修改參數值,並且將值彈回父組件
<template>
<div name='chidren'>
<h1 v-text="title"></h1>
<p v-text="info"></p>
<input type="text" v-model="dparam" @input="valChange">
<button @click="giao">發射屬性到父組件</button>
</div>
</template>
<script>
export default {
name: 'chidren',
props: {
title: String,
info: String
},
data(){
return{
param: 'GIAO',
dparam: this.title
}
},
methods:{
giao: function(){
this.$emit('giao',this.param);
},
valChange: function(event){
let newVal = event.target.value;
this.param = newVal;
this.$emit('title-change',newVal);
}
}/*,
watch:{
dparam(oldVal,newVal){
this.param = newVal;
this.$emit('title-change',newVal);
}
}*/
}
</script>
<style>
</style>
父組件代碼
父組件中可以直接使用v-model來修改子組件中屬性
<template>
<div name="parent">
<h1 v-text="title"></h1>
<input type="text" v-model="title">
<Childred @giao="giao" @title-change="titleChange" :title="title" :info="info"></Childred>
</div>
</template>
<script>
import Childred from './Chidren';
export default {
name: 'parent',
data(){
return {
title: 'rayfoo',
info: '真帥'
}
},
methods:{
giao: function(param){
alert(param);
},
titleChange:function(newVal){
this.title = newVal;
}
},
components:{
Childred
}
}
</script>
<style>
</style>
如果數據類型不是String,可能要牽涉一些類型轉換問題。
使用watch進行子父組件雙向綁定
略。。。
父組件中取得子組件的對象
$children-不常用
上面的案例中我們已經成功的在父組件中取得子組件的屬性,也可以從子組件中拿到父組件的屬性,下面介紹一個更加簡單的操作形式-從父組件中拿到子組件對象。
在父組件中,可以使用:this.\(children[index].屬性名、this.\)children[index].方法名來獲取子組件內的屬性和方法,但是在開發過程中一般不會使用這樣的形式,因為其依賴下標,有很多的不確定性。
btnClick: function(){
console.log(this.$children[0].param);
this.$children[0].showInfo();
}
$refs-常用
可以在引用子組件的位置給子組件指定一個ref屬性,例如ref='aaa'
此時,this.\(refs.aaa就是子組件對象,就可以在父組件中使用this.\)refs.aaa來訪問子組件啦~
btnClick: function(){
console.log(this.$refs.child.param);
}
子組件中訪問父組件對象
$parent不常用
在子組件中可以直接使用$parent來訪問父組件中的內容,但是在子組件中頻繁父組件中的內容,會使得組件的耦合度非常的高,所以開發過程中不常用。
btnClick: function(){
console.log(this.$parent.title);
}
$root
使用$root可以獲取根組件中的內容
btnClick: function(){
console.log(this.$root.title);
}
