用了几个月Vue一直很纠结自定义组件的v-model实现,最近开始学习React时,React中受控组件与状态提升的理念与v-model不谋而合。

转载请注明地址: https://www.cnblogs.com/sonoda-umi/p/9750188.html

在Vue与React中其实都存在单向数据流的概念,只不过Vue中通过各种语法糖被弱化了,比如React与Vue中的props都是单向传输数据的。在React中如果想实现类似于v-model的功能,需要这样实现:

父组件:

class Calculator extends React.Component {
constructor(props) {
super(props);
this.handleCelsiusChange = this.handleCelsiusChange.bind(this);
this.handleFahrenheitChange = this.handleFahrenheitChange.bind(this);
this.state = {temperature: '', scale: 'c'};
} handleCelsiusChange(temperature) {
this.setState({scale: 'c', temperature});
} handleFahrenheitChange(temperature) {
this.setState({scale: 'f', temperature});
} render() {
const scale = this.state.scale;
const temperature = this.state.temperature;
const celsius = scale === 'f' ? tryConvert(temperature, toCelsius) : temperature;
const fahrenheit = scale === 'c' ? tryConvert(temperature, toFahrenheit) : temperature; return (
<div>
<TemperatureInput
scale="c"
temperature={celsius}
onTemperatureChange={this.handleCelsiusChange} /> <TemperatureInput
scale="f"
temperature={fahrenheit}
onTemperatureChange={this.handleFahrenheitChange} /> <BoilingVerdict
celsius={parseFloat(celsius)} /> </div>
);
}
}

子组件:

class TemperatureInput extends React.Component {
constructor(props) {
super(props);
this.handleChange = this.handleChange.bind(this);
} handleChange(e) {
this.props.onTemperatureChange(e.target.value);
} render() {
const temperature = this.props.temperature;
const scale = this.props.scale;
return (
<fieldset>
<legend>Enter temperature in {scaleNames[scale]}:</legend>
<input value={temperature}
onChange={this.handleChange} />
</fieldset>
);
}
}

这是一个输入水温从而监控水是否沸腾的一个小组件。子组件是一个温度输入的input控件,父组件是由两个温度输入(华氏与摄氏)与一个现实水是否沸腾的指示器组成。父组件存在一个state作为唯一数据源用于存放温度等值于状态,温度通过子组件的prop传入子组件内部通过input的value属性显示在基础输入框中,当在基础输入框中触发输入时间时,onChange事件触发由prop传入的onTempreture事件并附带变化后的值,再由父组件的handleCelsiusChange/handleFahrenheitChange事件处理方法将基础输入框传来的值写入state中,再由state通过prop将温度传入子组件完成一次数据的更新。这其中其实已经完成了对Vue中基础组件v-model的理解与自定义组件v-model的理解。

转载请注明地址: https://www.cnblogs.com/sonoda-umi/p/9750188.html

在Vue官方文档中,对原生组件v-model的解释是这样的:

<input
v-bind:value="searchText"
v-on:input="searchText = $event.target.value"
>

v-model其实是上面写法的语法糖。其实就是将this.searchText的值通过名为value的prop传入input组件内,而后当input事件触发时将事件带来的input的新值写入this.searchText中,然后根据this.searchText中值的变化通过value的prop传入input控件完成input控件上值的变化,如果去掉v-on...后,这个控件将变为一个只读控件。

对于自定义组件,文档中有这样的解释:

一个组件上的 v-model 默认会利用名为 value 的 prop 和名为 input 的事件,但是像单选框、复选框等类型的输入控件可能会将 value 特性用于不同的目的。model 选项可以用来避免这样的冲突:

Vue.component('base-checkbox', {
model: {
prop: 'checked',
event: 'change'
},
props: {
checked: Boolean
},
template: `
<input
type="checkbox"
v-bind:checked="checked"
v-on:change="$emit('change', $event.target.checked)"
>
`
})
现在在这个组件上使用 v-model 的时候:
<base-checkbox v-model="lovingVue"></base-checkbox>
这里的 lovingVue 的值将会传入这个名为 checked 的 prop。同时当 <base-checkbox> 触发一个 change 事件并附带一个新的值的时候,这个 lovingVue 的属性将会被更新。

其实就是将原来v-model默认使用的名为value的prop与名为input的event自定义一个名字使用,在上面自定义组件中存在

props: {
checked: Boolean
}

说明checked本质上还是一个prop,然后在子组件的model属性中将自定义的prop与event注册,而触发model中event时也就是通过触发子组件的事件在父组件中修改绑定自定义prop的变量的值的过程,这样这个过程就很明显了:

1.父组件创建一个名为tmp变量绑定名为checked的prop的值(已被修饰为v-model)并根据父组件中tmp值的变化将变化后的值传入子组件中,引起子组件checkbox状态变化;

2.子组件中checkbox被勾选,触发checkbox的change事件,通过this.$emit方法触发子组件的change事件并将change事件产生的新值传入;

3.因为在model属性中已将v-model语法糖中event注册为change(换成其他名字也都可以),v-model会自动将子组件传来的值传入tmp变量中;

4.Vue监听到tmp值的变化,执行第一步,更新子组件中checkbox的状态;

其实上面的子组件可以换个写法更容易理解:

Vue.component('base-checkbox', {
model: {
prop: 'checked',
event: 'test'
},
props: {
checked: Boolean
},
template: `
<input
type="checkbox"
v-bind:checked="checked"
v-on:change="$emit('test', $event.target.checked)"
>
`
})

父组件中调用时可以这样写:

<base-checkbox :checked="something" @test="something='子组件中的$event.target.value'"></base-checkbox>

这样对v-model的理解也就一目了然了。

转载请注明地址: https://www.cnblogs.com/sonoda-umi/p/9750188.html

自定义组件v-model的实质性理解的更多相关文章

  1. vue 自定义封装组件 使用 model 选项

    自定义组件的 v-model 一个组件上的 v-model 默认会利用名为 value 的 prop 和名为 input 的事件,但是像单选框.复选框等类型的输入控件可能会将 value 特性用于不同 ...

  2. 【Spring注解驱动开发】自定义组件如何注入Spring底层的组件?看了这篇我才真正理解了原理!!

    写在前面 最近,很多小伙伴出去面试都被问到了Spring问题,关于Spring,细节点很多,面试官也非常喜欢问一些很细节的技术点.所以,在 Spring 专题中,我们尽量把Spring的每个技术细节说 ...

  3. Android开发之自定义组件和接口回调

    说到自定义控件不得不提的就是接口回调,在Android开发中接口回调用的还是蛮多的.在这篇博客开始的时候呢,我想聊一下iOS的自定义控件.在iOS中自定义控件的思路是继承自UIView, 在UIVie ...

  4. vue框架之自定义组件中使用v-model

    通常 vue在html常见表单空间支持v-model双向绑定例如 <input v-model="message" placeholder="edit me&quo ...

  5. vue自定义组件中的v-model简单解释

    在使用iview框架的时候,经常会看到组件用v-model双向绑定数据,与传统步骤父组件通过props传值子组件,子组件发送$emit来修改值相比,这种方式避免操作子组件的同时再操作父组件,显得子组件 ...

  6. 前端 | 自定义组件 v-model:Vue 如何实现双向绑定

    v-model 是 Vue 中一个常用的指令,常用于表单中的数据绑定.如下基本用法想必大家都很熟悉,data 中的 checked 属性的值就会随着多选框的状态实时变化. <el-checkbo ...

  7. Vue3 SFC 和 TSX 方式自定义组件实现 v-model

    1 v-model 1.1 理解 v-model v-model 是 vue3 中的一个内置指令,很多表单元素都可以使用这个属性,如 input.checkbox 等,咱可以在自定义组件中实现 v-m ...

  8. Android自定义组件

    [参考的原文地址] http://blog.csdn.net/l1028386804/article/details/47101387效果图: 实现方式: 一:自定义一个含有EditText和Butt ...

  9. PhoneGap: Android 自定义组件

    Hello Core Demo Plugin Development(组件部署): http://docs.phonegap.com/en/2.0.0/guide_plugin-development ...

随机推荐

  1. Juniper 防火墙端口映射设置

    首先我们登陆到juniper防火墙控制界面 默认地址大家都知道(192.168.1.1) 默认用户和密码netsscreen 下面介绍登陆界面: 让我们开始配置吧 依次展开policy → Polic ...

  2. Spring定时器——时间设置规则

    平时经常有一些写Spring定时器的需求,但是每次要设置定时器的时间的时候,老是既不住,到处找别人的博客又各种不爽,所以就自己记录一份吧,顺便整理一下. org.springframework.sch ...

  3. netty笔记(一)--Demo

    Netty是一个Java开源框架,用于传输数据.由server和client组成,封装了Java nio,支持TCP, UDP等协议.这里写了一Demo EchoClientHandler.java ...

  4. linux服务器上创建svn版本库

    1. 创建存放各个svn版本库的目录svnrepos(自己定义路径) -bash: cd /usr/local/apache/htdocs/ -bash: mkdir svnrepos 2. 假设我要 ...

  5. sort遇到的问题

    var arr = [2,10,6,9,7,8]; var arr1 = arr.sort(); var arr2 = arr.sort(function(a,b){ if (a>b){ ret ...

  6. Python爬虫之requests模块(1)

    一.引入 Requests 唯一的一个非转基因的 Python HTTP 库,人类可以安全享用. 警告:非专业使用其他 HTTP 库会导致危险的副作用,包括:安全缺陷症.冗余代码症.重新发明轮子症.啃 ...

  7. 关于Android那些事

    1.开发Activity步骤 第一步:写一个类继承Activity 第二步:重写oncreate方法 第三步:在主配置文件中注册activity <activity android:name=& ...

  8. 软件项目技术点(2)——Canvas之平移translate、旋转rotate、缩放scale

    AxeSlide软件项目梳理   canvas绘图系列知识点整理 画布操作介绍 画布绘图的环境通过translate(),scale(),rotate(), setTransform()和transf ...

  9. C++基础--指针,&的用法

    #include "stdafx.h" #include <stdio.h> #include <string.h> int main() { ] = {, ...

  10. matlab练习程序(Hilbert图像置乱)

    正好刚写了Hibert生成曲线,不如再加一篇应用的程序. 关于Hilbert图像置乱,我在网上搜的应用领域主要集中在数字水印和图像加密上,而这两个领域我都没怎么接触过. 大部分的图像置乱都是如下图的置 ...