一、制作微调器可能遇到的问题采用以下几点参考解决:
(1)制作微调器使用的props接收的父组件传递过来的数据是“单向数据流”
(2)props接收的数据不能再子组件中赋值,因为props接收的数据在子组件中是只读的
(3) props接收的数据不能在子组件中使用v-model进行双向绑定
二、解决方案,可以使用一个数据区data作为中专变量
(1)在子组件的数据区设置一个中转变量current,其初值是父组件传递过来的value属性的取值。
(2)在子组件的文本框中使用v-model双向绑定current
(3)所有的文本框数据修改(增、减、判断是否超过范围)都是用current来实现
(4)还需要再父组件的数据区创建一个变量buyCount,用来和current实现双向绑定
A .在子组件中侦听value:当value发生变化时,将这种变化赋给current
B .在子组件中侦听current:当current发生变化时,将current的值传递给父组件
三、以下是通过data作为中专变量解决的方案:
// HTML
<my-spinner :min="1" :max="50" :step="1" :value="buyCount" @custom="custom"></my-spinner>
//Vue代码部分
Vue.component("my-spinner",{
template:`
<div class="spinner">
<button class="minus" @click="minusClick">-</button>
<input type="text" v-model.number="current" @blur="inputBlur">
<button class="plus" @click="plusClick">+</button>
</div>
`,
props: {
min:{
type:Number
},
max:{
type:Number
},
step:{
type:Number,
defalut:1
},
value:{
type:Number
}
},
data(){
return{
current:this.value //从父组件传递过来的value属性的中转变量
}
},
methods:{
//加号按钮的单击事件
plusClick(){
if (this.current<=this.max-this.step){
this.current+=this.step;
}
},
//减号按钮的单击事件
minusClick(){
if (this.current>=this.min+this.step){
this.current-=this.step;
}
},
//鼠标释放焦点事件
inputBlur(){
if (this.current>this.max){
this.current=this.max
}
if (this.current<this.min){
this.current=this.min
}
},
watch:{
value(newValue){ //本质是在侦听父组件的buyCount
this.current=newValue
},
current(newValue){ //当current变化时需要将新值传递给buyCount
this.$emit("custom",newValue);
}
}
}
})
new Vue({
el:"#app",
data:{
buyCount:10
},
methods:{
custom(Value){
this.buyCount=Value
}
}
})
四、使用data作为中转变量太过于繁琐,一般还是通过语法糖和computed作为中转变量来解决较好,以下是通过computed作为中转变量来解决的办法:
//HTML代码:
<my-spinner :min="1" :max="50" :step="1" v-model="buyCount"></my-spinner>
Vue.component("my-spinner",{
template:`
<div class="spinner">
<button class="minus" @click="minusClick">-</button>
<input type="text" v-model.number="current" @blur="inputBlur">
<button class="plus" @click="plusClick">+</button>
</div>
`,
props: {
min:{
type:Number
},
max:{
type:Number
},
step:{
type:Number,
defalut:1
},
value:{
type:Number
}
},
computed:{
current:{
get(){
return this.value
},
set(newValue){
this.$emit("input", newValue)
}
}
},
methods:{
plusClick(){
if (this.current+this.step<=this.max){
this.current=this.current+this.step
}
},
minusClick(){
if (this.current-this.step>=this.min){
this.current=this.current-this.step
}
},
inputBlur(){
if (this.current>this.max){
this.current=this.max
}
if (this.current<this.min){
this.current=this.min
}
}
}
})
new Vue({
el:"#app",
data:{
buyCount:10
}
})
五、第二种方法使用了语法糖,使用v-model直接对组件进行绑定
(1)、无论采用data变量还是computed作为中转变量,组件的开发都具备以下两个阶段:
A .自定义属性(自定义属性名:value):
<my-spinner :value="buyCount"></my-spinner>
父组件向子组件传递数据:提供初值。
B .自定义事件(自定义事件名:custom):
<my-spinner @custom="custom"></my-spinner>
子组件向父组件传递数据:提供结果。
(2)、将v-model指令绑定在组件上:为组件制定与之双向绑定的父组件数据区变量
<my-spinner :min="1" :max="50" v-model="buyCount"></my-spinner>