一 子傳父(對$emit的理解)
作用 子組件可以使用 $emit 觸發父組件的自定義事件。 語法 vm.$emit( event, arg ) //觸發父級實例上的事件
對於vue.js中的this.emit的理解: 舉例 : this.emit(‘increment1’,”加參數”); 其實它的作用就是觸發自定義函數。此外,可以子組件傳參數給父組件 綜述,即子組件調用父組件的方法並傳遞數據 具體應用如下
子組件
<template> <button @click="emitEvent">點擊我</button> </template> <script> export default { data() { return { msg: "我是子組件中的數據" } }, methods: { emitEvent(){ this.$emit('my-event', this.msg) //通過按鈕的點擊事件觸發方法,然后用$emit觸發一個my-event的自定義方法,傳遞this.msg數據。 } } } </script>
父組件
<template>
<div id="app">
<child-a @my-event="getMyEvent"></child-a>
<!--父組件中通過監測my-event事件執行一個方法,然后取到子組件中傳遞過來的值-->
</div>
</template>
<script>
import ChildA from './components/child.vue'
export default {
components: {
ChildA
},
methods: {
getMyEvent(msg){ // msg是個形參value,實質是接收的子組件傳來數據的參數
console.log('接收的數據--------->'+msg)//接收的數據--------->我是子組件中的數據
}
}
}
</script>
二 父傳子
父組件可以使用 props 把數據傳給子組件。
子組件通過props拿到父組件傳來的數據。
父組件
<template>
<div id="app">
<div class="transac-del">
<div>
<span class="sub_title">交易詳情</span>
</div>
<p>
// v-if的原因是調接口回來數據是個異步操作,因此給個條件判斷,數據不為null的時候才傳數據給子組件,以免數據一開始拿到的是空對象
<transacDet v-if="deiMap" :DeiMap = 'deiMap' /> // 子組件,並且在數據模型中定義deiMap:null
</p>
</div>
</div>
</template>
子組件
props: { DeiMap:{ type:Object, required: true } }, mounted () { // 子組件通過props拿到父組件傳來的數據,是個對象,直接this.DeiMap可以使用數據 console.log('obj==',this.DeiMap) },
prop的單向數據流
vue官方:
所有的 prop 都使得其父子 prop 之間形成了一個單向下行綁定:父級 prop 的更新會向下流動到子組件中,但是反過來則不行。這樣會防止從子組件意外變更父級組件的狀態,從而導致你的應用的數據流向難以理解。
額外的,每次父級組件發生變更時,子組件中所有的 prop 都將會刷新為最新的值。這意味着你不應該在一個子組件內部改變 prop。如果你這樣做了,Vue 會在瀏覽器的控制台中發出警告。
如下
可以這樣理解
父傳子 prop是單向數據流
如果在子組件中已經接受了值,這時在子組件內直接再次改變這個值,會出現問題,vue不允許這樣操作,vue規定了props是單向數據流傳值
解決方法
在data中定義一個第三方的變量接收數據(即克隆數據),這個第三方變量即可更改
同時,在mounted階段賦值給這個變量
三 $refs的使用
$refs作用1 => 在DOM元素上使用$refs可以迅速進行dom定位 $refs作用2 => 在組件上使用ref屬性,可以通過$refs實現對子組件操作 即$refs是父組件調用子組件的方法,可以傳遞數據 首先給子組件做標記。demo :<firstchild ref="one"></firstchild> 然后在父組件中,通過this.$refs.one就可以訪問了這個自組件了,包括訪問自組件的data里面的數據,調用它的函數 注意1 ref 被用來給元素或子組件注冊引用信息。引用信息將會注冊在父組件的 $refs 對象上。如果在普通的 DOM 元素上使用,引用指向的就是 DOM 元素; 如果用在子組件上,引用就指向組件實例 當 v-for 用於元素或組件的時候,引用信息將是包含 DOM 節點或組件實例的數組 注意2 $refs不能在created生命周期中使用 因為在組件創建時候 該ref還沒有綁定元素 它是非響應的,所以應該避免在模板或計算屬性中使用 $refs ,它僅僅是一個直接操作子組件的應急方案 當使用v-for的元素或組件,引用信息$refs將是包含DOM節點的或組件實例的數組,類似$children的使用
父組件
<template>
<div id="app">
<child-a ref="child"></child-a>
<!--用ref給子組件起個名字-->
<button @click="getMyEvent">點擊父組件</button>
</div>
</template>
<script>
import ChildA from './components/child.vue'
export default {
components: {
ChildA
},
data() {
return {
msg: "我是父組件中的數據"
}
},
methods: {
getMyEvent(){
this.$refs.child.emitEvent(this.msg);
//調用子組件的方法,child是上邊ref起的名字,emitEvent是子組件的方法。
}
}
}
</script>
子組件
<template> <button>點擊我</button> </template> <script> export default { methods: { emitEvent(msg){ console.log('接收的數據--------->'+msg)//接收的數據--------->我是父組件中的數據 } } } </script>
四 $on的使用
vue中使用 $emit(eventName) 觸發事件,使用 $on(eventName) 監聽事件
$emit(eventName) 觸發當前實例上的事件,附加參數都會傳給監聽器回調。
$on(eventName) 監聽當前實例上的自定義事件。事件可以由 vm.$emit 觸發。回調函數會接收所有傳入事件觸發函數的額外參數。
e.g1 本頁面單個事件
<template>
<section>
<h1>left</h1>
<el-button type="primary" @click="isClick">點擊</el-button>
</section>
</template>
<script>
export default {
methods: {
isClick() {
this.$emit('isLeft', '點擊事件!');
}
},
mounted() {
this.$on('isLeft', (val) => {
console.log(val);
});
}
}
</script>
以上代碼,是通過按鈕的點擊事件,然后this.$emit傳遞事件,然后this.$on捕獲本頁面的事件

e.g2 本頁面多個事件
<template>
<section>
<h1>left</h1>
<el-button type="primary" @click="isClick">點擊</el-button>
<el-button type="primary" @click="isClickOther">點擊</el-button>
</section>
</template>
<script>
export default {
methods: {
isClick() {
this.$emit('isLeft', '點擊事件!');
},
isClickOther() {
this.$emit('isRight', ['點擊1', '點擊2']);
}
},
mounted() {
this.$on('isLeft', (val) => {
console.log(val);
});
this.$on('isRight', (...val) => {
console.log(val);
});
this.$on(['isLeft', 'isRight'], () => {
console.log(666);
});
}
}
</script>
以上例子,是本頁面的兩個點擊事件,可以同時監聽兩個事件,也可以同時傳多個參數
e.g3 非父子組件傳值(通過bus傳值)
子組件1
<template>
<section>
<h1>left</h1>
<el-button type="primary" @click="isClick">點擊</el-button>
</section>
</template>
<script>
import eventBus from '~/utils/eventBus';
export default {
methods: {
isClick() {
eventBus.$emit('isLeft', '點擊事件!');
}
}
}
</script>
子組件2
<template>
<section>
<h1>right</h1>
{{ name }}
</section>
</template>
<script>
import eventBus from '~/utils/eventBus';
export default {
data() {
return {
name: 'right默認值'
};
},
mounted() {
eventBus.$on('isLeft', (info) => {
this.name = info ;
});
}
}
</script>
父組件
<template>
<section>
<el-row>
<el-col :span="12">
<left/>
</el-col>
<el-col :span="12">
<right />
</el-col>
</el-row>
</section>
</template>
<script>
import left from '~/components/left'
import right from '~/components/right'
export default {
components: {
left,
right
}
}
</script>
以上例子就是 left組件傳值給bus,然后right組件監聽bus的isLest事件,當left組件觸發事件的時候,right組件就會觸發方法,替換頁面的值
總結
1.使用$emit傳遞事件
2.使用$on監聽事件
3.可以本頁面使用,也可以父子組件使用,也可以非關聯組件使用
五 $parent
vue 里 this.$parent 作用 $parent在子組件中調用父組件的方法或獲得其數據 this.$parent 可以訪問到父組件上所有的 data(){ 里的數據信息和生命周期方法,methods里的方法 } 如 this.$parent.List = []; 表示訪問到父組件中data的數據list數組 區分 1、ref為子組件指定一個索引名稱,通過索引來操作子組件; 2、this.$parent 可以直接訪問該組件的父實例或組件; 3、父組件也可以通過this.$children 訪問它所有的子組件, $parent和$children 可以遞歸向上或向下無線訪問, 直到根實例或最內層的組件。
六 $children
他返回的是一個組件集合,如果你能清楚的知道子組件的順序,你也可以使用下標來操作;
for(let i=0;i<this.$children.length;i++){ console.log(this.$children[i].children_data); this.$children[i].children_fun(); }
七 parent和children的案例
父組件index.vue
<template> <div> <testVue ref="childVue"></testVue> <br/><br/> <testVue2></testVue2> <br/><br/> <button @click="clickChild1">點擊訪問子組件</button> <br/><br/> <button @click="clickChild2">點擊訪問子組件2</button> </div> </template> <script> import testVue from './testVue' import testVue2 from './testVue2' export default { data(){ return { total: 0 } }, methods: { clickChild1(){ console.log(this.$refs.childVue.counter); }, clickChild2(){ console.log(this.$children[1].testval); } }, components: { testVue, testVue2 } } </script>
子組件1
<template> <div> <button @click="parentClick">點擊訪問父組件</button> </div> </template> <script> export default { data(){ return { counter: 0 } }, methods: { parentClick(){ console.log(this.$parent.total); } } } </script>
子組件2
<template> <div> </div> </template> <script> export default { data(){ return { testval: '2222' } } } </script>
