开发中常见的 32+ Vue 修饰符,你掌握几种啦?
开发中常见的 32+ Vue 修饰符,你掌握几种啦?
前端有道;)
前端有道
微信号 leadingEnd
功能介绍 给小白逆袭前端高手的学习社区,定期分享前端面试、前端最新技术和实战技巧等系列内容。如果你前端基础差,缺项目经验,这里就是为你量身定制的!如有需要,公众号后台准备了一些备战大厂面试资料,可以关注获取!
2021-11-08 08:00
收录于话题
以下文章来源于前端胖头鱼 ,作者前端胖头鱼
[
前端胖头鱼 .
曾在阿里跑堂的 “小二”,在美团烧得一壶“好开水” 的逗比前端。也许你我素未谋面,但很可能相见恨晚,关注我,一起快乐学前端。](#)
前言
vue 简洁好用体现在很多个地方,比如其内置了 32 + 修饰符,可以很方便我们阻止冒泡、阻止默认事件、鼠标事件处理、系统键盘事件等等,让我们可以快速搞定业务,简直不要太方便噢!!!
耽误您 15 分钟您可以收获:
- 32 + 修饰符(包括事件修饰符、鼠标修饰符、表单修饰符、系统修饰符等等)的含义和使用
- 如何利用 webpack 动态注册 vue 路由,再也不手写路由配置啦!
文章中例子都放在了 github 源码[1]上,也可以点击直接看例子[2]
如何动态注册路由?
文中的每个修饰符例子都由一个页面承载,聪明的你肯定不想手动引入几十个. vue 文件并配置路由.
有什么办法可以帮我们自动完成路由注册呢?
1. 文件目录结构
目录结构(已去除其他文件目录)大概如下
`├── package.json
└── src
├── App.vue
├── main.js
├── router.js
└── views
├── About.vue
├── Home.vue
└── modifiers
├── capture.vue
├── once.vue
├── order.vue
├── passive.vue
├── prevent.vue
├── self.vue
└── stop.vue
└── …
`
2. 期望的路由配置
最终给到
vue-router
的配置大概长下面这个样子,每个配置最重要的部分分别是path
、name
和component
`[
{
“path”: “/home”,
“name”: “home”,
“component”: {
“name”: “Home”,
“methods”: {},
“staticRenderFns”: [],
“_compiled”: true,
“_scopeId”: “data-v-fae5bece”,
“beforeCreate”: [
null
],
“beforeDestroy”: [
null
],
“file”:”src/views/Home.vue”
}
},
{
“path”: “/modifiers/capture”,
“name”: “modifiersCapture”,
“component”: {
“name”: “capture”,
“methods”: {},
“staticRenderFns”: [],
“_compiled”: true,
“_scopeId”: “data-v-63b4eeee”,
“beforeCreate”: [
null
],
“beforeDestroy”: [
null
],
“file”:”src/views/modifiers/capture.vue”
}
},
… // 其他路由配置
]
`
3. require.context 实现动态注册路由
借助 webpack require.context[3] 的能力,可以非常方便地实现上面目录到路由配置的映射工作,源码如下
`const registerRoutes = () => { const contextInfo = require.context('./views', true, /.vue$/) const routes = contextInfo.keys().map((filePath) => { // filePath 形如 ./Home.vue、./modifiers/capture.vue // path 我们希望是 / home、/modifiers/capture // 所以需要把开头的./ 和. vue 都替换为空 const path = filePath.toLowerCase().replace(/^\.|\.vue/g, '') // name 的话将 / home、/modifiers/capture 转成小驼峰即可 // 把开头的 / 先替换掉,再把第一个 / 后的单词变成大写就可以了 const name = path.replace(/^\//, '').replace(/\/(\w)/, ($0, $1) => $1.toUpperCase()) // 通过 require 去读取. vue 文件内容 const component = require(
./views${filePath.replace(/^./, ‘’)}`).default
return {
path,
name,
component
}
})
return routes
}
``
效果
经过上面的简单处理,动态注册路由就完成啦!您也可以点击 vue-demos[4]查看效果
事件修饰符
1. 阻止冒泡的两种方式
`
我是爸爸
我是儿子
export default {
name: ‘stop’,
methods: {
onClickParent () {
console.log(‘我是爸爸’)
},
onClickChild () {
console.log(‘我是儿子’)
}
}
}
`
点击子节点的时候因为事件冒泡的缘故不仅会打印出我是儿子
还会打印我是爸爸
。有什么办法可以阻止子节点的事件冒泡呢?
stop2.gif
1 .stop
只要加. stop 修饰符即可,阻止事件冒泡的及简方式,很方便是不是。
当添加上.stop
修饰符时,只会出现我是儿子
`
我是爸爸
我是儿子
`
stop.gif
2. event.stopPropagation
当然了,我们也可以通过调用
event.stopPropagation
来阻止冒泡。不过更加推荐修饰符的做法,这样你的函数会更加专注在逻辑处理上,而不用关心 DOM 事件细节
`export default {
name: ‘stop’,
methods: {
onClickChild (event) {
console.log(‘我是儿子’)
event.stopPropagation()
}
}
}
`
stop.gif
2. 阻止默认事件的两种方式
vue 中阻止冒泡有两种方式,那阻止默认事件呢?
1 .prevent
export default {
name: ‘prevent’,
methods: {
onNoPrevent () {
console.log(‘未阻止默认事件’)
},
onPrevent () {
console.log(‘阻止默认事件’)
}
}
}
`
只要添加.prevent
轻松实现阻止默认事件
prevent.gif
2.event.preventDefault()
和阻止冒泡一样,我们也可以通过调用事件对象的
preventDefault
方法来阻止默认事件
`export default {
name: ‘prevent’,
methods: {
onPrevent (event) {
console.log(‘阻止默认事件’)
event.preventDefault()
}
}
}
`
3 .capture
默认情况下,事件流是以
冒泡
(由里向外) 的形式传递的,如果想以捕获(由外向里)
的形式应该怎么办呢?
`
父节点
export default {
name: ‘capture’,
methods: {
onClickParent () {
console.log(‘我是父节点’)
},
onClickChild () {
console.log(‘我是子节点’)
}
}
}
`
不加catpture
修饰符,点击子节点会陆续打印我是父节点以及我是子节点,加了之后,则是反过来了
capture.gif
4 .self
只有当
event.target
是当前元素自身时才会触发事件回调函数
`
export default {
name: ‘self’,
methods: {
onClickSelf () {
console.log(‘我是 self 节点’)
},
onClickInner () {
console.log(‘我是 inner 节点’)
}
}
}
`
不加self
修饰符的话,点击inner
节点也会触发self
的事件,加了之后只有触发事件的元素本身是self
,才会打印出我是 self 节点
self.gif
暂停一下:修饰符的顺序如何理解?
已经回顾了 4 个修饰符,单独使用的时候很容易理解,但是注意官网有这么一句话
image.png
怎么理解呢?我们来看两个栗子
`
我是父节点,会跳转掘金
我是子节点
我是父节点,无法跳转掘金
我是子节点
export default {
name: ‘order’,
methods: {
onClickParent () {
console.log(‘我是父节点’)
},
onClickChild () {
console.log(‘我是子节点’)
}
}
}
`
您可以猜一下,上面的代码会发生什么,以下三点是可以明确的?
- 首先可以明确的是点击上面和下面的子节点都不会触发父节点的点击事件
- 点击下面的父节点会打印出我是父节点,但是不会跳转掘金
- 点击上面的父节点会打印出我是父节点,也不会跳转掘金
但是点击上面的子节点,父节点会不会跳转至掘金呢?答案是会
为什么?
a@click.self.prevent="onClickParent"
的意思是当点击的元素是 a 元素本身时,会阻止默认事件(可以解释 3,不会发生跳转),并且执行onClickParent
回调。
而点击 span 元素时,由于冒泡的缘故,点击事件会传递给 a,但是此时 a 会判断出该事件不是由自身触发的也就不会阻止默认事件
(此时也就发生跳转了),当然也不会触发onClickParent
回调
同理来我们分析一下a@click.prevent.self="onClickParent"
不管是子节点还是自身点击,都是先阻止默认事件,只有当触发点击事件是 a 元素本身时才会执行onClickParent
回调函数。
order.gif
回过头看,你理解事件的顺序含义了吗?
image.png
5. once
顾名思义,事件只会触发一次
`
只触发一次
export default {
name: ‘once’,
methods: {
onClickOnce () {
console.log(‘once,我只会触发一次点击事件回调’)
}
}
}
`
触发一次点击之后,任我再怎么点,回调怎也不会触发了。
once.gif
6 .native
我们知道在自定义组件上,只能监听自定义事件,一些原生事件(比如 click)是没有办法直接触发的,但是使用
.native
修饰符可以帮我们办到这点
native.vue
`
export default {
name: ‘nativeCustom’,
methods: {
onKeydown () {
this.$emit(‘onKeydown’)
}
}
}
`
custom.vue
`
import NativeCustom from ‘../../components/native.vue’
export default {
name: ‘native’,
components: {
NativeCustom
},
methods: {
onKeydown () {
console.log(‘onKeydown’)
},
onClick () {
console.log(‘onClick’)
}
}
}
`
native.gif
7 .passive
vue 对应
addEventListener
中的passive
选项[5]提供了.passive
修饰符
<br />
这个修饰符对于滚动性能的提升,一直没找到合适的例子,跪求广大掘友有例子啊
这个修饰符对于滚动性能的提升,一直没找到合适的例子,跪求广大掘友有例子啊
这个修饰符对于滚动性能的提升,一直没找到合适的例子,跪求广大掘友有例子啊
v-bind 修饰符
8 .sync
当我们想要在
父组件
和子组件
之间对某个属性值进行双向绑定时, 有什么便捷的方式?是的只要.sync
修饰符即可办到
父组件
`
我是父组件: {{text}}
import Child from ‘./child.vue’
export default {
name: ‘SyncParent’,
data () {
return {
text: ‘parent’
}
},
components: {
Child,
}
}
`
子组件
`
我是子组件:
export default {
name: ‘child’,
props: {
text: {
type: String
}
},
data () {
return {
value: this.text
}
},
methods: {
onInput () {
// 注意这里,必须是 update:xxx 的形式 xxx 即属性 prop
this.$emit(‘update:text’, this.value)
}
}
}
`
sync.gif
9 .camel
.camel
修饰符允许在使用 DOM 模板时将v-bind
property 名称驼峰化,例如 SVG 的viewBox
property:
`
`
10 .prop
关于. prop 修饰符官网只有这句话
.prop
作为一个 DOM property 绑定而不是作为 attribute 绑定。`。
有啥作用?
- 通过自定义属性存储变量,避免暴露数据
- 防止污染 HTML 结构
比如有以下代码
`
// 最终变成了
// 最终变成了