接着前面的内容:https://www.cnblogs.com/yanggb/p/12609450.html

组件的自定义事件

这里来学习一下组件中的自定义事件。

事件名

不同于组件名和prop,事件名不存在任何自动化的大小写转化,而是触发的事件名需要完全匹配监听这个事件所用的名称。

举个例子,如果触发一个camelCase名字的事件:

this.$emit('myEvent')

则监听这个名字的kebab-case版本是不会有任何效果的:

<!-- 没有效果 -->
<my-component v-on:my-event="doSomething"></my-component>

这是因为,不同于组件名和prop,事件名并不会被用作以一个javascript变量名或者属性名,所以就没有理由使用camelCase或PascalCase了。并且,由于【v-on】事件监听器在dom模板中会被自动转换为小写(因为html是大小写不敏感的),即【v-on:myEvent】会变成【v-on:myevent】,也就导致了myEvent不可能被监听到。

因此官方文档的建议是始终使用kebab-case的事件名,使用kebab-case的事件名,使用kebab-case的事件名。

自定义组件的【v-model】

一个组件上的【v-model】指令默认会利用名为【value】的prop和名为【input】的事件,但是像单选框或复选框等特殊类型的输入控件,则可能会将value属性用于不同的目的。因此,vue在2.2.0+的版本中提供了【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)">
`
})
<base-checkbox v-model="lovingVue"></base-checkbox>

在上面的组件定义中,使用了model选项来声明该组件是利用的【checked】的prop和名为【change】的事件,并通过【v-bind:checked】和【v-on:change】来绑定值和事件。因此在后面的组件实例中,lovingVue的值就会被传入到这个名为checked的prop中。同时,当<base-checkbox>触发一个change事件并附带一个新的值得时候,这个lovingVue的属性也会被同步更新。另外要注意的是,你仍然需要在组件的props选项中声明checked这个prop。

将原生的事件绑定到组件中

你可能会有很多次想要在一个组件的根元素上直接监听一个原生的事件。这时,你可以使用【v-on】指令的【.native】修饰符。

<base-input v-on:focus.native="onFocus"></base-input>

这在有的时候是很有用的,不过在你尝试监听一个类似<input>的非常特定的元素的时候,这就并不是一个好的主意。比如上述<base-input>组件可能做了如下重构,所以根元素实际上是一个<label>元素:

<label>
{{ label }}
<input
v-bind="$attrs"
v-bind:value="value"
v-on:input="$emit('input', $event.target.value)">
</label>

这时候,父级的【.native】监听器将静默失败,并不会产生任何的报错,但是onFocus处理函数却不会被调用,因为<label>元素并没有原生的onfocus事件。

为了解决这个问题,vue提供了一个【$listeners】属性,它是一个对象,里面包含了作用在这个组件上的所有监听器,例如:

{
focus: function (event) { /* ... */ }
input: function (value) { /* ... */ },
}

而有了这个【$listeners】属性,你就可以配合【v-on="$listeners"】指令将所有的事件监听器都指向这个组件的某个特定的子元素。

另外,对于类似<input>的你希望它也可以配合【v-model】指令工作的组件(在【v-model】指令的基础上加以触发另外的事件)来说,为这些监听器创建一个类似下述inputLiseners的计算属性通常是非常有用的:

Vue.component('base-input', {
inheritAttrs: false,
props: ['label', 'value'],
computed: {
inputListeners: function () {
var vm = this
// Object.assign将所有的对象合并为一个新对象
return Object.assign({},
// 我们从父级添加所有的监听器
this.$listeners,
// 然后我们添加自定义监听器,或覆写一些监听器的行为
{
// 这里确保组件配合v-model的工作
input: function (event) {
vm.$emit('input', event.target.value)
}
}
)
}
},
template: `
<label>
{{ label }}
<input
v-bind="$attrs"
v-bind:value="value"
v-on="inputListeners">
</label>
`
})

现在<base-input>组件就是一个完全透明的包裹器了,它可以完全像一个普通的<input>元素一样使用:所有跟它相同的的attribute和监听器都可以正常工作。

【.sync】修饰符

在有些情况下,我们可能需要对一个prop进行双向绑定。而不幸的是,真正的双向绑定会带来维护上的问题,因为子组件可以修改父组件,且在父组件和子组件都没有明显的改动来源。这是官方文档推荐以【update:myPropName】的模式触发事件的原因。举个例子,在一个包含title属性的假设组件中,我们可以使用以下方法表达对其赋值的意图:

this.$emit('update:title', newTitle)

然后父组件就可以监听那个事件,并根据需要更新一个本地的数据属性,例如:

<text-document
v-bind:title="doc.title"
v-on:update:title="doc.title = $event"></text-document>

而vue在2.3.0+的版本中新增了【.sync】修饰符作为这种模式的缩写,以此来方便开发,减少代码量。

<text-document v-bind:title.sync="doc.title"></text-document>

这里要注意的是,带有【.sync】修饰符的【v-bind】指令不能和表达式一起使用(例如【v-bind:title.sync="doc.title + '!'"】就是无效的)。取而代之的你只能提供想要的属性名,类似【v-model】。

而当我们用一个对象同时设置多个prop的时候,也可以将这个【.sync】修饰符和【v-bind】指令配合使用。

<text-document v-bind.sync="doc"></text-document>

这样就会把doc对象中的每一个属性(如title)都作为一个独立的prop传进去,然后各自添加用于更新的【v-on】监听器。

此外要注意的是,将【v-bind.sync】用于一个字面量的对象上,例如【v-bind.sync="{ title:doc.title }"】是无法正常工作的,因为在解析这样一个复杂的表达式的时候,有很多的边缘情况需要考虑。

"我还是很喜欢你,像星辰闪耀苍穹顶,不惧孤寂。"

vue2.x学习笔记(十五)的更多相关文章

  1. python3.4学习笔记(十五) 字符串操作(string替换、删除、截取、复制、连接、比较、查找、包含、大小写转换、分割等)

    python3.4学习笔记(十五) 字符串操作(string替换.删除.截取.复制.连接.比较.查找.包含.大小写转换.分割等) python print 不换行(在后面加上,end=''),prin ...

  2. (转载)西门子PLC学习笔记十五-(数据块及数据访问方式)

    一.数据块 数据块是在S7 CPU的存储器中定义的,用户可以定义多了数据块,但是CPU对数据块数量及数据总量是有限制的. 数据块与临时数据不同,当逻辑块执行结束或数据块关闭,数据块中的数据是会保留住的 ...

  3. (C/C++学习笔记) 十五. 构造数据类型

    十五. 构造数据类型 ● 构造数据类型概念 Structured data types 构造数据类型 结构体(structure), 联合体/共用体 (union), 枚举类型(enumeration ...

  4. MySQL学习笔记十五:优化(2)

    一.数据库性能评测关键指标 1.IOPS:每秒处理的IO请求次数,这跟磁盘硬件相关,DBA不能左右,但推荐使用SSD. 2.QPS:每秒查询次数,可以使用show status或mysqladmin ...

  5. Java基础学习笔记十五 集合、迭代器、泛型

    Collection 集合,集合是java中提供的一种容器,可以用来存储多个数据. 在前面的学习中,我们知道数据多了,可以使用数组存放或者使用ArrayList集合进行存放数据.那么,集合和数组既然都 ...

  6. angular学习笔记(十五)-module里的'服务'

    本篇介绍angular中的模块:module 在笔记(二)http://www.cnblogs.com/liulangmao/p/3711047.html里已经讲到过模块,这篇主要讲模块的 '服务' ...

  7. Java学习笔记十五:Java中的成员变量和局部变量

    Java中的成员变量和局部变量 一:成员变量: 成员变量在类中定义,用来描述对象将要有什么 成员变量可以被本类的方法使用,也可以被其他类的方法使用,成员变量的作用域在整个类内部都是可见的 二:局部变量 ...

  8. MYSQL进阶学习笔记十五:MySQL 的账号权限赋予!(视频序号:进阶_33,34)

    知识点十六:MySQL的账号权限赋予(33) 一.MySQL权限简介 关于mysql的权限简单的理解就是mysql允许你做你全力以内的事情,不可以越界.比如只允许你执行select操作,那么你就不能执 ...

  9. 数据结构和算法学习笔记十五:多路查找树(B树)

    一.概念 1.多路查找树(multi-way search tree):所谓多路,即是指每个节点中存储的数据可以是多个,每个节点的子节点数也可以多于两个.使用多路查找树的意义在于有效降低树的深度,从而 ...

  10. JavaScript权威设计--JavaScript脚本化文档Document与CSS(简要学习笔记十五)

    1.Document与Element和TEXT是Node的子类. Document:树形的根部节点 Element:HTML元素的节点 TEXT:文本节点   >>HtmlElement与 ...

随机推荐

  1. postgre安装和使用(R&Python)

    安装postgre http://helianthus-code.lofter.com/post/1dfe03e0_1c68233aa 这里选C更好 这里口令密码输入就是黑的 我装的时候反复报错,查了 ...

  2. coding++:Spring Boot全局事务解释及使用(一)

    Spring 事务的入口: TxAdviceBeanDefinitionParser 解释 <tx:advice/> 这里将解析tx的配置. @Override protected Cla ...

  3. Springcloud zuul 实现API 网关

    1,https://github.com/Netflix/zuul zuul 网关文档 2,什么是网关 网关就是客户端进行访问的时候,先经过网关服务器,再由网关服务器进行转发到真实的服务器.类似于Ng ...

  4. Mysql数据库的基本操作(1)

    一.启动数据库 1. 我的电脑(此电脑)--->右键点击[管理]--->[服务和应用程序]--->[服务] 找到MySQL8.0可以选择手动启动或者自动启动. 2.可以直接通过命令行 ...

  5. ovirt 重新安装主机失败

    重新安装主机引擎事件报错 Host engine installation failed. Failed to execute Ansible host-deploy role. Please che ...

  6. CodeForces 190C STL

    Portal: http://codeforces.com/problemset/problem/190/C 一道卡输入输出的蛋疼题 题意:给你一个由pair和int所组成的沙茶字符串(最大含有1e5 ...

  7. 粘包处理现象及其解决方案——基于NewLife.Net网络库的管道式帧长粘包处理方法

    [toc] #1.粘包现象 每个TCP 长连接都有自己的socket缓存buffer,默认大小是8K,可支持手动设置.粘包是TCP长连接中最常见的现象,如下图 socket缓存中有5帧(或者说5包)心 ...

  8. Pointer Lock API(1/3):Pointer Lock 的总体认识

    前言 指针锁定(Pointer Lock),以前也叫鼠标锁定,提供了基于鼠标随时间的移动(如deltaΔ)的输入方法,不仅仅是视窗区域鼠标的绝对位置.指针锁定让你能够访问原始的鼠标移动,将鼠标事件的目 ...

  9. wireshark一开,无线网络就断开

    最近在研究wireshark 笔记本连着wifi,开始抓包后,无线网就断了 查了半天,需要把捕获-->选项里的监控模式去掉就行了

  10. Nginx知多少系列之(二)安装

    目录 1.前言 2.安装 3.配置文件详解 4.Linux下托管.NET Core项目 5.Linux下.NET Core项目负载均衡 6.Linux下.NET Core项目Nginx+Keepali ...