欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

vue子組件通過.sync修飾符修改props屬性方式

 更新時間:2022年08月25日 10:32:42   作者:東之健大壞蛋  
這篇文章主要介紹了vue子組件通過.sync修飾符修改props屬性方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教

子組件通過.sync修飾符修改props屬性

在vue子組件中,如果我們直接修改props中的屬性,會報錯:

Avoid mutating a prop directly since the value will be overwritten whenever the parent component re-renders. Instead, use a data or computed property based on the prop’s value. Prop being mutated: “val”

vue為我們提供了.sync修飾符來解決這個問題:

// 父組件中,通過.sync修改符綁定屬性
<my-children :val.sync='val'></my-children>
// 子組件中,修改屬性
<script>
export default {
  props: ['val'],
  methods: {
    myClick() {
      this.$emit('update:val', this.val + 1)
    }
  }
}
</script>

子組件修改父組件prop的幾種方式

實際工作項目開發(fā)中,很經(jīng)常會有父組件先傳遞值給子組件,再由子組件渲染展示的場景,下面我總結(jié)一下目前工作中遇到和用過的一些方式

常用方式

推薦,遵循prop單向傳遞的規(guī)則,基本數(shù)據(jù)類型和引用數(shù)據(jù)類型均可。

1. 通過父組件on監(jiān)聽子組件emit事件實現(xiàn)修改prop

原理:

  • 給子組件中的input標(biāo)簽綁定value屬性賦值prop中的值,因為是用value而不是v-model,所以修改input值的時候并不會影響到prop。
  • 然后給input綁定input事件,每次輸入內(nèi)容都會觸發(fā)input事件,在事件里通過this.$emit(‘父要監(jiān)聽的事件名’, 修改后的值)去將值向上傳遞。
  • 父組件中通過on監(jiān)聽子組件剛剛觸發(fā)的emit事件,將事件傳遞過來的值更新到父組件的data中。
  • 父組件data中的值更新后,因為有通過prop傳遞給子組件,所以子組件也會同步更新prop值并渲染視圖層。

emit

父組件代碼如下:

<template>
? <div style="background-color: skyblue;">
? ? <h3>通過父組件on監(jiān)聽子組件emit事件實現(xiàn)修改prop</h3>
? ? <div>父obj:{{ obj }}</div>
? ? <div>父msg:{{ msg }}</div>
? ? <!-- 父組件調(diào)用子組件時通過on監(jiān)聽子組件觸發(fā)的emit事件,以接收值并更新用 -->
? ? <emitChild
? ? ? :obj="obj"
? ? ? :msg="msg"
? ? ? @update-obj="updateObj"
? ? ? @update-msg="updateMsg"
? ? />
? </div>
</template>
<script>
import emitChild from './components/emitChild'
export default {
? name: 'emitUpdate',
? components: {
? ? emitChild
? },
? data () {
? ? return {
? ? ? obj: {
? ? ? ? name: 'zhangsan',
? ? ? ? age: 18
? ? ? },
? ? ? msg: 'hello'
? ? }
? },
? methods: {
? ? // 監(jiān)聽子組件觸發(fā)的事件并更新data中的obj
? ? updateObj (key, newVal) {
? ? ? this.obj[key] = newVal
? ? },
? ? // 監(jiān)聽子組件觸發(fā)的事件并更新data中的msg
? ? updateMsg (newVal) {
? ? ? this.msg = newVal
? ? }
? }
}
</script>

子組件代碼如下:

<template>
? <div style="background-color: pink;">
? ? <div>
? ? ? <span>修改name:</span>
? ? ? <!-- 這里綁定值用value,因為input在這主要用作展示prop數(shù)據(jù),實際修改不在子組件,子組件只是作為修改觸發(fā)源 -->
? ? ? <!-- 綁定input事件,作為觸發(fā)源的入口 -->
? ? ? <input type="text" :value="obj.name" @input="updateObj($event, 'name')">
? ? </div>
? ? <div>
? ? ? <span>修改age:</span>
? ? ? <input type="text" :value="obj.age" @input="updateObj($event, 'age')">
? ? </div>
? ? <div>
? ? ? <span>修改msg:</span>
? ? ? <input type="text" :value="msg" @input="updateMsg($event.target.value)">
? ? </div>
? </div>
</template>
<script>
export default {
? name: 'emitUpdateChild',
? props: {
? ? obj: {
? ? ? type: Object,
? ? ? default: () => {}
? ? },
? ? msg: {
? ? ? type: String,
? ? ? default: ''
? ? }
? },
? methods: {
? ? // 通知父組件更新obj
? ? updateObj ($event, key) {
? ? ? // 接收輸入的值,和obj中對應(yīng)需要更新值的屬性,然后回傳給父組件
? ? ? // 父組件就可以知道子組件需要更新obj中哪個屬性的值
? ? ? this.$emit('update-obj', key, $event.target.value)
? ? },
? ? // 通知父組件更新msg
? ? updateMsg (newVal) {
? ? ? this.$emit('update-msg', newVal)
? ? }
? }
}
</script>

2. 通過父組件sync修飾符 + 子組件emit事件實現(xiàn)修改prop

原理:

  • 給子組件中的input標(biāo)簽綁定value屬性賦值prop中的值,因為是用value而不是v-model,所以修改input值的時候并不會影響到prop。
  • 然后給input綁定input事件,每次輸入內(nèi)容都會觸發(fā)input事件,在事件里通過this.$emit(‘父要監(jiān)聽的事件名’, 修改后的值)去將值向上傳遞。
  • 父組件調(diào)用子組件傳遞prop時,在prop后加上.sync即可將事件傳遞過來的值更新到父組件的data中,因為sync其實就相當(dāng)于執(zhí)行了@監(jiān)聽子觸發(fā)的事件名 = "父data中的屬性名 = emit傳遞的值(即$event)"這一段代碼。
  • 父組件data中的值更新后,因為有通過prop傳遞給子組件,所以子組件也會同步更新prop值并渲染視圖層。

sync

父組件代碼如下:

<template>
? <div style="background-color: skyblue;">
? ? <h3>通過父組件sync修飾符 + 子組件emit事件實現(xiàn)修改prop</h3>
? ? <div>父obj:{{ obj }}</div>
? ? <div>父msg:{{ msg }}</div>
? ? <!-- 父組件調(diào)用子組件傳遞prop時,在prop后加上.sync即可 -->
? ? <syncChild :obj.sync="obj" :msg.sync="msg" />
? ? <!--
? ? ? sync其實就相當(dāng)于執(zhí)行了
? ? ? ? @監(jiān)聽子觸發(fā)的事件名 = "父data中的屬性名 = emit傳遞的值(即$event)"
? ? ? 這一段代碼
? ? -->
? ? <!-- 效果相當(dāng)于下面的代碼,所以父組件methods中不需要再定義修改data數(shù)據(jù)的方法 -->
? ? <!--
? ? ? <syncChild
? ? ? ? :obj="obj"
? ? ? ? :msg="msg"
? ? ? ? @update-obj="obj = $event"
? ? ? ? @update-msg="msg = $event"
? ? ? />
? ? -->
? </div>
</template>
<script>
import syncChild from './components/syncChild'
export default {
? name: 'syncUpdate',
? components: {
? ? syncChild
? },
? data () {
? ? return {
? ? ? obj: {
? ? ? ? name: 'zhangsan',
? ? ? ? age: 18
? ? ? },
? ? ? msg: 'hello'
? ? }
? }
}
</script>

子組件代碼如下:

<template>
? <div style="background-color: pink;">
? ? <div>
? ? ? <span>修改name:</span>
? ? ? <!-- 這里綁定值用value,因為input在這主要用作展示prop數(shù)據(jù),實際修改不在子組件,子組件只是作為修改觸發(fā)源 -->
? ? ? <!-- 綁定input事件,作為觸發(fā)源的入口 -->
? ? ? <input type="text" :value="childObj.name" @input="updateObj($event, 'name')">
? ? </div>
? ? <div>
? ? ? <span>修改age:</span>
? ? ? <input type="text" :value="childObj.age" @input="updateObj($event, 'age')">
? ? </div>
? ? <div>
? ? ? <span>修改msg:</span>
? ? ? <input type="text" :value="msg" @input="updateMsg($event.target.value)">
? ? </div>
? </div>
</template>
<script>
// 這里引入lodash工具庫的cloneDeep深拷貝方法
// 官方文檔地址 https://www.lodashjs.com/
import { cloneDeep } from 'lodash'
export default {
? name: 'emitUpdateChild',
? props: {
? ? obj: {
? ? ? type: Object,
? ? ? default: () => {}
? ? },
? ? msg: {
? ? ? type: String,
? ? ? default: ''
? ? }
? },
? data () {
? ? return {
? ? ? // 這里通過深拷貝將prop的obj復(fù)制了一份,主要為了:
? ? ? // 1.區(qū)分2個對象(引用類型)用的不是同一個內(nèi)存地址
? ? ? // 2.保留對象中所有的值,方便子組件渲染/修改/回傳用
? ? ? childObj: cloneDeep(this.obj)
? ? }
? },
? methods: {
? ? // 通知父組件更新obj
? ? updateObj ($event, key) {
? ? ? // 接收輸入的值,和childObj中對應(yīng)需要更新值的屬性
? ? ? // 然后更新childOBj后,回傳給父組件
? ? ? // 父組件直接把拿到的childObj更新到data的obj即可
? ? ? this.childObj[key] = $event.target.value
? ? ? this.$emit('update:obj', this.childObj)
? ? },
? ? // 通知父組件更新msg
? ? updateMsg (newVal) {
? ? ? this.$emit('update:msg', newVal)
? ? }
? }
}
</script>

取巧方式

主要針對引用數(shù)據(jù)類型,繞過了vue對于prop的檢測機制,具體看項目規(guī)范是否允許這樣寫。

3.通過data實現(xiàn)修改prop

前提:只有引用數(shù)據(jù)類型可以實現(xiàn)

原理:

  • 將父組件傳入的prop直接賦值給子組件的data,此時prop和data兩邊的變量指向的都是同一個內(nèi)存地址,所以修改data等于修改prop。
  • vue2開始不允許直接修改prop,但此時我們表面修改的是data不是prop,因此vue不會拋出錯誤,相當(dāng)于繞過了vue對于不允許修改prop的檢測機制。

data

父組件代碼如下:

<template>
? <div style="background-color: skyblue;">
? ? <h3>通過賦值到data實現(xiàn)修改prop</h3>
? ? <div>父obj:{{ obj }}</div>
? ? <div>父msg:{{ msg }}</div>
? ? <dataChild :obj="obj" :msg.sync="msg" />
? </div>
</template>
<script>
import dataChild from './components/dataChild'
export default {
? name: 'dataUpdate',
? components: {
? ? dataChild
? },
? data () {
? ? return {
? ? ? obj: {
? ? ? ? name: 'zhangsan',
? ? ? ? age: 18
? ? ? },
? ? ? msg: 'hello'
? ? }
? }
}
</script>

子組件代碼如下:

<template>
  <div style="background-color: pink;">
    <div>
      <span>修改name:</span>
      <!-- 這里因為我們直接把prop賦值給data了,所以可以直接用v-model雙向綁定修改數(shù)據(jù) -->
      <input type="text" v-model="dataObj.name">
    </div>
    <div>
      <span>修改age:</span>
      <input type="text" v-model="dataObj.age">
    </div>
    <div>
      <span>修改msg:</span>
      <!-- 這里提供另一種修改基本數(shù)據(jù)類型的思路,可以通過watch偵聽器實現(xiàn) -->
      <input type="text" v-model="dataMsg">
    </div>
  </div>
</template>
<script>
export default {
  name: 'dataChild',
  props: {
    obj: {
      type: Object,
      default: () => {}
    },
    msg: {
      type: String,
      default: ''
    }
  },
  data () {
    return {
      // 引用數(shù)據(jù)類型直接賦值時是淺拷貝,只會復(fù)制內(nèi)存地址,修改其中一個會影響另一個
      dataObj: this.obj,
      // 基本數(shù)據(jù)類型直接賦值時是復(fù)制值,修改其中一個不會影響另一個
      dataMsg: this.msg
    }
  },
  watch: {
    // 這里偵聽data中復(fù)制過來的dataMsg,當(dāng)修改時執(zhí)行emit通知父組件進(jìn)行更新
    dataMsg (newVal) {
      this.$emit('update:msg', newVal)
    }
  }
}
</script>

4.通過計算屬性computed實現(xiàn)修改prop

前提:只有引用數(shù)據(jù)類型可以實現(xiàn)

原理:

  • 在子組件中直接通過計算屬性computed監(jiān)聽父組件傳入的prop,此時計算屬性computed和prop兩邊的變量指向的都是同一個內(nèi)存地址,所以修改計算屬性computed等于修改prop。
  • vue2開始不允許直接修改prop,但此時我們表面修改的是計算屬性computed不是prop,因此vue不會拋出錯誤,相當(dāng)于繞過了vue對于不允許修改prop的檢測機制。

computed

父組件代碼如下:

<template>
? <div style="background-color: skyblue;">
? ? <h3>通過計算屬性監(jiān)聽實現(xiàn)修改prop</h3>
? ? <div>父obj:{{ obj }}</div>
? ? <div>父msg:{{ msg }}</div>
? ? <computedChild :obj="obj" :msg.sync="msg" />
? </div>
</template>
<script>
import computedChild from './components/computedChild'
export default {
? name: 'computedUpdate',
? components: {
? ? computedChild
? },
? data () {
? ? return {
? ? ? obj: {
? ? ? ? name: 'zhangsan',
? ? ? ? age: 18
? ? ? },
? ? ? msg: 'hello'
? ? }
? }
}
</script>

子組件代碼如下:

<template>
? <div style="background-color: pink;">
? ? <div>
? ? ? <span>修改name:</span>
? ? ? <!-- 這里因為我們直接通過計算屬性computed監(jiān)聽prop了,所以可以直接用v-model雙向綁定修改數(shù)據(jù) -->
? ? ? <input type="text" v-model="computedObj.name">
? ? </div>
? ? <div>
? ? ? <span>修改age:</span>
? ? ? <input type="text" v-model="computedObj.age">
? ? </div>
? ? <div>
? ? ? <span>修改msg:</span>
? ? ? <!-- 這里提供另一種修改基本數(shù)據(jù)類型的思路,可以通過計算屬性computed的setter實現(xiàn) -->
? ? ? <input type="text" v-model="computedMsg">
? ? </div>
? </div>
</template>
<script>
export default {
? name: 'computedChild',
? props: {
? ? obj: {
? ? ? type: Object,
? ? ? default: () => {}
? ? },
? ? msg: {
? ? ? type: String,
? ? ? default: ''
? ? }
? },
? computed: {
? ? computedObj () {
? ? ? // 這里直接return引用數(shù)據(jù)類型obj,此時computedObj相當(dāng)于obj
? ? ? // 所以是淺拷貝,只會復(fù)制內(nèi)存地址,修改其中一個會影響另一個
? ? ? return this.obj
? ? },
? ? computedMsg: {
? ? ? get () {
? ? ? ? // 這里prop每次更新時,都會觸發(fā)計算屬性的getter方法獲取最新的值
? ? ? ? // 直接return基本數(shù)據(jù)類型時是復(fù)制值,修改其中一個不會影響另一個
? ? ? ? return this.msg
? ? ? },
? ? ? set (newVal) {
? ? ? ? // 這里利用計算屬性的setter方法,監(jiān)聽到值修改時觸發(fā)emit通知父組件更新值
? ? ? ? this.$emit('update:msg', newVal)
? ? ? }
? ? }
? }
}
</script>

以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • Vue 自定義標(biāo)簽的src屬性不能使用相對路徑的解決

    Vue 自定義標(biāo)簽的src屬性不能使用相對路徑的解決

    這篇文章主要介紹了Vue 自定義標(biāo)簽的src屬性不能使用相對路徑的解決,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-09-09
  • Vue3 封裝回到頂部組件的實現(xiàn)示例

    Vue3 封裝回到頂部組件的實現(xiàn)示例

    回到頂部在很多網(wǎng)頁中都可以見到,本文主要介紹了Vue3 封裝回到頂部組件的實現(xiàn)示例,文中根據(jù)實例編碼詳細(xì)介紹的十分詳盡,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-03-03
  • vue?事件獲取當(dāng)前組件的屬性方式

    vue?事件獲取當(dāng)前組件的屬性方式

    這篇文章主要介紹了vue?事件獲取當(dāng)前組件的屬性方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-03-03
  • 前端使用vue實現(xiàn)token無感刷新的三種方案解析

    前端使用vue實現(xiàn)token無感刷新的三種方案解析

    這篇文章主要為大家介紹了前端使用vue實現(xiàn)token無感刷新的三種方案詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-06-06
  • 如何測量vue應(yīng)用運行時的性能

    如何測量vue應(yīng)用運行時的性能

    這篇文章主要介紹了如何測量vue應(yīng)用運行時的性能,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,,需要的朋友可以參考下
    2019-06-06
  • vue源碼之批量異步更新策略的深入解析

    vue源碼之批量異步更新策略的深入解析

    這篇文章主要給大家介紹了關(guān)于vue源碼之批量異步更新策略的相關(guān)資料,關(guān)于vue異步更新是我們?nèi)粘i_發(fā)中經(jīng)常遇到的一個功能,需要的朋友可以參考下
    2021-05-05
  • vant的Loading加載動畫組件的使用(通過接口拿數(shù)據(jù)時顯示加載狀態(tài))

    vant的Loading加載動畫組件的使用(通過接口拿數(shù)據(jù)時顯示加載狀態(tài))

    這篇文章主要介紹了vant的Loading加載動畫組件的使用,通過接口拿數(shù)據(jù)時顯示加載狀態(tài),本文通過實例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友參考下吧
    2024-01-01
  • vue-cli設(shè)置publicPath小記

    vue-cli設(shè)置publicPath小記

    這篇文章主要介紹了vue-cli設(shè)置publicPath小記,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-04-04
  • Vue查詢數(shù)據(jù)并通過bootstarp?table渲染數(shù)據(jù)

    Vue查詢數(shù)據(jù)并通過bootstarp?table渲染數(shù)據(jù)

    這篇文章主要為大家介紹了Vue查詢數(shù)據(jù)并通過bootstarp?table渲染數(shù)據(jù),有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-04-04
  • 關(guān)于Vue 3.0引入百度地圖不兼容的解決辦法

    關(guān)于Vue 3.0引入百度地圖不兼容的解決辦法

    這篇文章主要介紹了關(guān)于Vue 3.0引入百度地圖不兼容的解決辦法,本文通過實例代碼給大家分享解決方法,需要的朋友可以參考下
    2022-08-08

最新評論