簡體   English   中英

在 Vue.js 2 中將道具作為初始數據傳遞的正確方法是什么?

[英]What's the correct way to pass props as initial data in Vue.js 2?

所以我想將道具傳遞給 Vue 組件,但我希望這些道具將來會從該組件內部更改,例如當我使用 AJAX 從內部更新該 Vue 組件時。 所以它們僅用於組件的初始化。

我的cars-list Vue 組件元素,我將具有初始屬性的道具傳遞給single-car

// cars-list.vue

<script>
    export default {
        data: function() {
            return {
                cars: [
                    {
                        color: 'red',
                        maxSpeed: 200,
                    },
                    {
                        color: 'blue',
                        maxSpeed: 195,
                    },
                ]
            }
        },
    }
</script>

<template>
    <div>
        <template v-for="car in cars">
            <single-car :initial-properties="car"></single-car>
        </template>
    </div>
</template>

我現在這樣做的方式是,在我single-car組件中,我在created()初始化掛鈎this.initialProperties分配給我的this.data.properties 它有效並且是反應性的。

// single-car.vue

<script>
    export default {
        data: function() {
            return {
                properties: {},
            }
        },
        created: function(){
            this.data.properties = this.initialProperties;
        },
    }
</script>

<template>
    <div>Car is in {{properties.color}} and has a max speed of {{properties.maxSpeed}}</div>
</template>

但我的問題是我不知道這是否是正確的方法? 這不會給我帶來一些麻煩嗎? 或者有更好的方法嗎?

感謝這個https://github.com/vuejs/vuejs.org/pull/567我現在知道答案了。

方法一

將初始道具直接傳遞給數據。 就像更新文檔中的示例一樣:

props: ['initialCounter'],
data: function () {
    return {
        counter: this.initialCounter
    }
}

但請記住,如果傳遞的 prop 是在父組件狀態中使用的對象或數組,則對該 prop 的任何修改都將導致該父組件狀態的更改。

警告:不推薦使用此方法。 它會讓你的組件變得不可預測。 如果您需要從子組件設置父數據,請使用 Vuex 之類的狀態管理或使用“v-model”。 https://v2.vuejs.org/v2/guide/components.html#Using-v-model-on-Components

方法二

如果您的初始道具是一個對象或數組,並且您不希望子狀態的更改傳播到父狀態,那么只需使用例如Vue.util.extend [1] 來制作道具的副本,而不是將其直接指向子數據, 像這樣:

props: ['initialCounter'],
data: function () {
    return {
        counter: Vue.util.extend({}, this.initialCounter)
    }
}

方法三

您還可以使用擴展運算符來克隆道具。 Igor 答案中的更多詳細信息: https ://stackoverflow.com/a/51911118/3143704

但請記住,舊瀏覽器不支持傳播運算符,為了更好的兼容性,您需要轉換代碼,例如使用babel

腳注

[1] 請記住,這是一個內部 Vue 實用程序,它可能會隨着新版本而改變。 您可能想使用其他方法來復制該道具,請參閱“https://stackoverflow.com/questions/728360/how-do-i-correctly-clone-a-javascript-object”。

我在哪里測試它的小提琴: https ://jsfiddle.net/sm4kx7p9/3/

伴隨@dominik-serafin 的回答:

如果您要傳遞一個對象,您可以使用擴展運算符(ES6 語法)輕松克隆它:

 props: {
   record: {
     type: Object,
     required: true
   }
 },

data () { // opt. 1
  return {
    recordLocal: {...this.record}
  }
},

computed: { // opt. 2
  recordLocal () {
    return {...this.record}
  }
},

但最重要的是要記住使用 opt。 2 如果您傳遞的是計算值,或者超過異步值。 否則本地值不會更新。

演示:

 Vue.component('card', { template: '#app2', props: { test1: null, test2: null }, data () { // opt. 1 return { test1AsData: {...this.test1} } }, computed: { // opt. 2 test2AsComputed () { return {...this.test2} } } }) new Vue({ el: "#app1", data () { return { test1: {1: 'will not update'}, test2: {2: 'will update after 1 second'} } }, mounted () { setTimeout(() => { this.test1 = {1: 'updated!'} this.test2 = {2: 'updated!'} }, 1000) } })
 <script src="https://cdn.jsdelivr.net/npm/vue@2.5.17/dist/vue.js"></script> <div id="app1"> <card :test1="test1" :test2="test2"></card> </div> <template id="app2"> <div> test1 as data: {{test1AsData}} <hr /> test2 as computed: {{test2AsComputed}} </div> </template>

https://jsfiddle.net/nomikos3/eywraw8t/281070/

我相信您做對了,因為這是文檔中所述的內容。

定義一個使用 prop 的初始值作為其初始值的本地數據屬性

https://vuejs.org/guide/components.html#One-Way-Data-Flow

我第二次或第三次遇到這個問題,回到一個舊的 vue 項目。

不知道為什么它在 vue 中如此復雜,但我們可以通過watch完成:

export default {

  props: ["username"],

  data () {
    return {
      usernameForLabel: "",
    }
  },

  watch: {
    username: {
      immediate: true,
      handler (newVal, oldVal) {
        this.usernameForLabel = newVal;
      }
    },
  },

就像另一種方法一樣,我通過子組件中的觀察者來做到這一點。

這種方式很有用,特別是當你傳遞一個異步值,並且在你的子組件中你想將傳遞的值綁定到 v-model 時。

此外,為了使其具有反應性,我在另一個觀察者中將本地值發送給父級。

例子:

  data() {
    return {
      properties: {},
    };
  },
  props: {
    initial-properties: {
      type: Object,
      default: {},
    },
  },
  watch: {
    initial-properties: function(newVal) {
      this.properties = {...newVal};
    },
    properties: function(newVal) {
      this.$emit('propertiesUpdated', newVal);
    },
  },

這樣我就有了更多的控制權和更少的意外行為。 例如,當父級傳遞的 props 是異步的時,它可能在創建或掛載生命周期時不可用。 所以你可以像@Igor-Parra 提到的那樣使用計算屬性,或者觀察道具然后發出它。

暫無
暫無

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

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