簡體   English   中英

如何從 vuejs 中的父組件更新子組件 b-tabs 值

[英]How to update the child component b-tabs value from parent component in vuejs

我正在嘗試從父組件更新子組件值,當我在道具中設置值時,我確實收到以下錯誤,

避免直接改變 prop,因為只要父組件重新渲染,該值就會被覆蓋。 相反,使用基於道具值的數據或計算屬性。

我嘗試了在 Internet 上找到的以下解決方案,但是通過這樣做,當我更新父組件時,我的子組件道具沒有改變

Parent component

<template>
  <child :index-val="indexVal"> </child>
</template>

<script>
export default {
  props: [indexVal],
  data() {
    return {
      indexVal: 0,
    }
  },
  methods: {
    updateVal() {
      // updating value from parent
      this.indexVal = 2
    },
  },
}
</script>

Child component

<template>
  <div>
    <!-- Tabs with card integration -->
    <b-card no-body>
      <b-tabs v-model="tabIndex" small card>
        <b-tab title="tab1">tab1</b-tab>
        <b-tab title="tab2">tab2</b-tab>
      </b-tabs>
    </b-card>
  </div>
</template>

<script>
export default {
  props: [indexVal],
  data() {
    return {
      tabIndex: this.indexVal,
    }
  },
}
</script>

當您嘗試改變prop的值時會發生您面臨的錯誤,因為prop值來自父母。 如果父級更改它,您在子級內部的更改將被覆蓋。

因此,當孩子需要更改prop時,它必須向父級發出一個事件,更新父級值,然后通過 prop 將更改流回子級。

道具下來,事件起來

為了消除這種機制的部分樣板,Vue 2 提供了.sync修飾符

在 Vue3 中, .sync已被棄用並刪除(重大更改)!
someProp.sync已被v-model:someProp取代,因為:

  • 它們提供相同的功能(雙重綁定),
  • 這增加了兩種語法及其特定實現細節之間的混淆。
  • 現在v-model行為在原生表單元素和 Vue 組件之間保持一致。

Vue 的作者 (Evan You) 在過去幾年中宣稱,未來,核心團隊的意圖是通過刪除不必要或令人困惑的語法選項來減少 API 表面。


Vue 2 示例:

 Vue.component('tab', { template: `#tab-tpl`, props: ['index', 'text'], computed: { tIndex: { get() { return this.index }, set(val) { this.$emit('update:index', val); } } } }) new Vue({ el: '#app', data: () => ({ tabs: [{text: 'one'}, {text: 'two'}, {text: 'three'}], tabIndex: 0 }), computed: { currentIndex: { get() { return this.tabIndex }, set(val) { this.tabIndex = (this.tabs.length + val) % this.tabs.length; } } } })
 .tab-pills { display: flex; border-bottom: 1px solid #ccc; cursor: pointer; } .active { color: red; } .tab-pills > div { padding: .3rem .7rem; } .tab-content { padding: 1rem .7rem; } .tab-body { padding: 1rem 0 }
 <script src="https://v2.vuejs.org/js/vue.min.js"></script> <div id="app"> <div class="tab-pills"> <div v-for="(tab, key) in tabs" v-text="tab.text" :class="{ active: key === currentIndex }" :key="key" @click="currentIndex = key"> </div> </div> <tab :index.sync="currentIndex" :text="tabs[currentIndex].text" class="tab-content"></tab> </div> <template id="tab-tpl"> <div> <div v-text="text" class="tab-body"></div> <button @click="tIndex -= 1">Prev</button> <button @click="tIndex += 1">Next</button> </div> </template>

同樣的事情,在 Vue 3(組合 API)中:

 const { defineComponent, toRefs, reactive, computed, createApp } = Vue; const Tab = defineComponent({ template: '#tab-tpl', props: ['index', 'text'], setup: (props, { emit }) => ({ tIndex: computed({ get: () => props.index, set: val => emit('update:index', val) }) }) }); const Tabs = defineComponent({ template: '#tabs-tpl', components: { Tab }, setup() { const state = reactive({ tabs: ['one', 'two', 'three'].map(text => ({ text })), tabIndex: 0, currentIndex: computed({ get: () => state.tabIndex, set: val => state.tabIndex = (state.tabs.length + val) % state.tabs.length }) }) return {...toRefs(state)} } }); createApp(Tabs).mount('#app')
 .tab-pills { display: flex; border-bottom: 1px solid #ccc; cursor: pointer; } .active { color: red; } .tab-pills > div { padding: .3rem .7rem; } .tab-content { padding: 1rem .7rem; } .tab-body { padding: 1rem 0 }
 <script src="https://unpkg.com/vue@3.2/dist/vue.global.prod.js"></script> <div id="app"></div> <template id="tabs-tpl"> <div class="tab-pills"> <div v-for="(tab, key) in tabs" v-text="tab.text" :class="{ active: key === currentIndex }" :key="key" @click="currentIndex = key"> </div> </div> <tab v-model:index="currentIndex" :text="tabs[currentIndex].text" class="tab-content"></tab> </template> <template id="tab-tpl"> <div v-text="text" class="tab-body"></div> <button @click="tIndex -= 1">Prev</button> <button @click="tIndex += 1">Next</button> </template>


在這兩個示例中,頂部的選項卡控件更改了父級別tabIndex

選項卡內的按鈕,從子級更改它(通過將更新的值發送給父級)。

重要的部分是父組件中的tabIndex更改,它驅動子組件中的更新。 不要介意在父項中計算的currentIndex ,這只是一個實現細節(它允許在最后一個選項卡上單擊Next時進入第一個選項卡,並在第一個選項卡上單擊Prev時進入最后一個選項卡 - 這是我添加它的唯一原因,它不是所有這些工作都需要)。

如果有不清楚的地方,請查看我在上面發布的文檔鏈接,了解您正在使用的 Vue 版本。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM