Dom*_*fin 74 javascript vue.js
所以我想将道具传递给Vue组件,但我希望这些道具将来会从该组件内部改变,例如当我使用AJAX从内部更新该Vue组件时.所以它们只用于组件的初始化.
我的cars-listVue组件元素,我将具有初始属性的props传递给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>
Run Code Online (Sandbox Code Playgroud)
我现在这样做的方式是在我的single-car组件里面我分配 this.initialProperties给我this.data.properties的created()初始化钩子.它起作用并且具有反应性.
// 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>
Run Code Online (Sandbox Code Playgroud)
但我的问题是我不知道这是否是一种正确的方法呢?这不会给我带来一些麻烦吗?或者有更好的方法吗?
Dom*_*fin 71
感谢这个https://github.com/vuejs/vuejs.org/pull/567我现在知道了答案.
将初始道具直接传递给数据.与更新文档中的示例一样:
props: ['initialCounter'],
data: function () {
return {
counter: this.initialCounter
}
}
Run Code Online (Sandbox Code Playgroud)
但请记住,如果传递的prop是在父组件状态中使用的对象或数组,则对该prop的任何修改都将导致该父组件状态的更改.
警告:不建议使用此方法.它会使您的组件变得不可预测.如果需要从子组件设置父数据,请使用Vuex之类的状态管理或使用"v-model".https://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)
}
}
Run Code Online (Sandbox Code Playgroud)
您还可以使用spread运算符来克隆道具.Igor回答的更多细节:https://stackoverflow.com/a/51911118/3143704
但请记住,旧浏览器不支持扩展运算符,为了更好的兼容性,您需要转换代码,例如使用babel.
[1]请记住这是一个内部Vue实用程序,它可能会随着新版本而改变.您可能希望使用其他方法来复制该prop,请参阅" 如何正确克隆JavaScript对象? ".
我在测试它的小提琴:https: //jsfiddle.net/sm4kx7p9/3/
jon*_*eda 13
我相信你做得对,因为它是在文档中说明的.
定义使用prop的初始值作为其初始值的本地数据属性
https://vuejs.org/guide/components.html#One-Way-Data-Flow
Igo*_*rra 12
与@ dominik-serafin的答案相配:
如果您传递的是opbject,可以使用spread operator(ES6)轻松克隆它:
props: {
record: {
type: Object,
required: true
}
},
data () { // opt. 1
return {
recordLocal: {...this.record}
}
},
computed: { // opt. 2
recordLocal () {
return {...this.record}
}
},
Run Code Online (Sandbox Code Playgroud)
但最重要的是要记住使用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)
}
})Run Code Online (Sandbox Code Playgroud)
<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>Run Code Online (Sandbox Code Playgroud)
https://jsfiddle.net/nomikos3/eywraw8t/281070/
小智 7
我第二次或第三次在回到旧的 vue 项目时遇到这个问题。
不知道为什么它在 vue 中如此复杂,但我们可以通过watch完成:
export default {
props: ["username"],
data () {
return {
usernameForLabel: "",
}
},
watch: {
username: {
immediate: true,
handler (newVal, oldVal) {
this.usernameForLabel = newVal;
}
},
},
Run Code Online (Sandbox Code Playgroud)