目錄
組件通信
1、props 父組件--->子組件通信
- 父組件---屬性的方式傳值給子組件
- 子組件---props方式接收數據
<Son :datas="fData"></Son>
<script>
import Son from '@/components/son'
export default{
name:'Father',
components:{Son},
data(){
return{
fData:'我是父組件向子組件傳遞的值-props方式'
}
}
}
</script>
子組件props接受的參數名稱,要與父組件傳遞時定義的屬性名一致
<template>
<div>我是父組件的數據:{{fData}}</div>
<div @click=changeData>我是父組件傳遞修改后的數據:{{mydata}}</div>
</template>
<script>
export default{
name:'Son',
props:{
fData:{
type:String,
default:''
}
}
data(){
mydata:this.fatherData
},
methods:{
changeData(){
this.mydata += '改變數據'
}
},
}
</script>
- 注意:
- 子組件不能夠直接去修改父組件傳遞的值修改的:因為Vue的單向數據流機制,如果直接修改那父組件的值就被“污染”了。(props是單向綁定的(只讀屬性):當父組件的屬性變化時,將傳導給子組件,但是反過來不會)
報錯信息大概是:vue使用prop通信出錯:Avoid mutating a prop directly since the value will be overwritten whenever the parent
- 解決方案:可以在子組件內定義一個變量mydata去接收fData數據
- 參數傳遞類型不確定是可以這么寫:
props:{ fData:{ type:[String,Number], default:'' } }
- 子組件不能夠直接去修改父組件傳遞的值修改的:因為Vue的單向數據流機制,如果直接修改那父組件的值就被“污染”了。(props是單向綁定的(只讀屬性):當父組件的屬性變化時,將傳導給子組件,但是反過來不會)
2、$emit 子組件--->父組件傳遞
- 子組件綁定自定義事件
- $emit()第一個參數為:自定義的事件名稱,第二個參數為:需要傳遞的數據
- 使用 $emit() 觸發更改數據
子組件
<el-button @click="handleEmit">改變父組件</el-button>
<script>
export default{
name:'Son',
methods:{
handleEmit(){
this.$emit('triggerEmit','子組件的數據')
}
}
}
</script>
父組件(子組件發送的事件名稱,要和父組件接受的事件名稱一致)
<Son @triggerEmit="changeData"></Son>
<script>
import Son from '@/components/son'
export default{
name:'Father',
components:{Son},
methods:{
changeData(name){
console.log(name) // => 我是來自子組件的數據
}
}
}
</script>
$emit與props結合 兄弟組件傳值
- 父組件引入兩個子組件
- 父組件充當一個橋梁作用
父組件
<childA :myName="name"></ChildA>
<ChildB :myName="name" @changeName="editName"></ChildB>
export default{
data() {
return {
name: '數據你好'
}
},
methods: {
editName(name){
this.name = name
}
}
}
子組件B改變,接收數據
<p>姓名:{{ myName }}</p>
<button @click="changeName">修改姓名</button>
<script>
export default{
props: {
myName:String
},
methods: {
changeName() {
this.$emit('changeName', '新數據名稱')
}
}
}
</script>
子組件A接收數據
<p>姓名:{{ newName }}</p>
<script>
export default{
props: {
myName:String
}
}
</script>
3、bus(事件總線) 兄弟組件通信
非父子組件或更多層級間組件間傳值,在Vue中通過單獨的事件中心來管理組件間的傳值
-
創建一個公共的bus.js文件
-
暴露出Vue實例
-
傳遞數據方,通過一個事件觸發bus.$emit(方法名,傳遞的數據)
-
接收數據方,在生命周期函數中,通過bus.$on(方法名,[params])來監聽
-
銷毀事件,在接受數據方,通過bus.$off(方法名)銷毀之后無法監聽數據
import Vue from "vue"
const bus=new Vue()
export default bus
需要改變數據的組件中定義調用
<template>
<div>
<div>我是通信組件A</div>
<button @click="changeName">修改姓名</button>
</div>
</template>
<script>
import bus from "@/utils/Bus.js";
export default {
components: {},
data() {
return {};
},
mounted() {
console.log(bus);
},
methods: {
changeName() {
bus.$emit("editName", "數據集!");
},
},
};
</script>
<style lang='scss' scoped>
</style>
另外一個組件中同樣引入bus.js文件,通過$on監聽事件回調
<template>
<div>
<span>名稱:{{name}}</span>
<div>我是通信組件B</div>
</div>
</template>
<script>
import bus from "@/utils/Bus.js";
export default {
components: {},
data() {
return {name};
},
mounted() {
bus.$on("editName", (name) => {
this.name=name
console.log(name); //
});
},
methods: {},
};
</script>
<style lang='scss' scoped>
</style>
4、$parent、$children 直接訪問組件實例
- 子組件通過---> $parent 獲得父組件實例
- 父組件通過---> $children 獲得子組件實例數組
子組件---this.$parent可以獲取到父組件的方法、data的數據等,並可以直接使用和執行
<template>
<div>我是子組件</div>
</template>
<script>
export default{
name:"Son",
data(){
return{
sonTitle: '我是子組件的數據'
}
},
methods:{
sonHandle(){
console.log('我是子組件的方法')
}
},
created(){
console.log(this.$parent)
console.log(this.$parent.fatherTitle) // => 我是父組件的數據
this.$parent.fantherHandle() // => 我是父組件的方法
}
}
</script>
父組件 --- 獲取子組件實例的,並且獲取的實例是一個數組形式,this.$children[0]才可以獲取某個組件實例,並調用組件方法和數據
<template>
<div>
<Son>我是父組件</Son>
</div>
</template>
<script>
import Son from './son.vue'
export default{
name: 'father',
components:{
Son
},
data(){
return{
fatherTitle: '我是父組件的數據'
}
},
methods:{
fantherHandle(){
console.log('我是父組件的方法')
}
},
mounted(){
console.log(this.$children)
console.log(this.$children[0].sonTitle) // => 我是子組件的數據
this.$children[0].sonHandle() // => 我是子組件的方法
}
}
</script>
5、$refs
ref被用來給元素或子組件注冊引用信息。引用信息將會注冊在父組件的 $refs 對象上。
父組件使用 $refs 獲得組件實例
<template>
<div>
<Son ref="son"></Son>
</div>
</template>
<script>
import Son from './son.vue'
export default{
name: 'father',
components:{
Son
},
mounted(){
console.log(this.$refs.son) /*組件實例*/
}
}
</script>
6、provide/inject(提供/注入) 多組件或深層次組件通信
- 父組件使用 provide 注入數據
- 子組件使用 inject 使用數據
/*父組件*/
export default{
provide: {
return{
provideName: '販賣前端仔'
}
}
}
至此provideName這個變量可以提供給它其下的所有子組件,包括曾孫、孫子組件等,只需要使用 inject 就能獲取數據
/*子組件*/
export default{
inject: ['provideName'],
created () {
console.log(this.provideName) // => "販賣前端仔"
}
}
- 父組件不需要知道哪個組件使用它提供出去的數據
- 子附件不需要知道這個數據從哪里來
7、slot(slot-scope作用域插槽) 子元素-->父元素(類似於通信)
- 用作一個 (能被傳遞數據的)可重用模板,來代替已經渲染好的元素
- 在子組件中,只需將數據傳遞到插槽,就像你將 prop 傳遞給組件一樣
- 注意:父級插槽接收內容是最外側元素 ,必須要有屬性slot-scope
子元素
<template>
<div>
<div class="isSon">
<slot :info='arrList'></slot>
</div>
</div>
</template>
<script>
export default {
components: {},
data() {
return {arrList:[1,'aa','張三']};
},
mounted() {
},
methods: {
},
};
</script>
父元素
<template>
<div>
<SonG>
<span slot-scope="props">
<ul>
aa
<li v-for="item in props.info" :key="item">
{{item}}
</li>
</ul>
</span>
</SonG>
</div>
</template>
<script>
import SonG from '../components/SonG.vue'
export default {
components:{
SonG
},
data () {
return {
}
}
}
</script>
8、vuex狀態管理
- 相當於一個公共數據的倉庫
- 提供一些方法管理倉庫數據
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
},
mutations: {
},
actions: {
},
modules: {
}
})