vue3 組件通信

Vue3 組件通信和 Vue2 的區(qū)別:

  • 移出事件總線盔沫,使用mitt代替。
  • vuex換成了pinia构舟。
  • .sync優(yōu)化到了v-model里面了
  • $listeners所有的東西灰追,合并到$attrs中了。
  • $children被砍掉了狗超。

常見搭配形式

1. props

props是使用頻率最高的一種通信方式弹澎,常用與 :父 ? 子
父傳子:屬性值是非函數(shù)
子傳父:屬性值是函數(shù)努咐。

  • 父傳子(屬性值是非函數(shù))
<child :name="name"/>
let name = ref('zs')
// 子組件接收
defineProps(['name'])
  • 子傳父(屬性值是函數(shù))
// 父組件
<child :getName="getName" />
const getName= (value) => {
  console.log(value);
}

// 子組件
defineProps(['getName'])
<el-button @click="getName('我是子組件的值')">傳值給父組件</el-button>

2. 自定義事件

概述:自定義事件常用于:子 => 父苦蒿。

// 父組件
<child @send-name="getName" />

const getName = (v1, v2) => {
  console.log(v1, v2);
}

//子組件
<el-button @click="handleSend">傳值給父組件</el-button>

const $emits = defineEmits(['send-name'])

const handleSend = ()=>{
    $emits('send-name','參數(shù)1','參數(shù)2')
}

3. mitt

與消息訂閱與發(fā)布(pubsub)功能類似,可以實(shí)現(xiàn)任意組件間通信

安裝:npm i mitt

//utils/emitter.js

// 引入 mitt 
import mitt from "mitt";

// 創(chuàng)建 mitt
const emitter = mitt()

// 暴露 mitt
export default emitter
  • 發(fā)送事件
import emitter from "@/utils/emitter";
const handleSend = () => {
  emitter.emit('send-name', { name: '參數(shù)1' })
}
  • 監(jiān)聽事件
import emitter from "@/utils/emitter";
// 綁定事件
emitter.on('send-name', (obj) => {
  console.log(obj)
})

// 卸載
onUnmounted(()=>{
   emitter.off('send-name')
})
  • 示例
// 綁定事件
  emitter.on('abc',(value)=>{
    console.log('abc事件被觸發(fā)',value)
  })
  emitter.on('xyz',(value)=>{
    console.log('xyz事件被觸發(fā)',value)
  })

  setInterval(() => {
    // 觸發(fā)事件
    emitter.emit('abc',666)
    emitter.emit('xyz',777)
  }, 1000);

  setTimeout(() => {
    // 清理事件
    emitter.all.clear()
  }, 3000); 

4. v-model

實(shí)現(xiàn) 父?子 之間相互通信渗稍。

// 父組件
<child v-model="name" />
// v-modle 本質(zhì) 上面的是下面的簡寫
<child :modelValue="name" @update:model-value="name = $event" />

let name = ref('my name is zs')

// 子組件 child
<input type="text" :value="modelValue" @input="emit('update:model-value',$event.target.value)">

defineProps(['modelValue'])
const emit = defineEmits(['update:model-value'])
  • 綁定多個(gè)值
// 父組件
<child v-model:name1="name1" v-model:name2="name2" />
let name1 = ref('zs')
let name2 = ref('ls')

// 子組件
<el-button @click="handleChange">開始傳值</el-button>

defineProps(['name1', 'name2'])

const emit = defineEmits(['update:name1', 'update:name2'])

const handleChange = () => {
    emit('update:name1','zs1')
    emit('update:name2','ls1')
}

5. $attrs

$attrs用于實(shí)現(xiàn)當(dāng)前組件的父組件佩迟,向當(dāng)前組件的子組件通信(祖→孫)团滥。
$attrs是一個(gè)對(duì)象,包含所有父組件傳入的標(biāo)簽屬性报强。
$attrs會(huì)自動(dòng)排除props中聲明的屬性

// 父
<child :name1="name1" :name2="name2" :name3="name3" />
let name1 = ref('name1')
let name2 = ref('name2')
let name3 = ref('name3')
// 子
<son v-bind="$attrs" />
defineProps(['name1'])
// 孫
defineProps(['name2', 'name3'])

6. refs灸姊、parent

$refs用于 :父→子。 值為對(duì)象躺涝,包含所有被ref屬性標(biāo)識(shí)的DOM元素或組件實(shí)例厨钻。
$parent用于:子→父。 值為對(duì)象坚嗜,當(dāng)前組件的父組件實(shí)例對(duì)象夯膀。

  • ref 獲取子組件數(shù)據(jù)
// 父組件
<child ref="childRef" />

let childRef = ref()

const getChild = () => {
  console.log(childRef.value.age);
  console.log(childRef.value.name);
}

// 子組件
let name = ref('zs')
let age = ref(16)

defineExpose({ name, age })
  • parent 子傳父
// 父組件
let parentAge = ref(12)
const printName = () => {
  console.log('我是名稱');
}
defineExpose({ parentAge,hanshu: printName })

// 子組件
<button @click="getParent($parent)">年齡-1</button>

const getParent = (parent) => {
    parent.hanshu()
    parent.parentAge-=1
}

7. provide、inject

實(shí)現(xiàn)祖孫組件直接通信
在祖先組件中通過provide配置向后代組件提供數(shù)據(jù)
在后代組件中通過inject配置來聲明接收數(shù)據(jù)

// 祖組件
let name = ref('zs')
let age = ref(18)
const updateAge = () => {
  age.value += 1
}
provide('name', name)
provide('ageContent', { age, updateAge })

// 孫組件
let name = inject('name')
let { age, updateAge } = inject('ageContent')

setInterval(() => {
  updateAge()
}, 1000);

8. pinia

vue3 pinia

9. slot

  • 默認(rèn)插槽
// 父組件
<child title="默認(rèn)插槽">
   <ul>
       <li v-for="i in 10" :key="i">{{i}}</li>
   </ul>
</child>

// 子組件
<div class="child">
    <h3>{{title}}</h3>
    <slot></slot>
</div>
defineProps(['title'])
  • 具名插槽
// 父組件 v-slot: 可以簡寫成#
<child title="默認(rèn)插槽">
  <template #c1>
    我是c1內(nèi)容
  </template>
  <template v-slot:c2>
    我是c2內(nèi)容
  </template>
</child>

// 子組件
<div class="child">
    <h3>{{title}}</h3>
    <slot name='c1'></slot>
    <slot name='c2'></slot>
</div>
defineProps(['title'])
  • 作用域插槽

數(shù)據(jù)在組件的自身苍蔬,但根據(jù)數(shù)據(jù)生成的結(jié)構(gòu)需要組件的使用者來決定诱建。

// 父組件 
<div class="parent">
  <child v-slot="params">
    <ul>
      <li v-for="item in params.dataList" :key="item.age">{{item.name}}</li>
    </ul>
  </child>

  <child v-slot:default="params">
    <ol>
      <li v-for="item in params.dataList" :key="item.age">{{item.name}}</li>
    </ol>
  </child>

  <child #default="params">
    <dl>
      <dt>{{ params.title }}</dt>
      <dd v-for="item in params.dataList" :key="item.age">{{item.name}}</dd>
    </dl>
  </child>
</div>

// 子組件
<div class="child">
  <slot :dataList="dataList" title="作用域插槽"></slot>
</div>

<script setup>
 let dataList = reactive([
    { name: 'zs', age: 11 },
    { name: 'ls', age: 22 },
    { name: 'wu', age: 33 },
  ])
</script>

總結(jié)

  • props 父傳子,子傳父
  • 自定義事件 子傳父
  • mitt 任意組件通信
  • v-model 父傳子碟绑,子傳父
  • $attrs 父傳子俺猿,父傳孫,祖孫通信
  • $refs 父傳子
  • $pare 子傳父
  • provide格仲、inject 祖?zhèn)魍ㄐ?/li>
  • pinia 任意組件通信
  • slot 父傳子押袍,子傳父
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市凯肋,隨后出現(xiàn)的幾起案子谊惭,更是在濱河造成了極大的恐慌,老刑警劉巖侮东,帶你破解...
    沈念sama閱讀 206,311評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件圈盔,死亡現(xiàn)場離奇詭異,居然都是意外死亡悄雅,警方通過查閱死者的電腦和手機(jī)驱敲,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,339評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來宽闲,“玉大人众眨,你說我怎么就攤上這事∪菸埽” “怎么了围辙?”我有些...
    開封第一講書人閱讀 152,671評(píng)論 0 342
  • 文/不壞的土叔 我叫張陵,是天一觀的道長放案。 經(jīng)常有香客問我姚建,道長,這世上最難降的妖魔是什么吱殉? 我笑而不...
    開封第一講書人閱讀 55,252評(píng)論 1 279
  • 正文 為了忘掉前任掸冤,我火速辦了婚禮厘托,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘稿湿。我一直安慰自己铅匹,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,253評(píng)論 5 371
  • 文/花漫 我一把揭開白布饺藤。 她就那樣靜靜地躺著包斑,像睡著了一般。 火紅的嫁衣襯著肌膚如雪涕俗。 梳的紋絲不亂的頭發(fā)上罗丰,一...
    開封第一講書人閱讀 49,031評(píng)論 1 285
  • 那天,我揣著相機(jī)與錄音再姑,去河邊找鬼萌抵。 笑死,一個(gè)胖子當(dāng)著我的面吹牛元镀,可吹牛的內(nèi)容都是我干的绍填。 我是一名探鬼主播,決...
    沈念sama閱讀 38,340評(píng)論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼栖疑,長吁一口氣:“原來是場噩夢(mèng)啊……” “哼!你這毒婦竟也來了遇革?” 一聲冷哼從身側(cè)響起卿闹,我...
    開封第一講書人閱讀 36,973評(píng)論 0 259
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎澳淑,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體嫩海,經(jīng)...
    沈念sama閱讀 43,466評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡涣觉,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,937評(píng)論 2 323
  • 正文 我和宋清朗相戀三年膝宁,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片愚争。...
    茶點(diǎn)故事閱讀 38,039評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡诚撵,死狀恐怖缭裆,靈堂內(nèi)的尸體忽然破棺而出扑毡,到底是詐尸還是另有隱情芒篷,我是刑警寧澤盗胀,帶...
    沈念sama閱讀 33,701評(píng)論 4 323
  • 正文 年R本政府宣布忌栅,位于F島的核電站徘六,受9級(jí)特大地震影響内边,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜待锈,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,254評(píng)論 3 307
  • 文/蒙蒙 一漠其、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦辉懒、人聲如沸阳惹。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,259評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽莹汤。三九已至,卻和暖如春颠印,著一層夾襖步出監(jiān)牢的瞬間纲岭,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,485評(píng)論 1 262
  • 我被黑心中介騙來泰國打工线罕, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留止潮,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,497評(píng)論 2 354
  • 正文 我出身青樓钞楼,卻偏偏與公主長得像喇闸,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子询件,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,786評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容