
require.context()在实际开发中,发必法绝大部分人都是须知以组件化的方式进行开发。随之而来就有了许多的道的大秘组件需要引入。比如以下场景:
import outExperInfo from "@/components/userInfo/outExperInfo"; import baseUserInfo from "@/components/userInfo/baseUserInfo"; import technicalExperInfo from "@/components/userInfo/technicalExperInfo"; import skillExperInfo from "@/components/userInfo/skillExperInfo"; components:{ outExperInfo,发必法 baseUserInfo, technicalExperInfo, skillExperInfo } 这样写并没有错,但是须知仔细观察发现写了很多重复的代码,这个时候利用require.context()可以写成:
const path = require(path) const files = require.context(@/components/userInfo,道的大秘 false, /\.vue$/) const userComponents = { } files.keys().forEach(key => { const name = path.basename(key, .vue) userComponents[name] = files(key).default || files(key) }) components:userComponents 这样不管需要引入多少组件,都可以使用这一个方法。发必法
路由的须知按需加载随着项目功能模块的增加,引入的道的大秘文件数量剧增。如果不做任何处理,发必法那么首屏加载会相当的须知缓慢,这个时候,道的大秘路由按需加载就闪亮登场了。发必法
webpack< 2.4 时 { path:/,须知 name:home, components:resolve=>require([@/components/home],resolve) } webpack> 2.4 时 { path:/, name:home, components:()=>import(@/components/home) } import()方法是由es6提出的,动态加载返回一个Promise对象,道的大秘then方法的参数是加载到的服务器托管模块。类似于Node.js的require方法,主要import()方法是异步加载的。
动态组件场景:如果项目中有tab切换的需求,那么就会涉及到组件动态加载,一般写法如下:
<component v-bind:is="currentTab"></component> 这样写也没有错,但是如果这样写的话,每次切换的时候,当前组件都会销毁并且重新加载下一个组件。会消耗大量的性能,所以就起到了作用。
<keep-alive> <component v-bind:is="currentTab"></component> </keep-alive> 有的小伙伴会说,这样切换虽然不消耗性能了,但是切换效果没有动画效果了,别着急,这时可以利用内置的。
<transition> <keep-alive> <component v-bind:is="currentTab"></component> </keep-alive> </transition> components和vue.component前者是局部注册组件,用法如下:
export default{ components:{ home} } 后者是全局注册组件,主要针对一些全局使用的组件,网站模板用法如下:
Vue.component(home,home) Vue.nextTickVue.nextTick()方法在下次DOM更新循环结束之后执行延迟回调,因此可以页面更新加载完毕之后再执行回调函数。下面介绍几个常用场景:
场景一
<template> <div> <div ref = "ref"/> </div> </template> <script> export default { created(){ console.log(this.$refs.ref) //undefined }) } } </script> 因为这个时候created阶段dom并未完全渲染完成,所以获取值为undefined,我们对其改造一下:
<template> <div> <div ref = "ref"/> </div> </template> <script> export default { created(){ Vue.nextTick(()=>{ console.log(this.$refs.ref) }) //<div></div> }) } } </script> 这样就可以获取到dom了。
场景二
<template> <div> <div v-if="visible" ref = "ref"/> </div> </template> <script> export default { data() { return { visible: false }; }, showRef() { this.visible = true; console.log(this.$refs.ref); //undefined }, } } </script> 因为这个时候虽然visible的值为true,但是页面dom并没有更新完成,所以获取值为undefined,我们对其改造一下:
<template> <div> <div v-if="visible" ref = "ref"/> </div> </template> <script> export default { data() { return { visible: false }; }, showRef() { this.visible = true; Vue.nextTick(()=>{ console.log(this.$refs.ref) }) //<div></div> }, } } </script> 这样就可以获取到dom了。
Vue.directive场景:官方给我们提供了很多指令,但是我们如果想将文字变成指定的颜色定义成指令使用,这个时候就需要用到Vue.directive,示例如下:
// 全局定义 Vue.directive("change-color",function(el,binding,vnode){ el.style["color"]= binding.value; }) // 使用 <template> <div v-change-color>{ { message}} </div> </template> <script> export default{ data(){ return{ color:green } } } </script> Vue.set()当在项目中直接设置数组的某一项的值,或者直接设置对象的某个属性值,这个时候,你会发现页面并没有更新。这是因为Object.defineprototype()限制,监听不到变化,具体的可以查看我的另一篇文章:
vue对象数组数据变化,页面不渲染
事件修饰符
.stop:阻止冒泡 .prevent:阻止默认行为 .self:仅绑定元素自身触发 .once: 2.1.4 新增,只触发一次 passive: 2.3.0 新增,滚动事件的默认行为 (即滚动行为) 将会立即触发,不能和.prevent 一起使用 .sync 修饰符 从 2.3.0 起vue重新引入了 .sync 修饰符,但是这次它只是作为一个编译时的语法糖存在。源码下载它会被扩展为一个自动更新父组件属性的 v-on 监听器。示例代码如下:
<comp :foo.sync="bar"></comp> 会被扩展为:
<comp :foo="bar" @update:foo="val => bar = val"></comp> 当子组件需要更新 foo 的值时,它需要显式地触发一个更新事件:
this.$emit(update:foo, newValue) 长列表性能优化(数据冻结)众所周知,vue会通过object.defineProperty对数据进行劫持,进而实现页面实时相应数据的变化,然而我们有些时候,需要的仅仅就是纯粹的展示数据,因为数据不会有任何改变,我们就不需要vue来劫持我们的数据。在数据量很大的情况下,这可以很明显的减少加载时间。
那么如何实现禁止vue劫持我们的数据尼?可以通过object.freeze方法来冻结数据,冻结之后数据也就不能再修改了。示例如下:
let longList = [ { name:monkeysoft}, ... ] this.longList = Object.freeze(longList)