【建议收藏】面试官贼喜欢问的|【建议收藏】面试官贼喜欢问的 32+ vue 修饰符,你掌握几种啦()
前言
vue简洁好用体现在很多个地方,比如其内置了32+修饰符,可以很方便我们阻止冒泡、阻止默认事件、鼠标事件处理、系统键盘事件等等,让我们可以快速搞定业务,简直不要太方便噢!!!耽误您15分钟您可以收获:
- 32+修饰符(包括事件修饰符、鼠标修饰符、表单修饰符、系统修饰符等等)的含义和使用
- 如何利用webpack动态注册vue路由,再也不手写路由配置啦!
如何动态注册路由?
文中的每个修饰符例子都由一个页面承载,聪明的你肯定不想手动引入几十个.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 的能力,可以非常方便地实现上面目录到路由配置的映射工作,源码如下
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(/^\./, '')}`).defaultreturn {
path,
name,
component
}
})return routes
}
效果
经过上面的简单处理,动态注册路由就完成啦!您也可以点击 vue-demos查看效果
事件修饰符 1. 阻止冒泡的两种方式
我是爸爸我是儿子export default {
name: 'stop',
methods: {
onClickParent () {
console.log('我是爸爸')
},
onClickChild () {
console.log('我是儿子')
}
}
}
点击子节点的时候因为事件冒泡的缘故不仅会打印出
我是儿子
还会打印我是爸爸
。有什么办法可以阻止子节点的事件冒泡呢?文章图片
1 .stop
只要加.stop修饰符即可,阻止事件冒泡的及简方式,很方便是不是。当添加上
.stop
修饰符时,只会出现我是儿子
我是爸爸我是儿子
文章图片
2. event.stopPropagation
当然了,我们也可以通过调用
event.stopPropagation
来阻止冒泡。不过更加推荐修饰符的做法,这样你的函数会更加专注在逻辑处理上,而不用关心DOM事件细节
export default {
name: 'stop',
methods: {
onClickChild (event) {
console.log('我是儿子')
event.stopPropagation()
}
}
}
文章图片
2. 阻止默认事件的两种方式
vue中阻止冒泡有两种方式,那阻止默认事件呢?1 .prevent
点击跳转掘金
阻止默认事件,无法跳转掘金export default {
name: 'prevent',
methods: {
onNoPrevent () {
console.log('未阻止默认事件')
},
onPrevent () {
console.log('阻止默认事件')
}
}
}
只要添加
.prevent
轻松实现阻止默认事件文章图片
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
修饰符,点击子节点会陆续打印我是父节点以及我是子节点,加了之后,则是反过来了文章图片
4 .self
只有当
event.target
是当前元素自身时才会触发事件回调函数
export default {
name: 'self',
methods: {
onClickSelf () {
console.log('我是self节点')
},
onClickInner () {
console.log('我是inner节点')
}
}
}
不加
self
修饰符的话,点击inner
节点也会触发self
的事件,加了之后只有触发事件的元素本身是self
,才会打印出我是self节点
文章图片
暂停一下:修饰符的顺序如何理解?
已经回顾了4个修饰符,单独使用的时候很容易理解,但是注意官网有这么一句话
文章图片
怎么理解呢?我们来看两个栗子
我是父节点,会跳转掘金
我是子节点我是父节点,无法跳转掘金
我是子节点export default {
name: 'order',
methods: {
onClickParent () {
console.log('我是父节点')
},
onClickChild () {
console.log('我是子节点')
}
}
}
【【建议收藏】面试官贼喜欢问的|【建议收藏】面试官贼喜欢问的 32+ vue 修饰符,你掌握几种啦()】您可以猜一下,上面的代码会发生什么,以下三点是可以明确的?
- 首先可以明确的是点击上面和下面的子节点都不会触发父节点的点击事件
- 点击下面的父节点会打印出我是父节点,但是不会跳转掘金
- 点击上面的父节点会打印出我是父节点,也不会跳转掘金
为什么?
a@click.self.prevent="onClickParent"
的意思是当点击的元素是a元素本身时,会阻止默认事件(可以解释3,不会发生跳转),并且执行onClickParent
回调。而点击span元素时,由于冒泡的缘故,点击事件会传递给a,但是此时a会判断出该事件不是由自身触发的也就
不会阻止默认事件
(此时也就发生跳转了),当然也不会触发onClickParent
回调同理来我们分析一下
a@click.prevent.self="onClickParent"
不管是子节点还是自身点击,都是先阻止默认事件,只有当触发点击事件是a元素本身时才会执行
onClickParent
回调函数。回过头看,你理解事件的顺序含义了吗?
文章图片
5. once
顾名思义,事件只会触发一次
只触发一次export default {
name: 'once',
methods: {
onClickOnce () {
console.log('once,我只会触发一次点击事件回调')
}
}
}
触发一次点击之后,任我再怎么点,回调怎也不会触发了。
文章图片
6 .native
我们知道在自定义组件上,只能监听自定义事件,一些原生事件(比如click)是没有办法直接触发的,但是使用
.native
修饰符可以帮我们办到这点
native.vueexport 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')
}
}
}
文章图片
7 .passive
vue对应addEventListener
中的passive
选项提供了.passive
修饰符
...
这个修饰符对于滚动性能的提升,一直没找到合适的例子,跪求广大掘友有例子啊
这个修饰符对于滚动性能的提升,一直没找到合适的例子,跪求广大掘友有例子啊
这个修饰符对于滚动性能的提升,一直没找到合适的例子,跪求广大掘友有例子啊
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)
}
}
}
文章图片
9 .camel
.camel
修饰符允许在使用 DOM 模板时将v-bind
property 名称驼峰化,例如 SVG 的viewBox
property:
10 .prop
关于.prop修饰符官网只有这句话
.prop
作为一个 DOM property 绑定而不是作为 attribute 绑定。`。
有啥作用?- 通过自定义属性存储变量,避免暴露数据
- 防止污染 HTML 结构
// 最终变成了 // 最终变成了
export default {
name: 'prop',
data () {
return {
prop: 'hello prop',
prop2: 'hello prop2'
}
},
methods: {
onGetResult () {
const $refProp = this.$refs.prop
const $refProp2 = this.$refs.prop2console.log($refProp.getAttribute('my-name')) // hello prop
console.log($refProp2.getAttribute('my-name')) // null
}
}
}
从示例上可以看出未使用
.prop
修饰符的my-name
属性会绑定到dom节点的attribute,从而出现暴露的情况。鼠标修饰符
当咱们想监听用户点击了根据MDN MouseEvent.button,介绍。左键
、右键
或者中键
时也有修饰符可以快捷使用,分别是.left
、.right
、middle
,来看个例子试试
文章图片
在最外层
div.mouse
监听mousedown
事件,看下用户点击的是鼠标哪个键,三个button
分别用三个修饰符快捷方式监听左键
、中键
、右键
并打印出left
、middle
、right
export default {
name: 'mouse',
mounted () {},
methods: {
onClickBtn (msg) {
console.log(msg)
},
onMousedown (event) {
const mosueMsgMap = {
0: '鼠标左键',
1: '鼠标中键',
2: '鼠标右键'
}
console.log('点击了', mosueMsgMap[event.button])
}
}
}
没有带鼠标回来,中键点击暂时不能演示,后续会补上
11 .left
同上例子,监听鼠标左键点击12 .right
同上例子,监听鼠标右键点击13 .middle
同上例子,监听鼠标中键点击表单相关修饰符 14 .trim
对于输入的内容,希望可以
过滤首尾空格
应该怎么做呢?
用户名:{{ name }}
用户名2:{{ name2 }}
export default {
name: 'trim',
data () {
return {
name: '',
name2: '',
}
},
watch: {
name (newVal) {
console.log(`'----${newVal}----'`)
},
name2 (newVal) {
console.log(`'----${newVal}----'`)
},
}
}
.trim修饰符可以很方便做到
15 .lazy
思路1: 绑定change事件,在事件回调中手动获取target的值v-model
大家都很熟悉,默认情况下,每次input事件
触发的时候都会将输入框的值与其绑定的数据进行实时同步。但是如果想要实现光标离开的时候再更新数据如何实现呢?
思路2: 直接使用
.lazy
修饰符即可达到效果无.lazy: {{ text }}
.lazy: {{ text2 }}
export default {
name: 'lazy',
data () {
return {
text: '',
text2: ''
}
}
}
可以看到添加了.lazy修饰符之后,第二个输入框输入的值不会实时反应在下面,而是光标离开实,
text2
的数据才更新了文章图片
16 .number
我们知道input
输入框的type
哪怕是number
得到的值的类型也是string
,如果我们想直接拿到number
类型的数据,有不想麻烦的手动转换应该怎么办呢?
无.number
type:text .number
type:number .number
export default {
name: 'lazy',
data () {
return {
number: 0,
number1: '',
number2: '',
}
},
watch: {
number (newVal) {
console.log(typeof newVal, newVal)
},
number1 (newVal) {
console.log(typeof newVal, newVal)
},
number2 (newVal) {
console.log(typeof newVal, newVal)
},
}
}
- 第一个输入框的类型是number,但是得到的值是string
- 第二个输入框的类型是text,但是添加了number修饰符,得到的值可以是number(如果这个值无法被
parseFloat()
解析,则会返回原始的值。) - 第三个输入框的类型是number,最后得到的值也是number
系统修饰符
当点击事件或者键盘事件需要系统键同时按下才触发时如下代码.ctrl
、.alt
、.shift
、.meta
可以帮大忙噢!
- 全局监听keydown事件,尝试看
.ctrl
、.alt
、.shift
、.meta
是否被按下 - 分别给四个按钮加上
.ctrl
、.alt
、.shift
、.meta
修饰符并配合点击事件,验证是否同时按下指定按键,再点击才会生效
{{ msg }}
export default {
name: 'system',
data () {
return {
msg: ''
}
},
mounted () {
this.onListenSystemKeyDown()
},
methods: {
onListenSystemKeyDown () {
document.addEventListener('keydown', (event) => {
let msg = '按下了'if (event.ctrlKey) {
msg += 'ctrl键'
} else if (event.altKey) {
msg += 'alt键'
} else if (event.shiftKey) {
msg += 'shift键'
} else if (event.metaKey) {
msg += 'meta键'
} else {
msg += '其他键'
}this.msg = msg
}, false)
},
onClickButon (key) {
console.log(`只有同时按下${key}键,点击事件才会发生`)
}
}
}
17 .ctrl
仅在按下ctrl按键时才触发鼠标或键盘事件的监听器,详细例子请看上面18 .alt
仅在按下alt按键时才触发鼠标或键盘事件的监听器,详细例子请看上面19 .shift
仅在按下shift按键时才触发鼠标或键盘事件的监听器,详细例子请看上面20 .meta
仅在按下meta按键时才触发鼠标或键盘事件的监听器,详细例子请看上面21 .exact
严格来说这还是用上面的例子,看一下下面的gif, 此时我同时按下了alt和shift,对应的两个事件都可以触发.exact
不属于系统修饰符,只是上面例子的写法有一个现象,同时按下几个系统修饰键(例如alt和shift)既可以触发.alt
也可以触发.shift
。
文章图片
- 只想某个系统修饰键按下时才触发点击
- 没有任何系统修饰符被按下的时候才触发点击
.exact
就派上用场了,用上面的例子稍作改造{{ msg }}
export default {
name: 'extra',
data () {
return {
msg: ''
}
},
mounted () {
this.onListenSystemKeyDown()
},
methods: {
onListenSystemKeyDown () {
document.addEventListener('keydown', (event) => {
let msg = '按下了'if (event.ctrlKey) {
msg += 'ctrl键'
} else if (event.altKey) {
msg += 'alt键'
} else if (event.shiftKey) {
msg += 'shift键'
} else if (event.metaKey) {
msg += 'meta键'
} else {
msg += '其他键'
}this.msg = msg
}, false)
},
onClickButon (key) {
console.log(`只有同时按下${key}键,点击事件才会发生`)
}
}
}
按键修饰符
在监听键盘事件时,我们经常需要检查详细的按键再执行对应的逻辑,vue也为我们内置了至少11+的按键修饰符。如下代码,我们分别给
enter
、tab
、delete
等按键指定了keydown
事件,当在指定的输入框中按下指定的键盘,会打印出enter
、tab
、delete
等,其他按键在输入框中无法触发该consoleenter:
tab:
delete:
esc:
space:
up:
down:
left:
right:
page-down:
page-up:
export default {
name: 'keyModifiers',
methods: {
onKeydown (keyName) {
console.log(keyName)
}
}
}
22 .enter
在按下enter按键时才触发鼠标或键盘事件的监听器,详细例子请看上面23 .tab
在按下tab按键时才触发鼠标或键盘事件的监听器,详细例子请看上面24 .delete
在按下delete按键时才触发鼠标或键盘事件的监听器,详细例子请看上面25 .esc
在按下esc按键时才触发鼠标或键盘事件的监听器,详细例子请看上面26 .space
在按下space按键时才触发鼠标或键盘事件的监听器,详细例子请看上面27 .up
在按下up按键时才触发鼠标或键盘事件的监听器,详细例子请看上面28 .down
在按下down按键时才触发鼠标或键盘事件的监听器,详细例子请看上面29 .left
在按下left按键时才触发鼠标或键盘事件的监听器,详细例子请看上面30 .right
在按下right按键时才触发鼠标或键盘事件的监听器,详细例子请看上面31 .page-down
在按下(fn + down)按键时才触发鼠标或键盘事件的监听器,详细例子请看上面32 .page-up
在按下(fn + up)按键时才触发鼠标或键盘事件的监听器,详细例子请看上面如何自定义按键修饰符
vue本身给我们内置了很多实用的按键修饰符,大部分情况下可以满足我们的日常需求了,那么有没有办法可以自定义按键修饰符呢?通过以下配置即可定义一个属于我们自己的按键修饰符, 比如我们定义q为按下q的快捷键。
Vue.config.keyCodes = {
q: 81
}export default {
name: 'custom',
methods: {
f1Keydown () {
console.log('按下了q')
}
}
}
文章图片
不说再见
以上就是胖头鱼对vue修饰符学习和了解的内容啦!欢迎大家补充和评论交流。O(∩_∩)O哈哈~
文章中例子都放在了github源码上,也可以点击直接看例子
推荐阅读
- 宽容谁
- 我要做大厨
- 增长黑客的海盗法则
- 画画吗()
- 2019-02-13——今天谈梦想()
- 远去的风筝
- 三十年后的广场舞大爷
- 叙述作文
- 20190302|20190302 复盘翻盘
- 学无止境,人生还很长