读书网站建设策划书,蔚县网站建设wl17581,淘宝联盟 wordpress,网站外链资源大家好#xff0c;我是若川。最近组织了源码共读活动#xff0c;感兴趣的可以加我微信 ruochuan12 参与#xff0c;已进行了三个多月#xff0c;大家一起交流学习#xff0c;共同进步。前言vue简洁好用体现在很多个地方#xff0c;比如其内置了32修饰符#xff0c;可以很… 大家好我是若川。最近组织了源码共读活动感兴趣的可以加我微信 ruochuan12 参与已进行了三个多月大家一起交流学习共同进步。前言vue简洁好用体现在很多个地方比如其内置了32修饰符可以很方便我们阻止冒泡、阻止默认事件、鼠标事件处理、系统键盘事件等等让我们可以快速搞定业务简直不要太方便噢耽误您15分钟您可以收获32修饰符包括事件修饰符、鼠标修饰符、表单修饰符、系统修饰符等等的含义和使用如何利用webpack动态注册vue路由再也不手写路由配置啦文章中例子都放在了github源码上也可以点击直接看例子如何动态注册路由文中的每个修饰符例子都由一个页面承载聪明的你肯定不想手动引入几十个.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. 阻止冒泡的两种方式templatediv classparent clickonClickParent我是爸爸div classchild clickonClickChild我是儿子/div/div
/templateexport default {name: stop,methods: {onClickParent () {console.log(我是爸爸)},onClickChild () {console.log(我是儿子)}}
}点击子节点的时候因为事件冒泡的缘故不仅会打印出我是儿子还会打印我是爸爸。有什么办法可以阻止子节点的事件冒泡呢stop2.gif1 .stop只要加.stop修饰符即可阻止事件冒泡的及简方式很方便是不是。当添加上.stop修饰符时只会出现我是儿子templatediv classparent clickonClickParent我是爸爸div classchild click.stoponClickChild我是儿子/div/div
/templatestop.gif2. event.stopPropagation当然了我们也可以通过调用event.stopPropagation来阻止冒泡。不过更加推荐修饰符的做法这样你的函数会更加专注在逻辑处理上而不用关心DOM事件细节export default {name: stop,methods: {onClickChild (event) {console.log(我是儿子)event.stopPropagation()}}
}stop.gif2. 阻止默认事件的两种方式vue中阻止冒泡有两种方式那阻止默认事件呢1 .preventtemplatediv classpreventa hrefhttps://juejin.cn/ clickonNoPrevent点击跳转掘金/abr /br /a hrefhttps://juejin.cn/ click.preventonPrevent阻止默认事件无法跳转掘金/a/div
/templateexport default {name: prevent,methods: {onNoPrevent () {console.log(未阻止默认事件)},onPrevent () {console.log(阻止默认事件)}}
}只要添加.prevent轻松实现阻止默认事件prevent.gif2.event.preventDefault()和阻止冒泡一样我们也可以通过调用事件对象的preventDefault方法来阻止默认事件export default {name: prevent,methods: {onPrevent (event) {console.log(阻止默认事件)event.preventDefault()}}
}3 .capture默认情况下事件流是以冒泡(由里向外)的形式传递的如果想以捕获由外向里的形式应该怎么办呢templatediv classcapture parent click.captureonClickParent父节点div classchild click.captureonClickChild自节点/div/div
/templateexport default {name: capture,methods: {onClickParent () {console.log(我是父节点)},onClickChild () {console.log(我是子节点)}}
}不加catpture修饰符点击子节点会陆续打印我是父节点以及我是子节点加了之后则是反过来了capture.gif4 .self只有当event.target是当前元素自身时才会触发事件回调函数templatediv classself click.selfonClickSelfdiv classinner clickonClickInner/div/div
/templateexport default {name: self,methods: {onClickSelf () {console.log(我是self节点)},onClickInner () {console.log(我是inner节点)}}
}不加self修饰符的话点击inner节点也会触发self的事件加了之后只有触发事件的元素本身是self才会打印出我是self节点self.gif暂停一下修饰符的顺序如何理解已经回顾了4个修饰符单独使用的时候很容易理解但是注意官网有这么一句话image.png怎么理解呢我们来看两个栗子templatediv classorderdiv classorder-0a hrefhttps://juejin.cn/ classorder-parent click.self.preventonClickParent我是父节点会跳转掘金br /span classorder-child clickonClickChild我是子节点/span/ahr //divdiv classorder-2a hrefhttps://juejin.cn/ classorder-parent click.prevent.selfonClickParent我是父节点无法跳转掘金br /span classorder-child clickonClickChild我是子节点/span/a/div/div
/templateexport default {name: order,methods: {onClickParent () {console.log(我是父节点)},onClickChild () {console.log(我是子节点)}}
}您可以猜一下上面的代码会发生什么以下三点是可以明确的首先可以明确的是点击上面和下面的子节点都不会触发父节点的点击事件点击下面的父节点会打印出我是父节点但是不会跳转掘金点击上面的父节点会打印出我是父节点,也不会跳转掘金但是点击上面的子节点父节点会不会跳转至掘金呢答案是会为什么aclick.self.preventonClickParent的意思是当点击的元素是a元素本身时会阻止默认事件可以解释3不会发生跳转并且执行onClickParent回调。而点击span元素时由于冒泡的缘故点击事件会传递给a但是此时a会判断出该事件不是由自身触发的也就不会阻止默认事件(此时也就发生跳转了)当然也不会触发onClickParent回调同理来我们分析一下aclick.prevent.selfonClickParent不管是子节点还是自身点击都是先阻止默认事件只有当触发点击事件是a元素本身时才会执行onClickParent回调函数。order.gif回过头看你理解事件的顺序含义了吗image.png5. once顾名思义事件只会触发一次templatediv classonce click.onceonClickOnce只触发一次/div
/templateexport default {name: once,methods: {onClickOnce () {console.log(once我只会触发一次点击事件回调)}}
}触发一次点击之后任我再怎么点回调怎也不会触发了。once.gif6 .native我们知道在自定义组件上只能监听自定义事件一些原生事件比如click是没有办法直接触发的但是使用.native修饰符可以帮我们办到这点native.vuetemplatediv classnative-custominput typetext keydownonKeydown/div
/templateexport default {name: nativeCustom,methods: {onKeydown () {this.$emit(onKeydown)}}
}custom.vuetemplatediv classnative!-- 加上.native之后原生事件才得以监听成功 --NativeCustom onKeydownonKeydown click.nativeonClick //div
/templateimport NativeCustom from ../../components/native.vueexport default {name: native,components: {NativeCustom},methods: {onKeydown () {console.log(onKeydown)},onClick () {console.log(onClick)}}
}native.gif7 .passivevue对应 addEventListener 中的 passive 选项提供了 .passive 修饰符!-- 滚动事件的默认行为 (即滚动行为) 将会立即触发 --
!-- 而不会等待 onScroll 完成 --
!-- 这其中包含 event.preventDefault() 的情况 -- div v-on:scroll.passiveonScroll.../div这个修饰符对于滚动性能的提升一直没找到合适的例子跪求广大掘友有例子啊这个修饰符对于滚动性能的提升一直没找到合适的例子跪求广大掘友有例子啊这个修饰符对于滚动性能的提升一直没找到合适的例子跪求广大掘友有例子啊v-bind修饰符8 .sync当我们想要在父组件和子组件之间对某个属性值进行双向绑定时,有什么便捷的方式是的只要.sync修饰符即可办到父组件templatediv classsync-parent我是父组件: {{ text }}Child :text.synctext //div
/templateimport Child from ./child.vueexport default {name: SyncParent,data () {return {text: parent}},components: {Child,}
}子组件templatediv classchild我是子组件: input typetext v-modelvalue inputonInput/div
/templateexport default {name: child,props: {text: {type: String}},data () {return {value: this.text}},methods: {onInput () {// 注意这里必须是update:xxx的形式xxx即属性propthis.$emit(update:text, this.value)}}
}sync.gif9 .camel.camel 修饰符允许在使用 DOM 模板时将 v-bind property 名称驼峰化例如 SVG 的 viewBox propertysvg :view-box.camelviewBox/svg10 .prop关于.prop修饰符官网只有这句话 .prop 作为一个 DOM property 绑定而不是作为 attribute 绑定。。有啥作用通过自定义属性存储变量避免暴露数据防止污染 HTML 结构比如有以下代码templatediv classpropdiv classprop-item :my-nameprop/div// 最终变成了 div my-namehello prop classprop-item/divdiv classprop-item :my-name.propprop2/div// 最终变成了div classprop-item/divbutton clickonGetResult获取结果/button/div
/templateexport default {name: prop,data () {return {prop: hello prop,prop2: hello prop2}},methods: {onGetResult () {const $refProp this.$refs.propconst $refProp2 this.$refs.prop2console.log($refProp.getAttribute(my-name)) // hello propconsole.log($refProp2.getAttribute(my-name)) // null}}
}从示例上可以看出未使用.prop修饰符的my-name属性会绑定到dom节点的attribute从而出现暴露的情况。prop.gif鼠标修饰符当咱们想监听用户点击了左键、右键或者中键时也有修饰符可以快捷使用分别是.left、.right、middle来看个例子试试根据MDN MouseEvent.button介绍。image.png在最外层div.mouse监听mousedown事件看下用户点击的是鼠标哪个键三个button分别用三个修饰符快捷方式监听左键、中键、右键并打印出left、middle、righttemplatediv classmouse mousedownonMousedownbutton click.leftonClickBtn(left)left/buttonbutton click.middleonClickBtn(middle)middle/buttonbutton click.rightonClickBtn(right)right/button/div
/templateexport default {name: mouse,mounted () {},methods: {onClickBtn (msg) {console.log(msg)},onMousedown (event) {const mosueMsgMap {0: 鼠标左键,1: 鼠标中键,2: 鼠标右键}console.log(点击了, mosueMsgMap[event.button])}}
}没有带鼠标回来中键点击暂时不能演示后续会补上mouse.gif11 .left同上例子监听鼠标左键点击12 .right同上例子监听鼠标右键点击13 .middle同上例子监听鼠标中键点击表单相关修饰符14 .trim对于输入的内容希望可以过滤首尾空格应该怎么做呢templatediv classtrimdiv classtrim-iteminput typetext v-modelnamep用户名span{{ name }}/span/p/divdiv classtrim-iteminput typetext v-model.trimname2p用户名2span{{ name2 }}/span/p/div/div
/templateexport default {name: trim,data () {return {name: ,name2: ,}},watch: {name (newVal) {console.log(----${newVal}----)},name2 (newVal) {console.log(----${newVal}----)},}
}.trim修饰符可以很方便做到trim.gif15 .lazyv-model大家都很熟悉默认情况下每次input事件触发的时候都会将输入框的值与其绑定的数据进行实时同步。但是如果想要实现光标离开的时候再更新数据如何实现呢思路1 绑定change事件在事件回调中手动获取target的值思路2 直接使用.lazy修饰符即可达到效果templatediv classlazydiv classlazy-iteminput typetext v-modeltextp无.lazy: {{ text }}/p/divdiv classlazy-iteminput typetext v-model.lazytext2p.lazy: {{ text2 }}/p/div/div
/templateexport default {name: lazy,data () {return {text: ,text2: }}
}可以看到添加了.lazy修饰符之后第二个输入框输入的值不会实时反应在下面而是光标离开实text2的数据才更新了lazy.gif16 .number我们知道input输入框的type哪怕是number得到的值的类型也是string如果我们想直接拿到number类型的数据有不想麻烦的手动转换应该怎么办呢templatediv classnumberdiv classnumber-itemp无.number /pinput typenumber v-modelnumber/divdiv classnumber-itemptype:text .number /pinput typetext v-model.numbernumber1/divdiv classnumber-itemptype:number .number /pinput typenumber v-model.numbernumber2/div/div
/templateexport 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最后得到的值也是numbernumber.gif系统修饰符当点击事件或者键盘事件需要系统键同时按下才触发时.ctrl、.alt、.shift、.meta可以帮大忙噢如下代码全局监听keydown事件尝试看.ctrl、.alt、.shift、.meta是否被按下分别给四个按钮加上 .ctrl、.alt、.shift、.meta修饰符并配合点击事件验证是否同时按下指定按键再点击才会生效注明电脑ctrl键 点击估计和浏览器快捷配置冲突了导致没触发templatediv classsystemp{{ msg }}/pdiv classbuttonsbutton click.ctrlonClickButon(ctrl)ctrl/buttonbutton click.altonClickButon(alt)alt/buttonbutton click.shiftonClickButon(shift)shift/buttonbutton click.metaonClickButon(meta)meta/button/div/div
/templateexport 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}键点击事件才会发生)}}
}system.gif17 .ctrl仅在按下ctrl按键时才触发鼠标或键盘事件的监听器详细例子请看上面18 .alt仅在按下alt按键时才触发鼠标或键盘事件的监听器详细例子请看上面19 .shift仅在按下shift按键时才触发鼠标或键盘事件的监听器详细例子请看上面20 .meta仅在按下meta按键时才触发鼠标或键盘事件的监听器详细例子请看上面21 .exact严格来说这.exact不属于系统修饰符只是上面例子的写法有一个现象同时按下几个系统修饰键例如alt和shift既可以触发.alt也可以触发.shift。还是用上面的例子看一下下面的gif, 此时我同时按下了alt和shift对应的两个事件都可以触发system2.gif只想某个系统修饰键按下时才触发点击没有任何系统修饰符被按下的时候才触发点击要实现上面的需求.exact就派上用场了用上面的例子稍作改造templatediv classextrap{{ msg }}/pdiv classbuttonsbutton click.ctrl.exactonClickButon(ctrl)ctrl/buttonbutton click.alt.exactonClickButon(alt)alt/buttonbutton click.shift.exactonClickButon(shift)shift/buttonbutton click.meta.exactonClickButon(meta)meta/buttonbutton click.exactonClickButon(非系统键)非系统键/button/div/div
/templateexport 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}键点击事件才会发生)}}
}extra.gif按键修饰符在监听键盘事件时我们经常需要检查详细的按键再执行对应的逻辑vue也为我们内置了至少11的按键修饰符。如下代码我们分别给enter、tab、delete等按键指定了keydown事件当在指定的输入框中按下指定的键盘会打印出enter、tab、delete等其他按键在输入框中无法触发该consoletemplatediv classkey-modifiersdiv classkey-modifiers-itementer:input typetext keydown.enteronKeydown(enter)/divdiv classkey-modifiers-itemtab:input typetext keydown.tabonKeydown(tab)/div div classkey-modifiers-itemdelete:input typetext keydown.deleteonKeydown(delete)/div div classkey-modifiers-itemesc:input typetext keydown.esconKeydown(esc)/div div classkey-modifiers-itemspace:input typetext keydown.spaceonKeydown(space)/div div classkey-modifiers-itemup:input typetext keydown.uponKeydown(up)/div div classkey-modifiers-itemdown:input typetext keydown.downonKeydown(down)/div div classkey-modifiers-itemleft:input typetext keydown.leftonKeydown(left)/div div classkey-modifiers-itemright:input typetext keydown.rightonKeydown(right)/div div classkey-modifiers-itempage-down:input typetext keydown.page-downonKeydown(page-down)/div div classkey-modifiers-itempage-up:input typetext keydown.page-uponKeydown(page-up)/div /div
/templateexport default {name: keyModifiers,methods: {onKeydown (keyName) {console.log(keyName)}}
}key-modifiers.gif22 .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
}div classcustominput typetext keydown.qf1Keydown
/divexport default {name: custom,methods: {f1Keydown () {console.log(按下了q)}}
}custom.gif最近组建了一个江西人的前端交流群如果你是江西人可以加我微信 ruochuan12 私信 江西 拉你进群。推荐阅读1个月200人一起读了4周源码我历时3年才写了10余篇源码文章但收获了100w阅读老姚浅谈怎么学JavaScript我在阿里招前端该怎么帮你可进面试群················· 若川简介 ·················你好我是若川毕业于江西高校。现在是一名前端开发“工程师”。写有《学习源码整体架构系列》10余篇在知乎、掘金收获超百万阅读。从2014年起每年都会写一篇年度总结已经写了7篇点击查看年度总结。同时最近组织了源码共读活动帮助1000前端人学会看源码。公众号愿景帮助5年内前端人走向前列。识别上方二维码加我微信、拉你进源码共读群今日话题略。欢迎分享、收藏、点赞、在看我的公众号文章~