参考文档 $watch
什么时候使用它?
我们都知道,当父组件向子组件传值时,子组件通过props 可以接收到父组件传过来的值
但这样只能接收父组件的静态值:比如以下代码:
下边是个数字框组件展示这个问题:
父组件
<template>
<div id="app">
<one v-model="value" :max='10' :min="0"></one>
</div>
</template>
<script>
import one from './components/one'
export default {
components:{
one
},
data(){
return{
value:5
}
}
}
</script>
子组件
<template>
<div class="three">
{{currentValue}}
</div>
</template>
<script>
export default {
props:{
max:{
type:Number,
default:Infinity
},
min:{
type:Number,
default:-Infinity
},
value:{
type:Number,
default:0
}
},
data(){
return{
currentValue:this.value
}
}
};
</script>
以上父子组件,当你手动改变父组件中的 value 值得时候,在子组件都能立马展示出来,
且数据立马会更新出来!但实际开发中我们的数据都是动态传给子组件的,
接着你就会发现一个问题来,当我们传一个动态的数据时,发现子组件的数据竟然没有变化?
怎么解决呢,这时候就要用到vue的$watch了
----------------------------------------
贴个代码演示 动态数据 传入子组件中 子组件的数据不会改变
在刚才的父组件中加入一个点击事件,我们让这个数字每次点击+1
<template>
<div id="app">
<one v-model="value" :max='10' :min="0"></one>
<button @click="addvalue">+</button>
</div>
</template>
<script>
import one from './components/one'
export default {
components:{
one
},
data(){
return{
value:5
}
},
methods:{
addvalue(){
//每次点击数据都加了1
this.value++
}
}
}
</script>
子组件不变
<template>
<div class="three">
{{currentValue}}
</div>
</template>
<script>
export default {
props:{
max:{
type:Number,
default:Infinity
},
min:{
type:Number,
default:-Infinity
},
value:{
type:Number,
default:0
}
},
data(){
return{
currentValue:this.value
}
}
};
</script>
完整代码 ,数据改变 watch监听 (一个数字框输入框组件)
父组件
<template>
<div id="app">
<one v-model="value" :max='10' :min="0"></one>
<br>
{{ value }}
<br>
<button @click="addvalue">+</button>
</div>
</template>
<script>
import one from './components/one'
export default {
components:{
one
},
data(){
return{
value:5
}
},
methods:{
addvalue(){
this.value++
}
}
}
</script>
子组件
<template>
<div class="three">
<!-- {{currentValue}}z -->
<input type="text" :value="currentValue" @change="handelChange">
<button @click="handelDown" :disabled="currentValue <= min">-</button>
<button @click="handelUp" >+</button>
</div>
</template>
<script>
// 判断是不是数字
function isValueNumber(value){
return (/(^-?[0-9]+\.{1}\d+$)|(^-?[1-9][0-9]*$)|(^-?0{1}$)/).test(value +'')
}
export default {
props:{
max:{
type:Number,
default:Infinity
},
min:{
type:Number,
default:-Infinity
},
value:{
type:Number,
default:0
}
},
data(){
return{
currentValue:this.value
}
},
// 加入 watch 监听数据变化
watch:{
// 接收两个参数 第一个是改变后的新值newvalue,第二个是老值oldvalue,
// 只写一个,默认是新值
value(val){
// 这样重新赋值后,就得到了父组件动态改变的数据
this.currentValue = val
},
// 实际业务中,当子组件值改变时,有时候也会通知父组件,这时我们也要监听子组件的数据变化
currentValue(val){
this.$emit('input',val)
}
},
mounted () {
this.updataValue(this.value)
},
methods:{
// 点击-1时,得到更新的值,告诉父组件
handelDown(){
if(this.currentValue <= this.min) return;
this.currentValue -=1;
},
// 点击+1 ,得到更新后的值告诉父组件
handelUp(){
if(this.currentValue >= this.max) return;
this.currentValue +=1;
},
updataValue(val){
if(val > this.max) val = this.max
if(val <this.min) val = min
this.currentValue = val
},
// 失去焦点时,得到更新后的值
handelChange(){
let val = event.target.value.trim();
console.log(val)
let max = this.max;
let min = this.min;
if(isValueNumber(val)){
val = Number(val)
this.currentValue = val
if(val > max){
this.currentValue = max
}else if(val < min){
this.currentValue = min
}else{
event.target.value = min
}
}else{
event.target.value = this.currentValue
}
}
}
};
</script>