1. 基本框架,
<div id="app">
<cpn :number1="num1" :number2="num2"></cpn>
</div>
<template id="cpn">
<div>
<h2>{{number1}}</h2>
<input type="text" v-model>
<h2>{{number2}}</h2>
<input type="text" v-model>
</div>
</template>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js" type="text/javascript" charset="utf-8"></script>
<script type="text/javascript">
const app = new Vue({
el: '#app',
data: {
num1: 1,
num2: 2
},
components: {
cpn: {
template: "#cpn",
props: {
number1: Number,
number2: Number
}
}
}
})
</script>
- 需求:通过 input 输入内容,改变 实例的 num1, num2 以及子组件的 number1, number2的值
<template id="cpn">
<div>
<h2>{{number1}}</h2>
<input type="text" v-model="number1">
<h2>{{number2}}</h2>
<input type="text" v-model="number2">
</div>
</template>
- 之间将 input的 v-model 进行绑定到 number1 number2 中,则会报错
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. 避免直接改变属性,因为每当父组件重新渲染时,该值将被覆盖。相反,使用基于属性值的数据或计算属性。
修改如下:
<div id="app">
<cpn :number1="num1" :number2="num2"></cpn>
</div>
<template id="cpn">
<div>
<h2>props: {{number1}}</h2>
<h2>data: {{dnumber1}}</h2>
<input type="text" v-model="dnumber1">
<h2>props: {{number2}}</h2>
<h2>data: {{dnumber2}}</h2>
<input type="text" v-model="dnumber2">
</div>
</template>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js" type="text/javascript" charset="utf-8"></script>
<script type="text/javascript">
const app = new Vue({
el: '#app',
data: {
num1: 1,
num2: 2
},
components: {
cpn: {
template: "#cpn",
props: {
number1: Number,
number2: Number
},
data() {
return {
dnumber1: this.number1,
dnumber2: this.number2
}
}
}
}
})
</script>
- 可以将 input 中的 v-model 换成
:value="dnumber1" @input="dnumber1 = $event.target.value"
保持数据流是单向的,所以子组件不能修改父组件的数据
<div id="app">
<cpn :number1="num1"
:number2="num2"
@num1change="num1change"
@num2change="num2change"></cpn>
</div>
<template id="cpn">
<div>
<h2>props: {{number1}}</h2>
<h2>data: {{dnumber1}}</h2>
<input type="text" :value="dnumber1" @input="num1Input">
<h2>props: {{number2}}</h2>
<h2>data: {{dnumber2}}</h2>
<input type="text" :value="dnumber2" @input="num2Input">
</div>
</template>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js" type="text/javascript" charset="utf-8"></script>
<script type="text/javascript">
const app = new Vue({
el: '#app',
data: {
num1: 1,
num2: 2
},
methods: {
num1change(value) {
this.num1 = value;
},
num2change(value) {
this.num2 = value;
}
},
components: {
cpn: {
template: "#cpn",
props: {
number1: Number,
number2: Number
},
data() {
return {
dnumber1: this.number1,
dnumber2: this.number2
}
},
methods: {
num1Input(event) {
this.dnumber1 = event.target.value;
this.$emit('num1change', this.dnumber1)
},
num2Input(event) {
this.dnumber2 = event.target.value;
this.$emit('num2change', this.dnumber2)
}
}
}
}
})
</script>
这样可以通过input,进行修改 dnumber 的值,通过 子传父 事件$emit 发送到父组件,父组件通过 numchange进行修改 num的值
默认情况下,emit 传的参数类型为 string 类型
methods: {
num1change(value) {
// console.log(typeof value) //value 是字符串类型
this.num1 = parseFloat(value); //parseInt 将 value转为 float类型
},
num2change(value) {
this.num2 = parseFloat(value);
}
},
2. 完整代码
需求: 通过 input 输入内容,改变 实例的 num1, num2 以及子组件的 number1, number2的值
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<div id="app">
<cpn :number1="num1"
:number2="num2"
@num1change="num1change"
@num2change="num2change"></cpn>
</div>
<template id="cpn">
<div>
<h2>props: {{number1}}</h2>
<h2>data: {{dnumber1}}</h2>
<input type="text" :value="dnumber1" @input="num1Input">
<h2>props: {{number2}}</h2>
<h2>data: {{dnumber2}}</h2>
<input type="text" :value="dnumber2" @input="num2Input">
</div>
</template>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js" type="text/javascript" charset="utf-8"></script>
<script type="text/javascript">
const app = new Vue({
el: '#app',
data: {
num1: 1,
num2: 2
},
methods: {
num1change(value) {
// console.log(typeof value) //value 是字符串类型
this.num1 = parseFloat(value); //parseInt 将 value转为float类型
},
num2change(value) {
this.num2 = parseFloat(value);
}
},
components: {
cpn: {
template: "#cpn",
props: {
number1: Number,
number2: Number
},
data() {
return {
dnumber1: this.number1,
dnumber2: this.number2
}
},
methods: {
num1Input(event) {
this.dnumber1 = event.target.value;
this.$emit('num1change', this.dnumber1)
},
num2Input(event) {
this.dnumber2 = event.target.value;
this.$emit('num2change', this.dnumber2)
}
}
}
}
})
</script>
</body>
</html>
3. 扩展
在上面的情况下,下面的number 为上面的 number的 100倍。
methods: {
num1Input(event) {
//1. 将 input中 value赋值到 dnumber中
this.dnumber1 = event.target.value;
//2.为了父组件可以修改值,发出一个事件
this.$emit('num1change', this.dnumber1)
//3. 同时修改 dnumber的值
this.dnumber2 = this.dnumber1 * 100;
this.$emit('num2change', this.dnumber2)
},
num2Input(event) {
this.dnumber2 = event.target.value;
this.$emit('num2change', this.dnumber2)
this.dnumber1 = this.dnumber2 / 100;
this.$emit('num1change', this.dnumber1)
}
}
4. watch 实现
侦听器:watch 官方文档
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<div id="app">
<cpn :number1="num1"
:number2="num2"
@num1change="num1change"
@num2change="num2change"></cpn>
</div>
<template id="cpn">
<div>
<h2>props: {{number1}}</h2>
<h2>data: {{dnumber1}}</h2>
<input type="text" v-model="dnumber1">
<h2>props: {{number2}}</h2>
<h2>data: {{dnumber2}}</h2>
<input type="text" v-model="dnumber2">
</div>
</template>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js" type="text/javascript" charset="utf-8"></script>
<script type="text/javascript">
const app = new Vue({
el: '#app',
data: {
num1: 1,
num2: 2
},
methods: {
num1change(value) {
// console.log(typeof value) //value 是字符串类型
this.num1 = parseFloat(value); //parseInt 将 value转为float类型
},
num2change(value) {
this.num2 = parseFloat(value);
}
},
components: {
cpn: {
template: "#cpn",
props: {
number1: Number,
number2: Number
},
data() {
return {
dnumber1: this.number1,
dnumber2: this.number2
}
},
watch: {
dnumber1(newValue) {
this.dnumber2 = newValue * 100;
//改变Vue实例中的值,通过props改变number1
this.$emit("num1change", newValue);
},
dnumber2(newValue) {
this.dnumber1 = newValue / 100;
this.$emit("num2change", newValue)
}
}
}
}
})
</script>
</body>
</html>