一、非父子通信-event bus 事件總線
1.作用
非父子組件之間,進行簡易消息傳遞。(復雜場景→ Vuex)
2.步驟
創建一個都能訪問的事件總線 (空Vue實例)
import Vue from 'vue' const Bus = new Vue() export default Bus
A組件(接受方),監聽Bus的 $on事件
created () { ? Bus.$on('sendMsg', (msg) => { ? ? this.msg = msg ? }) }
B組件(發送方),觸發Bus的$emit事件
Bus.$emit('sendMsg', '這是一個消息')
3.代碼示例
EventBus.jsimport Vue from 'vue'
const Bus ?= ?new Vue()
export default Bus
BaseA.vue(接受方)<template><div class="base-a">我是A組件(接收方)<p>{{msg}}</p> ?</div>
</template>
?
<script>
import Bus from '../utils/EventBus'
export default {data() {return {msg: '',}},
}
</script>
?
<style scoped>
.base-a {width: 200px;height: 200px;border: 3px solid #000;border-radius: 3px;margin: 10px;
}
</style>
BaseB.vue(發送方)<template><div class="base-b"><div>我是B組件(發布方)</div><button>發送消息</button></div>
</template>
?
<script>
import Bus from '../utils/EventBus'
export default {
}
</script>
?
<style scoped>
.base-b {width: 200px;height: 200px;border: 3px solid #000;border-radius: 3px;margin: 10px;
}
</style>
App.vue<template><div class="app"><BaseA></BaseA><BaseB></BaseB> </div>
</template>
?
<script>
import BaseA from './components/BaseA.vue'
import BaseB from './components/BaseB.vue'
export default {components:{BaseA,BaseB}
}
</script>
?
<style>
?
</style>
4.總結
1.非父子組件傳值借助什么?
2.什么是事件總線
3.發送方應該調用事件總線的哪個方法
4.接收方應該調用事件總線的哪個方法
5.一個組件發送數據,可不可以被多個組件接收
?
二、非父子通信-provide&inject
1.作用
跨層級共享數據
2.場景
3.語法
父組件 provide提供數據
export default {provide () {return {// 普通類型【非響應式】color: this.color, // 復雜類型【響應式】userInfo: this.userInfo, }}
}
2.子/孫組件 inject獲取數據
export default {inject: ['color','userInfo'],created () {console.log(this.color, this.userInfo)}
}
4.注意
provide提供的簡單類型的數據不是響應式的,復雜類型數據是響應式。(推薦提供復雜類型數據)
子/孫組件通過inject獲取的數據,不能在自身組件內修改
三、v-model原理
?
1.原理:
v-model本質上是一個語法糖。例如應用在輸入框上,就是value屬性 和 input事件 的合寫
<template><div id="app" ><input v-model="msg" type="text"><input :value="msg" @input="msg = $event.target.value" type="text"></div>
</template>
?
2.作用:
提供數據的雙向綁定
數據變,視圖跟著變 :value
視圖變,數據跟著變 @input
3.注意
$event 用于在模板中,獲取事件的形參
4.代碼示例
<template><div class="app"><input type="text" /><br /> <input type="text" /></div>
</template><script>
export default {data() {return {msg1: '',msg2: '',}},
}
</script>
<style>
</style>
5.v-model使用在其他表單元素上的原理
不同的表單元素, v-model在底層的處理機制是不一樣的。比如給checkbox使用v-model
底層處理的是 checked屬性和change事件。
不過咱們只需要掌握應用在文本框上的原理即可
?
四、.sync修飾符(父子組件的雙向綁定)
1.作用
可以實現 子組件 與 父組件數據 的 雙向綁定,簡化代碼
簡單理解:子組件可以修改父組件傳過來的props值
2.場景
封裝彈框類的基礎組件, visible屬性 true顯示 false隱藏
3.本質
.sync修飾符 就是 :屬性名 和 @update:屬性名 合寫
?
父組件
isShow.sync ?=> :isShow="isShow" @update:isShow="isShow=$event"
4.案例:
5、代碼
父組件
<template><div class="app"><button @click="openDialog">退出按鈕</button><!-- isShow.sync => :isShow="isShow" @update:isShow="isShow=$event" --><BaseDialog :isShow.sync="isShow"></BaseDialog></div>
</template><script>
import BaseDialog from './components/BaseDialog.vue'
export default {data() {return {isShow: false,}},methods: {openDialog() {this.isShow = true// console.log(document.querySelectorAll('.box')); },},components: {BaseDialog,},
}
</script><style>
</style>
子組件
<template><div class="base-dialog-wrap" v-show="isShow"><div class="base-dialog"><div class="title"><h3>溫馨提示:</h3><button class="close" @click="closeDialog">x</button></div><div class="content"><p>你確認要退出本系統么?</p></div><div class="footer"><button>確認</button><button>取消</button></div></div></div>
</template><script>
export default {props: {isShow: Boolean,},methods:{closeDialog(){this.$emit('update:isShow',false)}}
}
</script><style scoped>
.base-dialog-wrap {width: 300px;height: 200px;box-shadow: 2px 2px 2px 2px #ccc;position: fixed;left: 50%;top: 50%;transform: translate(-50%, -50%);padding: 0 10px;
}
.base-dialog .title {display: flex;justify-content: space-between;align-items: center;border-bottom: 2px solid #000;
}
.base-dialog .content {margin-top: 38px;
}
.base-dialog .title .close {width: 20px;height: 20px;cursor: pointer;line-height: 10px;
}
.footer {display: flex;justify-content: flex-end;margin-top: 26px;
}
.footer button {width: 80px;height: 40px;
}
.footer button:nth-child(1) {margin-right: 10px;cursor: pointer;
}
</style>
五、ref和$refs
?
1.作用
????????利用ref 和 $refs 可以用于 獲取 dom 元素 或 組件實例
2.特點:
????????查找范圍 → 當前組件內(更精確穩定)
3.語法
????????1.給要獲取的盒子添加ref屬性
<div ref="chartRef">我是渲染圖表的容器</div>
????????2.獲取時通過 $refs獲取 this.$refs.chartRef 獲取
mounted () {console.log(this.$refs.chartRef)
}
4.代碼示例
父級代碼
<template><div class="app"><BaseChart></BaseChart></div>
</template><script>
import BaseChart from './components/BaseChart.vue'
export default {components:{BaseChart}
}
</script><style>
</style>
子代碼
<template><div class="base-chart-box" ref="baseChartBox">子組件</div>
</template><script>
// yarn add echarts 或者 npm i echarts
import * as echarts from 'echarts'export default {mounted() {// 基于準備好的dom,初始化echarts實例var myChart = echarts.init(document.querySelect('.base-chart-box'))// 繪制圖表myChart.setOption({title: {text: 'ECharts 入門示例',},tooltip: {},xAxis: {data: ['襯衫', '羊毛衫', '雪紡衫', '褲子', '高跟鞋', '襪子'],},yAxis: {},series: [{name: '銷量',type: 'bar',data: [5, 20, 36, 10, 10, 20],},],})},
}
</script><style scoped>
.base-chart-box {width: 400px;height: 300px;border: 3px solid #000;border-radius: 6px;
}
</style>
六、異步更新 & $nextTick
1、 $nextTick:是等 DOM更新后,才會觸發執行此方法里的函數體
語法: this.$nextTick(函數體)
this.$nextTick(() => {this.$refs.inp.focus()
})
注意:$nextTick 內的函數體 一定是箭頭函數,這樣才能讓函數內部的this指向Vue實例
2、代碼示例
<template><div class="app"><div v-if="isShowEdit"><input type="text" v-model="editValue" ref="inp" /><button>確認</button></div><div v-else><span>{{ title }}</span><button @click="editFn">編輯</button></div></div>
</template><script>
export default {data() {return {title: '大標題',isShowEdit: false,editValue: '',}},methods: {editFn() {// 1.顯示文本框this.isShowEdit = true// 2.讓文本框聚焦 (會等dom更新完之后 立馬執行nextTick中的回調函數)// this.$nextTick(() => {// console.log(this.$refs.inp)// this.$refs.inp.focus()// })setTimeout(() => {this.$refs.inp.focus()}, 0)},},
}
</script><style>
</style>
?
?
?
?
?
?