中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Vue組件間如何通信

發布時間:2022-08-13 09:15:29 來源:億速云 閱讀:150 作者:iii 欄目:編程語言

本篇內容主要講解“Vue組件間如何通信”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓小編來帶大家學習“Vue組件間如何通信”吧!

Vue組件間如何通信

vue的兩大特性是響應式編程和組件化。組件(Component)是 Vue 最核心的功能,但是各個組件實例的作用域是相互獨立的,這表明不同組件之間的數據是無法直接相互引用的。如果想要跨組件引用數據,就需要用到組件通信了,在通信之前先要理解組件之間的關系:

Vue組件間如何通信

如上圖所示:
父子關系:A與B,A與C,B與D,C與E
兄弟關系:B與C
隔代關系(可能隔更多代):A與D,A與E
跨級關系:B與E,D與E等

通信方式

一、props/$emit

父組件通過v-bind綁定一個自定義的屬性,子組件通過props接收父組件傳來的數據;子組件通過$emit觸發事件,父組件用on()或者在子組件的自定義標簽上使用v-on來監聽子組件觸發的自定義事件,從而接收子組件傳來的數據。

1、父組件向子組件傳值

下面通過一個例子來說明父組件向子組件傳值,父組件parent.vue把數據books:['JavaScript高級程序設計', 'CSS新世界', '圖解 HTTP 彩色版']傳給子組件child.vue,并在child.vue中展示出來

// 父組件parent.vue
<template>
  <div>
    <Child :books="books"/>
  </div>
</template>

<script>
import Child from './components/Child.vue'

export default {
  name: 'parent',
  components: {
    Child
  },
  data() {
    return {
      books: ['JavaScript高級程序設計', 'CSS新世界', '圖解 HTTP 彩色版']
    }
  }
}
</script>
// 子組件child.vue
<template>
  <div>
    <ul>
      <li v-for="(item, index) in books" :key="index">{{item}}</li>
    </ul>
  </div>
</template>

<script>
export default {
  props: {
    books: {
      type: Array,
      default: () => {
        return []
      }
    }
  }
}
</script>

Vue組件間如何通信
注意:通過props傳遞數據是單向的,父組件數據變化時會傳遞給子組件,但子組件不能通過修改props傳過來的數據來修改父組件的相應狀態,即所謂的單向數據流。

2、子組件向父組件傳值

下面通過子組件點擊書籍列表,用$emit()觸發,然后再父組件中獲取

// 子組件child.vue
<template>
  <div>
    <ul>
      <li v-for="(item, index) in books" :key="index" @click="like(item)">{{item}}</li>
    </ul>
  </div>
</template>

<script>
export default {
  props: {
    books: {
      type: Array,
      default: () => {
        return []
      }
    }
  },
  methods: {
    like(item) {
      this.$emit('likeBook', item)
    }
  }
}
</script>
// 父組件parent.vue
<template>
  <div>
    <Child :books="books" @likeBook="likeBook"/>
  </div>
</template>

<script>
import Child from './components/Child.vue'

export default {
  name: 'parent',
  components: {
    Child
  },
  data() {
    return {
      books: ['JavaScript高級程序設計', 'CSS新世界', '圖解 HTTP 彩色版']
    }
  },
  methods: {
    likeBook(val) {
      alert('我最喜歡的書籍是《' + val + '》')
    }
  }
}
</script>

Vue組件間如何通信

二、&dollar;parent/$children

  • $parent:訪問父組件實例

  • $children:訪問子組件實例

// 父組件parent.vue
<template>
  <div>
    <Child />
    <button @click="getChildData">獲取子組件數據</button>
  </div>
</template>

<script>
import Child from './components/Child.vue'

export default {
  name: 'parent',
  components: {
    Child
  },
  data() {
    return {
      books: ['JavaScript高級程序設計', 'CSS新世界', '圖解 HTTP 彩色版']
    }
  },
  methods: {
    getChildData() {
      alert(this.$children[0].msg)
    }
  }
}
</script>
// 子組件child.vue
<template>
  <div>
    <ul>
      <li v-for="(item, index) in bookLists" :key="index">{{item}}</li>
    </ul>
  </div>
</template>

<script>
export default {
  name: 'child',
  data() {
    return {
      bookLists: [],
      msg: '我是子組件的值!'
    }
  },
  mounted() {
    this.bookLists = this.$parent.books
  }
}
</script>

注意:&dollar;parent拿到的是對象,如果是最頂層沒有父組件的情況下拿到的是undefined$children拿到的是數組,如果是做底層沒有子組件的情況下,拿到的是空數組;這兩種通信方式只能用于父子組件通信

三、ref

ref如果在普通Dom元素上使用,引用指向的就是 DOM 元素;如果在子組件上使用,引用就指向組件實例,可以通過實例直接調用組件的方法和數據

// 父組件parent.vue
<template>
  <div>
    <Child ref="child" />
    <button @click="getChildData">獲取子組件數據</button>
  </div>
</template>

<script>
import Child from './components/Child.vue'

export default {
  name: 'parent',
  components: {
    Child
  },
  methods: {
    getChildData() {
      const msg = this.$refs['child'].msg
      console.log(msg)
      this.$refs['child'].say()
    }
  }
}
</script>
// 子組件child.vue
<script>
export default {
  name: 'child',
  data() {
    return {
      msg: '我是子組件的值!'
    }
  },
  methods: {
    say() {
      alert('你好,我是子組件!')
    }
  },
}
</script>

四、provide/inject

祖先組件通過provide來提供變量,子孫組件通過inject注入變量來獲取祖先組件的數據,不管子孫組件嵌套有多深, 只要調用了inject 那么就可以注入provide中的數據。下面是具體代碼:

// 父組件
<template>
  <div>
    <h2>康熙</h2>
    <Son />
  </div>
</template>

<script>
import Son from './components/Son.vue'

export default {
  components: {
    Son
  },
  provide() {
    return {
      FatherToSon: this.FatherToSon,
      FatherToGrandson: this.FatherToGrandson,
    }
  },
  data() {
    return {
      FatherToSon: '我是康熙,雍正,你是我兒子!',
      FatherToGrandson: '我是康熙,乾隆,你是我孫子!',
    }
  }
}
</script>
// 子組件
<template>
  <div>
    <h2>雍正</h2>
    <button @click="receive">接收</button>
    <Grandson />
  </div>
</template>

<script>
import Grandson from './Grandson.vue'
export default {
  components: { 
    Grandson 
  },
  inject: ['FatherToSon'],
  methods: {
    receive() {
      alert(this.FatherToSon)
    }
  }
}
</script>
// 孫組件
<template>
  <div>
    <h2>乾隆</h2>
    <button @click="receive">接收</button>
  </div>
</template>

<script>
export default {
  inject: ['FatherToGrandson'],
  methods: {
    receive() {
      alert(this.FatherToGrandson)
    }
  }
}
</script>

Vue組件間如何通信
注意:provide/inject只能從上往下傳值,且不是響應式,若要變成響應式的數據provide需要提供函數

五、eventBus&dollar;emit/$on

eventBus是消息傳遞的一種方式,基于一個消息中心,訂閱和發布消息的模式,稱為發布訂閱者模式。
eventBus 又稱為事件總線。在 Vue 中可使用 eventBus 來作為溝通橋梁的概念,就像是所有組件共用相同的事件中心,可向該中心注冊發送事件或接收事件,所以組件都可以上下平行地通知其他組件。

  • $emit('name',args): name:發布的消息名稱 , args:發布的消息

  • $on('name',fn): name:訂閱的消息名稱, fn: 訂閱的消息

  • &dollar;once('name',fn): name:訂閱的消息名稱, fn: 訂閱的消息。與$on相似但是只觸發一次,一旦觸發之后,監聽器就會被移除

  • &dollar;off('name',callback):name:事件名稱,callback:回調監聽器
    eventbus可以實現任何組件之前的通信,下面以兄弟組件為例

    1、初始化,全局引入
// main.js
// 全局添加事件總線
Vue.prototype.$bus = new Vue()
2、發送事件

在parent.vue引入ChildA和ChildB組件,使它們成為兄弟組件

// 父組件parent.vue
<template>
  <div>
    <ChildA />
    <ChildB />
  </div>
</template>

<script>
import ChildA from './components/childA'
import ChildB from './components/childB'
export default {
  components: {
    ChildA,
    ChildB
  }
}
</script>

在ChildA組件中用$emit發送事件

// ChildA組件
<template>
  <div>
    <h2>組件A</h2>
    <button @click="send">發送</button>
  </div>
</template>

<script>
export default {
  methods: {
    // 發送事件
    send() {
      this.$bus.$emit('message', '歡迎使用eventBus!')
    }
  }
}
</script>
3、接收事件發送的事件

在ChildB組件中用$on接收ChildA發送的事件

// ChildB組件
<template>
  <div>
    <h2>組件B</h2>
  </div>
</template>

<script>
export default {
  mounted() {
    // 接收事件
    this.$bus.$on('message', data => {
      alert('我是組件B,我收到的消息為:' + data)
    })
  },
  beforeDestroy() {
    this.$bus.$off('message')
  }
}
</script>

注意:&dollar;on監聽的事件不會自動移除監聽,因此在不用時最好使用$off移除監聽以免產生問題

六、&dollar;attrs/$listeners

1、簡介

當組件為兩級嵌套時,一般采用props&dollar;emit,但遇到多級組件嵌套時這種方法就不太適用了,如果不做中間處理,只傳遞數據用vuex有點大材小用了。因此在vue2.4中為了解決這一需求,便引入了&dollar;attrs$listeners, 新增了inheritAttrs屬性

  • &dollar;attrs:當父組件傳遞了很多數據給子組件時,子組件沒有聲明props來進行接收,么子組件中的attrs屬性就包含了所有父組件傳來的數據(除開已經props聲明了的);子組件還可以使用v?bind="$attrs"的形式將所有父組件傳來的數據(除開已經props聲明了的)傳向下一級子組件,通常和interitAttrs屬性一起使用。

  • &dollar;listeners:包含了父組件中(不含.native修飾器的)v-on 事件監聽器,通過v-on="$listeners",可以將這些事件綁定給它自己的子組件

    2、實例

    下面看一個例子:

// 父組件
<template>
  <div>
    <ChildA :name="name" :sex="sex" :age="age" @getName="getName" @getAge="getAge" />
  </div>
</template>

<script>
import ChildA from './components/childA'
export default {
  name: 'parent',
  components: {
    ChildA,
  },
  data() {
    return {
      name: '小明',
      age: 18,
      sex: '男'
    }
  },
  methods: {
    // 獲取名字
    getName() {
      console.log('我的名字是' + this.name)
    },
    // 獲取年齡
    getAge() {
      console.log('我今年' + this.age + '歲');
    }
  }
}
</script>
// 子組件A
<template>
  <div>
    <h2>組件A</h2>
    {{ msgA }}
    <hr/>
    <ChildB v-bind="$attrs" :height="height" v-on="$listeners" @getHeight="getHeight" />
  </div>
</template>

<script>
import ChildB from './childB.vue'
export default {
  name: 'ChildA',
  components: {
    ChildB
  },
  data() {
    return {
      msgA: null,
      height: '175cm'
    }
  },
  props: {
    sex: {
      type: String,
      default: ''
    }
  },
  mounted() {
    this.msgA = this.$attrs
    console.log('組件A獲取的$listeners:', this.$listeners)
  },
  methods: {
    // 獲取身高
    getHeight() {
      console.log('我的身高是' + this.height);
    }
  }
}
</script>
// 孫組件B
<template>
  <div>
    <h2>組件B</h2>
    {{ msgB }}
  </div>
</template>

<script>
export default {
  name: 'ChildB',
  data() {
    return {
      msgB: null
    }
  },
  mounted() {
    this.msgB = this.$attrs
    console.log('組件B獲取的$listeners:', this.$listeners)
  }
}
</script>

$attrs獲取的結果:
Vue組件間如何通信
$listeners獲取的結果:

Vue組件間如何通信

如代碼和圖所示組件A中props聲明接收了sex屬性,因此組件中&dollar;attrs獲取的是父組件中綁定的除去sex屬性的值;組件A中使用了v-bind="&dollar;attrs"v-on="$listeners",則組件B獲取不僅是組件A中本身綁定的屬性和方法還包含組件A獲取父組件綁定的屬性和方法

3、inheritAttrs

如果父組件傳遞了很多參數給子組件,而子組件沒有用props完全接收,那么沒有接收的這些屬性作為普通的 HTML attribute 應用在子組件的根元素上
如果你不希望子組件的根元素繼承特性,你可以在組件的選項中設置inheritAttrs: false

以上面的組件B為例,當inheritAttrs為true(inheritAttrs默認為true)
Vue組件間如何通信

當inheritAttrs為false時

// 孫組件B
export default {
  name: 'ChildB',
  inheritAttrs: false,
  data() {
    return {
      msgB: null
    }
  },
  mounted() {
    this.msgB = this.$attrs
    console.log('組件B獲取的$listeners:', this.$listeners)
  }
}

Vue組件間如何通信

七、Vuex

1、Vuex概述

Vuex 是一個專為 Vue.js 應用程序開發的狀態管理模式 + 庫。它采用集中式存儲管理應用的所有組件的狀態,并以相應的規則保證狀態以一種可預測的方式發生變化。
狀態管理包含以下幾個部分:
Vue組件間如何通信

  • 狀態(State),驅動應用的數據源

  • 視圖(View),以聲明方式將狀態映射到視圖;

  • 操作(Actions),響應在視圖上的用戶輸入導致的狀態變化

視圖發生變化會導致數據源的改變,數據源發生變化則會改變視圖,則上面表示是一個“單向數據流”。但是當我們的應用遇到多個組件共享狀態時,單向數據流的簡潔性很容易被破壞:

  • 多個視圖依賴于同一狀態。

  • 來自不同視圖的行為需要變更同一狀態。

因此,為了解決這種問題我們把組件的共享狀態抽取出來,以一個全局單例模式管理。在這種模式下,我們的組件樹構成了一個巨大的“視圖”,不管在樹的哪個位置,任何組件都能獲取狀態或者觸發行為!

通過定義和隔離狀態管理中的各種概念并通過強制規則維持視圖和狀態間的獨立性,我們的代碼將會變得更結構化且易維護。
Vue組件間如何通信

2、 Vuex各個模塊

1、state:存儲應用中需要共享的狀態,是Vuex中的唯一數據源。
2、getters:類似Vue中的計算屬性computedgetter 的返回值會根據它的依賴被緩存起  來,且只有當它的依賴值發生了改變才會被重新計算。
3、mutations:更改 Vuex 的 store 中的狀態(state)的唯一方法,且mutation 必須是同步函數
4、actions:類似于 mutation,提交的是 mutation,而不是直接變更狀態;可以包含任意異步操作
5、modules:將 store 分割成模塊(module)。每個模塊擁有自己的 state、mutation、action、getter、甚至是嵌套子模塊——從上至下進行同樣方式的分割

3、Vuex舉例

// 父組件
<template>
  <div class="home">
    <h2>父組件</h2>
    <hr/>
    <ChildA />
    <hr/>
    <ChildB />
  </div>
</template>

<script>
import ChildA from './components/ChildA'
import ChildB from './components/ChildB'

export default {
  name: 'parent',
  components: {
    ChildA,
    ChildB
  }
}
</script>
// 子組件A
<template>
  <div>
    <h2>組件A</h2>
    <p>A獲取的值: {{ count }}</p>
    <button @click="add(5)">ChildA-add</button>
  </div>
</template>

<script>
export default {
  computed: {
    count() {
      return this.$store.state.count
    }
  },
  methods: {
    // 改變store里count的值
    add(num) {
      this.$store.dispatch('countAdd', num)
    }
  }
}
</script>

<style>

</style>
// 子組件B
<template>
  <div>
    <h2>組件B</h2>
    <p>B獲取的值: {{ countB }}</p>
    <button @click="add(10)">ChildB-add</button>
  </div>
</template>

<script>
import { mapMutations, mapGetters } from 'vuex'
export default {
  computed: {
    ...mapGetters({
      countB: 'getCount'
    })
  },
  methods: {
    ...mapMutations(['countAdd']),
    // 改變store里count的值
    add(num) {
      this.countAdd(num)
    }
  }
}
</script>

<style>

</style>

store.js

import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

export default new Vuex.Store({
  state: {
    count: 0,
  },
  getters: {
    getCount: (state) => {
      return state.count
    }
  },
  mutations: {
    countAdd(state, num) {
      state.count += num
    }
  },
  actions: {
    countAdd(context, num) {
      context.commit('countAdd', num)
    }
  },
  modules: {
  }
})

Vue組件間如何通信

八、localStorage/sessionStorage

1、介紹

localStorage:本地存儲對象,存儲的數據是永久性數據,頁面刷新,即使瀏覽器重啟,除非主動刪除不然存儲的數據會一直存在
sessionStorage:與localStorage相似,但是只有在當前頁面下有效,關閉頁面或瀏覽器存儲的數據將會清空

localStorage和sessionStorage常用的API:

setItem (key, value) ——  保存數據,以鍵值對的方式儲存信息。
getItem (key) ——  獲取數據,將鍵值傳入,即可獲取到對應的value值。
removeItem (key) ——  刪除單個數據,根據鍵值移除對應的信息。
clear () ——  刪除所有的數據
key (index) —— 獲取某個索引的key
2、舉例
// 存儲
setItem() {
  window.localStorage.setItem('name1', '小明')
  window.sessionStorage.setItem('name2', '小紅')
}
// 接收
receive() {
  const name1 = window.localStorage.getItem('name1')
  const name2 = window.sessionStorage.getItem('name2')
  console.log(name1) // 打印結果為:小明
  console.log(name2) // 打印結果為:小紅
}
3、setItem()和getItem()使用時的類型轉換

localStorage和sessionStorage通過setItem()存儲數據會自動轉換為String類型,但是通過getItem()其類型并不會轉換回來(localStorage和sessionStorage使用方法一樣,下面均以localStorage為例)

const num = 1
window.localStorage.setItem('num', num)

const numRec = window.localStorage.getItem('num')
console.log(numRec, typeof(numRec)) // 1 string

因此正確的存儲方式應該為:存儲之前用JSON.stringify()方法將數據轉換成json字符串形式;需要使用數據的時候用JSON.parse()方法將之前存儲的字符串轉換成json對象

const num = 1
window.localStorage.setItem('num', JSON.stringify(num))
const obj = {
   name: '小紅',
   age: 18
 }
window.localStorage.setItem('obj', JSON.stringify(obj))

const numRec = JSON.parse(window.localStorage.getItem('num'))
console.log(numRec, typeof(numRec)) // 1 'number'
const objRec = JSON.parse(window.localStorage.getItem('obj'))
console.log(objRec, typeof(objRec)) // {name: '小紅', age: 18} 'object'

注意:localStorage.setItem()和sessionStorage.setItem()不能直接存儲對象,必須使用JSON.stringify()JSON.parse()轉換實現

總結

以上8種通信方式主要應用在以下三類場景:

  • 父子組件通信:最經常使用通信方式的是props/&dollar;emit,單一的父子組件通信使用&dollar;parent>/&dollar;children也比較方便;父組件也常使用ref獲取子組件實例;也可使用provide/inject&dollar;attrs/&dollar;listeners以及localStorage/sessionStorage

  • 兄弟組件通信:簡單的數據傳遞可使用eventBus&dollar;emit/&dollar;on;復雜的數據使用Vuex比較方便;也可以使用localStorage/sessionStorage;

  • 跨級組件通信:父子孫等嵌套組件通信方式多使用provide/inject&dollar;attrs/&dollar;listeners;跨級組件通信的數據如果不復雜可使用eventBuslocalStorage/sessionStorage;如果數據復雜可使用Vuex,但是要注意刷新界面Vuex存儲的數據會消失

到此,相信大家對“Vue組件間如何通信”有了更深的了解,不妨來實際操作一番吧!這里是億速云網站,更多相關內容可以進入相關頻道進行查詢,關注我們,繼續學習!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

vue
AI

建湖县| 云林县| 烟台市| 聊城市| 荣成市| 舞阳县| 二连浩特市| 江川县| 林州市| 奈曼旗| 修武县| 鄂托克前旗| 永善县| 新宾| 微山县| 宾川县| 临漳县| 沁阳市| 眉山市| 邻水| 嵩明县| 鄂伦春自治旗| 鱼台县| 鄯善县| 花莲县| 南郑县| 潼南县| 淮阳县| 宜黄县| 滦南县| 青铜峡市| 高要市| 涟源市| 方正县| 太保市| 雅江县| 临江市| 永和县| 射洪县| 南涧| 韶山市|