一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務器之家:專注于服務器技術及軟件下載分享
分類導航

node.js|vue.js|jquery|angularjs|React|json|js教程|

服務器之家 - 編程語言 - JavaScript - vue.js - Vue中的父子組件通訊以及使用sync同步父子組件數據

Vue中的父子組件通訊以及使用sync同步父子組件數據

2022-03-10 16:23外婆的 vue.js

這篇文章主要介紹了Vue中的父子組件通訊以及使用sync同步父子組件數據,對vue感興趣的同學,可以參考下

前言

父子組件通訊,可分為兩種情況:

1. 父組件向子組件中傳遞數據
2. 子組件向父組件中傳遞數據

一般情況下, 1中情況可通過props解決數據傳遞的問題, 這里就不多贅述了。

子組件向父組件中傳遞數據

主要談談2中情景的實現,有三種方式:

一. 通過props,父組件向子組件中傳遞數據和改變數據的函數,通過在子組件中調用父組件傳過來的函數,達到更新父組件數據(向父組件傳遞數據)的作用(子組件中需要有相應的響應事件)

二. 通過在子組件中觸發一個 自定義事件(vm.$emit),將數據作為vm.$emit方法的參數,回傳給父組件用v-on:[自定義事件]監聽的函數

三.通過ref對子組件做標記,父組件可以通過vm.$refs.[子組件的ref].[子組件的屬性/方法]這種方式直接取得子組件的數據

下面我將一 一展示

一. 通過props從父向子組件傳遞函數,調用函數改變父組件數據

這里就不做代碼展示了

一來是因為相對比較簡單
二來是因為這種方式顯然不是Vue中的最佳實踐(在react中倒比較常見)
想要看代碼的話可以看這里:《【Vue】淺談Vue不同場景下組件間的數據交流》http://www.cnblogs.com/penghuwan/p/7286912.html (在兄弟組件的數據交流那一節)

二. 通過自定義事件從子組件向父組件中傳遞數據

我們可以在子組件中通過$emit(event, [...參數])觸發一個自定義的事件,這樣,父組件可以在使用子組件的地方直接用 v-on來監聽子組件觸發的事件, 并且可以在監聽函數中依次取得所有從子組件傳來的參數

例如:
在子組件中某個部分寫入:

this.emit("eventYouDefined", arg);

然后你就可以在父組件的子組件模板里監聽:
// 這里是父組件的Template:

<Son  v-on: eventYouDefined = "functionYours" />

下面是一個實例

父組件

<template>
  <div id="father">
    <div>
       我是父組件,我接受到了:
      {{ text || "暫無數據"  }}
      <son v-on:sendData="getSonText"></son>
    </div>
  </div>
</template>
 
<script>
import son from "./son.vue"
export default {
  data: function () {
    return {
      text: ""
    }
  },
  components: {
    son: son
  },
  methods: {
    getSonText (text) {
      this.text = text
    }
  }
}

</script>
 
<style scoped>
#father div {
  padding: 10px;
  margin: 10px;
  border: 1px solid grey;
  overflow: hidden;
}
</style>

子組件:

<template>
  <div>
    <p>我是子組件,我所擁有的數據: {{ text }}</p>
    <button @click="sendData">
      發送數據
    </button>
  </div>
</template>
 
<script>
export default {
  data () {
    return {
      text: "來自子組件的數據"
    }
  },
  methods: {
    sendData () {
      this.$emit("sendData", this.text)
    }
  }
}
</script>
 
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
   button { float: left }
</style>

在點擊子組件中的“發送數據”按鈕前, 父組件還沒有接受到數據(text為空字符串), 則通過 {{ text || "暫無數據" }}將顯示默認文本:‘暫無數據"

Vue中的父子組件通訊以及使用sync同步父子組件數據

點擊“發送數據”按鈕后:

Vue中的父子組件通訊以及使用sync同步父子組件數據

因為sendData自定義事件被觸發,通過

this.$emit("sendData", this.text)   //此處的this指向子組件實例)

子組件的text數據被父組件中:

 <son v-on:sendData="getSonText"></son>

中的getSonText函數作為參數接傳參受到, 從而完成了從子組件向父組件中的傳參過程

三. 通過ref屬性在父組件中直接取得子組件的數據(data)

對于我們上面講的一和二的處理情景來說,有個局限性就是它們都需要以事件機制為基礎(無論是像click那樣的原生事件還是自定義事件),而在事件發生的時候才能調用函數將數據傳遞過來

但如果子組件里沒有類似“按鈕”的東西,因而無法制造原生事件,同時也沒辦法找到一個觸發自定義事件的時機的時候,怎么從子組件向父組件傳遞數據呢??

這個時候, 我們就只能從父組件中“直接取”子組件的數據了,借助ref屬性

ref是我們經常用到的Vue屬性,利用它可以簡單方便地從本組件的template中取得DOM實例,而實際上,如果你在父組件中為子組件設置ref的話, 就可以直接通過vm.$refs.[子組件的ref].[子組件的屬性]去拿到數據啦,例如:

父組件:

<template>
  <div id="father">
    <div>
       我是父組件,我接受到了:
      {{ text || "暫無數據"  }}
      <button @click="getSonText()">接受數據</button>
      <son ref="son"></son>
    </div>
  </div>
</template>
 
<script>
import son from "./son.vue"
export default {
  data: function () {
    return {
      text: ""
    }
  },
  components: {
    son: son
  },
  methods: {
    getSonText () {
      this.text = this.$refs.son.text
    }
  }
}

</script>
 
<style scoped>
#father div {
  padding: 10px;
  margin: 10px;
  border: 1px solid grey;
  overflow: hidden;
}
</style>

子組件:

<template>
  <div>
    <p>我是子組件,我所擁有的數據: {{ text }}</p>
  </div>
</template>
 
<script>
export default {
  data () {
    return {
      text: "來自子組件的數據"
    }
  }
}
</script>
 
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
   button { float: left }
</style>

demo:

尚未點擊“接受數據”按鈕前:

Vue中的父子組件通訊以及使用sync同步父子組件數據

點擊接受數據按鈕后:

Vue中的父子組件通訊以及使用sync同步父子組件數據

通過sync實現數據雙向綁定, 從而同步父子組件數據

通過以上三種方式, 我想你應該能解決絕大多數父子組件通信的場景了,但讓我們再仔細考慮一下上面的通信場景,就會發現它們還可能存在的問題:

從子組件向父組件傳遞數據時,父子組件中的數據仍不是每時每刻都同步的

但在某些特殊的需求場景下,我們可能會希望父子組件中的數據時刻保持同步, 這時候你可能會像下面這樣做:

這是父組件中的template:

<son :foo="bar" v-on:update="val => bar = val"></son>

在子組件中, 我們通過props聲明的方式接收foo并使用

props: {
     foo: [type]
}

同時每當子組件中數據改變的時候,通過

this.$emit("update", newValue)

把參數newValue傳遞給父組件template中監聽函數中的"val"。然后通過

val => bar = val

這個表達式就實現了bar = newValue. 這個時候,我們發現父組件中的關鍵數據bar被子組件改變(相等)了!

通過數據的雙向綁定, 父(組件)可以修改子的數據, 子也可以修改父的數據

Vue提供了sync修飾符簡化上面的代碼,例如:

<comp :foo.sync="bar"></comp>

會被擴展為:

<comp :foo="bar" @update:foo="val => bar = val"></comp>

然后你需要在子組件中改變父組件數據的時候, 需要觸發以下的自定義事件:

this.$emit("update:foo", newValue)

【注意】你可能覺得這好像和我上面提到的二中的“通過自定義事件(emit)從子組件向父組件中傳遞數據”的那一節的內容似乎重疊了,。

然而并不是, 兩者有著父子組件關系上的不同, 下面我通過一行關鍵的代碼證明它們的區別所在

1.在我們講解sync的這一小節里, 自定義事件發生時候運行的響應表達式是:
<son :foo="bar" v-on:update="val => bar = val"></son> 中的 "val => bar = val"

2.在二中的“通過自定義事件從子組件向父組件中傳遞數據” 里,自定義事件發生時候運行的響應表達式是:
<Son v-on: eventYouDefined = "arg => functionYours(arg)" /> 中的 "arg => functionYours(arg)"

對前者, 表達式 val => bar = val意味著強制讓父組件的數據等于子組件傳遞過來的數據, 這個時候,我們發現父子組件的地位是平等的。 父可以改變子(數據), 子也可以改變父(數據)

對后者, 你的functionYours是在父組件中定義的, 在這個函數里, 你可以對從子組件接受來的arg數據做任意的操作或處理, 決定權完全落在父組件中, 也就是: 父可以改變子(數據), 但子不能直接改變父(數據)!, 父中數據的變動只能由它自己決定

下面是一個展示demo:

父組件:

<template>
  <div id="father">
    <div>
       我是父組件
      <son
        :wisdom.sync="wisdom"
        :magic.sync="magic"
        :attack.sync="attack"
        :defense.sync="defense">
      </son>
      <p>智力: {{ wisdom }}</p>
      <p>膜法: {{ magic }}</p>
      <p>攻擊: {{ attack }}</p>
      <p>防御: {{ defense }}</p>
    </div>
  </div>
</template>
 
<script>
import son from "./son.vue"
export default {
  data: function () {
    return {
      wisdom: 90,
      magic: 160,
      attack: 100,
      defense: 80
    }
  },
  components: {
    son: son
  }
}

</script>
 
<style scoped>
#father div {
  padding: 10px;
  margin: 10px;
  border: 1px solid grey;
  overflow: hidden;
}
</style>

子組件:

<template>
  <div>
    <p>我是子組件</p>
    <p>智力: {{ wisdom }}</p>
    <p>膜法: {{ magic }}</p>
    <p>攻擊: {{ attack }}</p>
    <p>防御: {{ defense }}</p>
    <button @click="increment("wisdom")">增加智力</button>
    <button @click="increment("magic")">增加膜法</button>
    <button @click="increment("attack")">增加攻擊</button>
    <button @click="increment("defense")">增加防御</button>
  </div>
</template>
 
<script>
export default {
  props: {
    wisdom: Number,
    magic: Number,
    attack: Number,
    defense: Number
  },

  methods: {
    increment (dataName) {
      let newValue = this[dataName] + 1
      this.$emit(`update:${dataName}`, newValue)
    }
  }
}
</script>
 
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
   button { float: left }
</style>

點擊前

Vue中的父子組件通訊以及使用sync同步父子組件數據

點擊增加子組件中“增加智力”按鈕的時候, 父組件和子組件中的智力參數同時從90變為91

Vue中的父子組件通訊以及使用sync同步父子組件數據

點擊增加子組件中“增加膜法”按鈕的時候, 父組件和子組件中的智力參數同時從160變為161

Vue中的父子組件通訊以及使用sync同步父子組件數據

數據雙向綁定是把雙刃劍

從好處上看:

1.它實現了父子組件數據的“實時”同步, 在某些數據場景下可能會使用到這一點
2.sync提供的語法糖使得雙向綁定的代碼變得很簡單

從壞處上看:

它破環了單向數據流的簡潔性, 這增加了分析數據時的難度

當sync修飾的prop是個對象

我們對上面的例子修改一下, 把數據包裹在一個對象中傳遞下來:

父組件

<template>
  <div id="father">
    <div>
       我是父組件
      <son :analysisData.sync="analysisData">
      </son>
      <p>智力: {{ analysisData.wisdom }}</p>
      <p>膜法: {{ analysisData.magic }}</p>
      <p>攻擊: {{ analysisData.attack }}</p>
      <p>防御: {{ analysisData.defense }}</p>
    </div>
  </div>
</template>
 
<script>
import son from "./son.vue"
export default {
  data: function () {
    return {
      analysisData: {
        wisdom: 90,
        magic: 160,
        attack: 100,
        defense: 80
      }
    }
  },
  components: {
    son: son
  }
}

</script>
 
<style scoped>
#father div {
  padding: 10px;
  margin: 10px;
  border: 1px solid grey;
  overflow: hidden;
}
</style>

子組件

<template>
  <div>
    <p>我是子組件</p>
    <p>智力: {{ analysisData.wisdom }}</p>
    <p>膜法: {{ analysisData.magic }}</p>
    <p>攻擊: {{ analysisData.attack }}</p>
    <p>防御: {{ analysisData.defense }}</p>
    <button @click="increment("wisdom")">增加智力</button>
    <button @click="increment("magic")">增加膜法</button>
    <button @click="increment("attack")">增加攻擊</button>
    <button @click="increment("defense")">增加防御</button>
  </div>
</template>
 
<script>
export default {
  props: {
    analysisData: Object
  },

  methods: {
    increment (dataName) {
      let newObj = JSON.parse(JSON.stringify(this.analysisData))
      newObj[dataName] += 1
      this.$emit("update:analysisData", newObj)
    }
  }
}
</script>
 
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
   button { float: left }
</style>

demo同上

不要通過在子組件中修改引用類型props達到“父子組件數據同步”的需求!

父組件的數據傳遞給子組件, 一般通過props實現, 而在實現“父子組件數據同步”這一需求的時候, 小伙伴們可能會發現一點: 在子組件中修改引用類型的props(如數組和對象)是可行的

1.不僅可以達到同時修改父組件中的數據(因為本來引用的就是同一個數據)
2.而且還不會被Vue的檢測機制發現!(不會報錯)

但千萬不要這樣做, 這樣會讓數據流變得更加難以分析,如果你嘗試這樣做, 上面的做法可能會更好一些
不要這樣做,糟糕的做法:

父組件:

<template>
  <div id="father">
    <div>
       我是父組件
      <son :analysisData="analysisData">
      </son>
      <p>智力: {{ analysisData.wisdom }}</p>
      <p>膜法: {{ analysisData.magic }}</p>
      <p>攻擊: {{ analysisData.attack }}</p>
      <p>防御: {{ analysisData.defense }}</p>
    </div>
  </div>
</template>
 
<script>
import son from "./son.vue"
export default {
  data: function () {
    return {
      analysisData: {
        wisdom: 90,
        magic: 160,
        attack: 100,
        defense: 80
      }
    }
  },
  components: {
    son: son
  }
}

</script>
 
<style scoped>
#father div {
  padding: 10px;
  margin: 10px;
  border: 1px solid grey;
  overflow: hidden;
}
</style>

子組件:

<template>
  <div>
    <p>我是子組件</p>
    <p>智力: {{ analysisData.wisdom }}</p>
    <p>膜法: {{ analysisData.magic }}</p>
    <p>攻擊: {{ analysisData.attack }}</p>
    <p>防御: {{ analysisData.defense }}</p>
    <button @click="increment ("wisdom")">增加智力</button>
    <button @click="increment ("magic")">增加膜法</button>
    <button @click="increment ("attack")">增加攻擊</button>
    <button @click="increment ("defense")">增加防御</button>
  </div>
</template>
 
<script>
export default {
  props: {
    analysisData: Object
  },

  methods: {
    increment (dataName) {
      let obj = this.analysisData
      obj[dataName] += 1
    }
  }
}
</script>
 
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
   button { float: left }
</style>

以上就是Vue中的父子組件通訊以及使用sync同步父子組件數據的詳細內容,更多關于Vue的資料請關注服務器之家其它相關文章!

原文鏈接:https://www.cnblogs.com/penghuwan/p/7473375.html

延伸 · 閱讀

精彩推薦
  • vue.jsVue2.x 項目性能優化之代碼優化的實現

    Vue2.x 項目性能優化之代碼優化的實現

    這篇文章主要介紹了Vue2.x 項目性能優化之代碼優化的實現,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋...

    優小U9632022-02-21
  • vue.js詳解vue 表單綁定與組件

    詳解vue 表單綁定與組件

    這篇文章主要介紹了vue 表單綁定與組件的相關資料,幫助大家更好的理解和學習使用vue框架,感興趣的朋友可以了解下...

    Latteitcjz6432022-02-12
  • vue.jsVue項目中實現帶參跳轉功能

    Vue項目中實現帶參跳轉功能

    最近做了一個手機端系統,其中遇到了父頁面需要攜帶參數跳轉至子頁面的問題,現已解決,下面分享一下實現過程,感興趣的朋友一起看看吧...

    YiluRen丶4302022-03-03
  • vue.js用vite搭建vue3應用的實現方法

    用vite搭建vue3應用的實現方法

    這篇文章主要介紹了用vite搭建vue3應用的實現方法,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下...

    Asiter7912022-01-22
  • vue.jsVue多選列表組件深入詳解

    Vue多選列表組件深入詳解

    這篇文章主要介紹了Vue多選列表組件深入詳解,這個是vue的基本組件,有需要的同學可以研究下...

    yukiwu6752022-01-25
  • vue.jsVue中引入svg圖標的兩種方式

    Vue中引入svg圖標的兩種方式

    這篇文章主要給大家介紹了關于Vue中引入svg圖標的兩種方式,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的...

    十里不故夢10222021-12-31
  • vue.js梳理一下vue中的生命周期

    梳理一下vue中的生命周期

    看過很多人講vue的生命周期,但總是被繞的云里霧里,尤其是自學的同學,可能js的基礎也不是太牢固,聽起來更是吃力,那我就已個人之淺見,以大白話...

    CRMEB技術團隊7992021-12-22
  • vue.jsVue2.x-使用防抖以及節流的示例

    Vue2.x-使用防抖以及節流的示例

    這篇文章主要介紹了Vue2.x-使用防抖以及節流的示例,幫助大家更好的理解和學習使用vue框架,感興趣的朋友可以了解下...

    Kyara6372022-01-25
主站蜘蛛池模板: 国产精品极品美女自在线 | 亚洲羞羞裸色私人影院 | 亚洲精品123区在线观看 | 黑人巨大精品战中国美女 | 荡女人人爱全文免费阅读 | 免费一级毛片在线播放放视频 | 狠狠色狠狠色综合系列 | 久久不射视频 | katsuniav在线播放 | 欧美式禁忌 | 日日精品 | chinese壮直男gay老年人 | 日韩综合第一页 | 久久久久久久电影 | 国产资源在线视频 | 国产伦码精品一区二区三区 | 美国69xxxx59| 日本高清在线播放一区二区三区 | bbwfreehd女厕所ved | 亚洲激情网站 | 99成人国产精品视频 | 禁止的爱善良的未删减版hd | 国产卡一卡二卡四卡无卡 | 第一次破女视频国产一级 | a级毛片毛片免费很很综合 a级黄色视屏 | 国产亚洲欧美日韩俺去了 | 国产老熟 | 99视频都是精品热在线播放 | 日本精品vide·ssex日本 | 国产精品亚洲片在线不卡 | 免费一级毛片在级播放 | 男人肌肌捅女人肌肌 | 欧美综合另类 | 四虎网站最新网址 | 成年人视频在线免费看 | 国产精品刺激好大好爽视频 | 天天干夜夜拍 | 免费的强动漫人物 | 日本videosdesexo乱| 免费港剧在线观看港剧 | julianann在厨房|