我說這是全網最全vue元件通訊方式,你沒意見吧?

十安發表於2022-04-23

父子元件通訊

prop
event
style和class
natvie修飾符
$listeners
v-model
sync修飾符
$parent和$children
$slots和$scopedSlots
ref    

跨元件通訊

Provide和Inject
router
vuex
store模式
eventbus

父子元件通訊

prop

最常見的元件通訊方式,由父元件向子元件傳遞。prop可接收一個陣列或物件

//子元件
<script>
export default {
  name: "Comp",
  //陣列方式 props:[....]
  // ↓ 物件方式
  props: {
    datas: {
      type: Object,
      default: () => {
        return {};
      }
     },
  }
</script>

event

子元件向父元件傳送通知,並傳遞引數

子元件

methods:{
    // 通過 $emit向父元件傳送一個通知
    handleEvent(){
      this.$emit('eventMsg', option)
    }
  }

父元件

methods:{
    // 監聽子元件定義的方法
    eventMsg(option){
      console.log(option);
    }
  }

style 和 class

父元件可以向子元件傳遞style 和 class ,style 和 class將合併到子元件根元素上

父元件


<template>
  <div id="app">
    <HelloWorld
      style="color:red"
      class="hello"
      msg="Welcome to Your Vue.js App"
    />
  </div>
</template>
​
<script>
import HelloWorld from "./components/HelloWorld.vue";
export default {
  components: {
    HelloWorld,
  },
};
</script>

子元件​


<template>
  <div class="world" style="text-align:center">
    <h1>{{msg}}</h1>
  </div>
</template>
​
<script>
export default {
  name: "HelloWorld",
  props: {
    msg: String,
  },
};
</script>

最終渲染結果


<div id="app">
  <div class="hello world" style="color:red; text-aling:center">
    <h1>Welcome to Your Vue.js App</h1>
  </div>
</div>

attribute

父元件在使用子元件時,在子元件上定義一些屬性,這些屬性將作用於子元件的根元素上,但是不包括style和class

父元件


 
<HelloWorld data-a="1" data-b="2" msg="Welcome to Your Vue.js App" />
 

子元件


<template>
 <div>
   <h1>{{msg}}</h1>
 </div>
</template>
​
<script>
export default {
 name: "HelloWorld",
 props: {
   msg: String,
 },
 created() {
   // 通過$attrs獲取父元件定義的 attribute
   console.log(this.$attrs); // {"data-a":"1","data-b":"2"}
 },
};
</script>

最終渲染結果


<div id="app">
  <div data-a="1" data-b="2">
    <h1>Welcome to Your Vue.js App</h1>
  </div>
</div>

Tip:子元件可以通過定義 inheritAttrs:false 來緊張 attribute 附著在子元件根元素上 但不影響通過 $attrs 獲取資料

natvie修飾符

在註冊事件時,父元件可以通過 navite 修飾符,將事件註冊到子元件根元素上

父元件


 
<template>
  <div id="app">
    <HelloWorld @click.native="handleClick" />
  </div>
</template>
​
<script>
import HelloWorld from "./components/HelloWorld.vue";
​
export default {
  components: {
    HelloWorld,
  },
  methods: {
    handleClick() {
      console.log(1);
    },
  },
};
</script>
 

子元件


 
<template>
  <div>
    <h1>Hello World</h1>
  </div>
</template>
 

最終渲染結果


<template>
 <div id="app">
   <h1>Hello World</h1>
 </div>
</template>
// 當點選app時。會觸發父元件定義的 handleClick 方法

$listeners

子元件可以通過 $listeners 獲取父元件傳遞過來的所有處理函式

v-model

父元件在使用子元件時,可以在子元件上繫結v-model,子元件通過定義model的prop和event還獲取父元件定義的值

父元件​
`

<Compn v-model="datas" />
`
子元件


 
<script>
export default {
  //分類篩選元件
  name: "sortFilter",
  //定義實現v-modal的屬性與事件
  model: {
    prop: "value",
    event: "change"
  },
  props: {
    //繫結的值
    value: {
      type: [String, Number],
      default: ""
    }
   },
   created() {
    console.log(this.value)
  },
    
</script>
 

sync 修飾符

和 v-model類似,用於雙向資料繫結,不同點在於 v-model只能針對一個資料進行繫結,而 sync 修飾符沒有限制

子元件​

<template>
  <div>
    <p>
      <button @click="$emit(`update:num1`, num1 - 1)">-</button>
      {{ num1 }}
      <button @click="$emit(`update:num1`, num1 + 1)">+</button>
    </p>
    <p>
      <button @click="$emit(`update:num2`, num2 - 1)">-</button>
      {{ num2 }}
      <button @click="$emit(`update:num2`, num2 + 1)">+</button>
    </p>
  </div>
</template>
<script>
export default {
  props: ["num1", "num2"],
};
</script>
 

父元件​


<template>
 <div id="app">
   <Numbers :num1.sync="n1" :num2.sync="n2" />
   <!-- 等同於 -->
   <Numbers
     :num1="n1"
     @update:num1="n1 = $event"
     :num2="n2"
     @update:num2="n2 = $event"
   />
 </div>
</template>
<script>
import Numbers from "./components/Numbers.vue";
export default {
 components: {
   Numbers,
 },
 data() {
   return {
     n1: 0,
     n2: 0,
   };
 },
};
</script>

$parent 和 $children

在元件內部,可以通過$parent 和$children屬性,分別獲取當前元件的父元件和子元件例項


<template>
 <div class="hello">
   <button @click="handelParent">獲取父元件例項</button>
   <button @click="handelChild">獲取子元件例項</button>
   <Child />
 </div>
</template>
​
<script>
import Child from "./Children.vue";
export default {
 name: "HelloWorld",
 props: {
   msg: String,
 },
 components: {
   Child,
 },
 methods: {
   handelParent() {
     console.log("父元件例項:", this.$parent);
   },
   handelChild() {
     console.log("子元件例項", this.$children);
   },
 },
};
</script>

ref

在使用元件時,可以通過在元件上定義ref來獲取元件例項


 
<template>
  <div class="hello">
    <button @click="handelChild">獲取子元件例項</button>
    <Child ref="child" />
  </div>
</template>
<script>
import Child from "./Children.vue";
export default {
  name: "HelloWorld",
  props: {
    msg: String,
  },
  components: {
    Child,
  },
  methods: {
    handelChild() {
      console.log("子元件例項", this.$refs.child);
    },
  },
};
</script>
 

跨元件通訊

provide 和 Inject

provide和inject 可以實現深層元件通訊,頂層元件只需定義provide,底層元件通過inject接受資料

頂層元件


// 父元件
provide(){
 msg:'hello Children'
},
​
// 子元件
inject: ['msg']
created () {
 console.log(this.msg) // hello Children
}

router

如果一個組將改變了位址列,所有監聽位址列的組將都會做出相應的改變,


//監聽路由變化
watch:{
   $route(to,from) {
     console.log(to,from);
   }
}

vuex

vuex 過於笨重,通常不建議在小型專案中使用,小型專案可以使用store 或 eventbus代替vuex,vuex本質上就是一個資料倉儲。在此不做過多贅述,先挖一個坑,下回再敘。

store 模式

store模式其實就是一個普通的js模組,各元件可以匯入該模組,將資料放到data裡面,此時store就具有響應式了。

// 匯出一個 store.js模組
export default {
    userInfo:{...},
    loginInfo:{...}
}

// A子元件匯入 store模組
import store from './store.js'
export default {
  name:'Acompon',
  data(){
    userInfo: store.userInfo
  }
}

// B子元件匯入 store模組
import store from './store.js'
export default {
  name:'Bcompon',
  data(){
    loginInfo: store.loginInfo
  }
}
 

tip: store模式的缺點是無法跟蹤資料的改變,因為所有元件都可以更改資料

eventbus

eventbus事件匯流排相當於一個橋樑,作為所有組將的一個事件中心,所有元件皆可往eventbus裡面註冊事件,也可以監聽事件。


// 定義一個eventbus模組
import Vue from 'vue'
export const EventBus = new Vue()


// 在main.js裡匯入該模組並掛載到全域性

// main.js
import eventbus from './eventbus.js'
Vue.prototype.$eventBus = eventbus


所有子元件向eventbus裡組 註冊 或者 監聽 事件


 
// 元件A 通過 $emit()註冊事件
sendMsg() {
   this.$eventBus.$emit("aMsg", 'from A');
}

// 元件B 通過 $on 監聽事件
this.$eventBus.$on("aMsg", (msg) => {
    // A傳送來的訊息
    console.log(msg) // from A
})

// 通過 $off() 可以關閉事件

相關文章