Vue中双向绑定props的正确方式是什么?
What's the correct ways of two-way binding props in Vue?
这里我有两个组件:
msg.vue
<template>
<div>
<input type="text" v-model="msg" />
</div>
</template>
<script>
export default {
name: "msg",
props: ["msg"]
};
</script>
samples.vue
<template>
<div>
<h2>{{ msg }}</h2>
</div>
</template>
<script>
export default {
name: "samples",
props: ["msg"]
};
</script>
最后,
App.vue
<template>
<div id="app">
<samples v-bind:msg="msg"></samples>
<msg :msg="msg"></msg>
</div>
</template>
<script>
import samples from "./components/samples.vue";
import msg from "./components/msg.vue";
export default {
name: "app",
components: {
samples,
msg
},
data: () => {
return {
msg: "Hello World"
};
}
};
</script>
<style>
#app {
font-family: "Poppins", Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
margin-top: 60px;
}
</style>
我想做的是 msg
组件 我想更改 App.vue 数据中的 msg
组件。但是当我更改值时,Vue 会发出警告:
所以我不知道下一步该做什么。请帮助我。
你根本不允许改变 props,你只能改变 data
个变量。
要解决您的问题,您可以执行以下操作。在组件上实现 v-model
,因此 msg
始终保持同步,在 App
中也是如此
App.vue
<template>
<div id="app">
<samples v-bind:msg="msg"></samples>
<msg v-model="msg"></msg>
</div>
</template>
<script>
import samples from "./components/samples.vue";
import msg from "./components/msg.vue";
export default {
name: "app",
components: {
samples,
msg
},
data: () => {
return {
msg: "Hello World"
};
}
};
</script>
msg.vue
<template>
<div>
<input type="text" v-model="selected" />
</div>
</template>
<script>
export default {
name: "msg",
props: ["value"],
computed: {
selected: {
get() {
return this.value;
},
set(value) {
return this.$emit('input', value)
}
}
}
};
</script>
不要使用 v-model
而是使用 $emit
消息组件
Vue.component('msg',{
props:["msg"],
template: `<div>
<input @keyup="changeMsg" :value="msg">
</div>`,
methods:{
changeMsg:function(e){
this.$emit("changed",e.target.value);
}
}
});
<msg @changed="msg = $event" :msg="msg"></msg>
1. 什么是 v-model
?
<input v-model="msg" />
基本上会转译为
<input :value="msg" @input="msg = $event.target.value" />
2. data
对比 props
2.1 data
应该是组件自包含的,而 props
是从父级传递的。
2.2 data
在组件内应该是可变的,props
不应该。为什么?因为 2.1.
3. mutating a prop locally is considered an anti-pattern in Vue 2
结果: 这是我更改的解决方案 只有 2 行代码 来自你的:
App.vue
<template>
<div id="app">
<samples v-bind:msg="msg"></samples>
<msg :msg="msg" @update:msg="msg = $event"></msg> // changed this line
</div>
</template>
msg.vue
<template>
<div>
<input type="text" :value="msg" @input="$emit('uddate:msg', $event.target.value)" /> // changed this line
</div>
</template>
一个简单的解决方案是使用 v-bind.sync。按照link查看文档和用法。通过使用它,您需要更改 2 行您的 代码才能使其正常工作:
在App.vue:
change
<msg :msg="msg"></msg>
to
<msg :msg.sync="msg"></msg>
在msg.vue:
change
<input type="text" v-model="msg" />
to
<input type="text" @input="$emit('update:msg',$event.target.value)" />
然而,这个是not recommended by Vue
这里我有两个组件:
msg.vue
<template>
<div>
<input type="text" v-model="msg" />
</div>
</template>
<script>
export default {
name: "msg",
props: ["msg"]
};
</script>
samples.vue
<template>
<div>
<h2>{{ msg }}</h2>
</div>
</template>
<script>
export default {
name: "samples",
props: ["msg"]
};
</script>
最后,
App.vue
<template>
<div id="app">
<samples v-bind:msg="msg"></samples>
<msg :msg="msg"></msg>
</div>
</template>
<script>
import samples from "./components/samples.vue";
import msg from "./components/msg.vue";
export default {
name: "app",
components: {
samples,
msg
},
data: () => {
return {
msg: "Hello World"
};
}
};
</script>
<style>
#app {
font-family: "Poppins", Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
margin-top: 60px;
}
</style>
我想做的是 msg
组件 我想更改 App.vue 数据中的 msg
组件。但是当我更改值时,Vue 会发出警告:
所以我不知道下一步该做什么。请帮助我。
你根本不允许改变 props,你只能改变 data
个变量。
要解决您的问题,您可以执行以下操作。在组件上实现 v-model
,因此 msg
始终保持同步,在 App
App.vue
<template>
<div id="app">
<samples v-bind:msg="msg"></samples>
<msg v-model="msg"></msg>
</div>
</template>
<script>
import samples from "./components/samples.vue";
import msg from "./components/msg.vue";
export default {
name: "app",
components: {
samples,
msg
},
data: () => {
return {
msg: "Hello World"
};
}
};
</script>
msg.vue
<template>
<div>
<input type="text" v-model="selected" />
</div>
</template>
<script>
export default {
name: "msg",
props: ["value"],
computed: {
selected: {
get() {
return this.value;
},
set(value) {
return this.$emit('input', value)
}
}
}
};
</script>
不要使用 v-model
而是使用 $emit
消息组件
Vue.component('msg',{
props:["msg"],
template: `<div>
<input @keyup="changeMsg" :value="msg">
</div>`,
methods:{
changeMsg:function(e){
this.$emit("changed",e.target.value);
}
}
});
<msg @changed="msg = $event" :msg="msg"></msg>
1. 什么是 v-model
?
<input v-model="msg" />
基本上会转译为
<input :value="msg" @input="msg = $event.target.value" />
2. data
对比 props
2.1 data
应该是组件自包含的,而 props
是从父级传递的。
2.2 data
在组件内应该是可变的,props
不应该。为什么?因为 2.1.
3. mutating a prop locally is considered an anti-pattern in Vue 2
结果: 这是我更改的解决方案 只有 2 行代码 来自你的:
App.vue
<template>
<div id="app">
<samples v-bind:msg="msg"></samples>
<msg :msg="msg" @update:msg="msg = $event"></msg> // changed this line
</div>
</template>
msg.vue
<template>
<div>
<input type="text" :value="msg" @input="$emit('uddate:msg', $event.target.value)" /> // changed this line
</div>
</template>
一个简单的解决方案是使用 v-bind.sync。按照link查看文档和用法。通过使用它,您需要更改 2 行您的 代码才能使其正常工作:
在App.vue:
change
<msg :msg="msg"></msg>
to
<msg :msg.sync="msg"></msg>
在msg.vue:
change
<input type="text" v-model="msg" />
to
<input type="text" @input="$emit('update:msg',$event.target.value)" />
然而,这个是not recommended by Vue