近年来,vue越来越火,使用它的人也越来越多。vue基本用法很容易上手,但是还有很多优化的写法你就不一定知道了。本文列举了一些vue常用的开发技巧。
require.context()
在实际开发中,绝大部分人都是以组件化的方式进行开发。随之而来就有了许多的组件需要引入。比如以下场景:
- importoutExperInfofrom"@/components/userInfo/outExperInfo";
- importbaseUserInfofrom"@/components/userInfo/baseUserInfo";
- importtechnicalExperInfofrom"@/components/userInfo/technicalExperInfo";
- importskillExperInfofrom"@/components/userInfo/skillExperInfo";
- components:{
- outExperInfo,
- baseUserInfo,
- technicalExperInfo,
- skillExperInfo
- }
这样写并没有错,但是仔细观察发现写了很多重复的代码,这个时候利用require.context()可以写成:
- constpath=require('path')
- constfiles=require.context('@/components/userInfo',false,/\.vue$/)
- constuserComponents={}
- files.keys().forEach(key=>{
- constname=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切换的需求,那么就会涉及到组件动态加载,一般写法如下:
- <componentv-bind:is="currentTab"></component>
这样写也没有错,但是如果这样写的话,每次切换的时候,当前组件都会销毁并且重新加载下一个组件。会消耗大量的性能,所以就起到了作用。
- <keep-alive>
- <componentv-bind:is="currentTab"></component>
- </keep-alive>
有的小伙伴会说,这样切换虽然不消耗性能了,但是切换效果没有动画效果了,别着急,这时可以利用内置的。
- <transition>
- <keep-alive>
- <componentv-bind:is="currentTab"></component>
- </keep-alive>
- </transition>
components和vue.component
前者是局部注册组件,用法如下:
- exportdefault{
- components:{home}
- }
后者是全局注册组件,主要针对一些全局使用的组件,用法如下:
- Vue.component('home',home)
Vue.nextTick
Vue.nextTick()方法在下次DOM更新循环结束之后执行延迟回调,因此可以页面更新加载完毕之后再执行回调函数。下面介绍几个常用场景:
场景一
- <template>
- <div>
- <divref="ref"/>
- </div>
- </template>
- <script>
- exportdefault{
- created(){
- console.log(this.$refs.ref)
- //undefined
- })
- }
- }
- </script>
因为这个时候created阶段dom并未完全渲染完成,所以获取值为undefined,我们对其改造一下:
- <template>
- <div>
- <divref="ref"/>
- </div>
- </template>
- <script>
- exportdefault{
- created(){
- Vue.nextTick(()=>{
- console.log(this.$refs.ref)
- })
- //<div></div>
- })
- }
- }
- </script>
这样就可以获取到dom了。
场景二
- <template>
- <div>
- <divv-if="visible"ref="ref"/>
- </div>
- </template>
- <script>
- exportdefault{
- data(){
- return{
- visible:false
- };
- },
- showRef(){
- this.visible=true;
- console.log(this.$refs.ref);
- //undefined
- },
- }
- }
- </script>
因为这个时候虽然visible的值为true,但是页面dom并没有更新完成,所以获取值为undefined,我们对其改造一下:
- <template>
- <div>
- <divv-if="visible"ref="ref"/>
- </div>
- </template>
- <script>
- exportdefault{
- 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>
- <divv-change-color>{{message}}
- </div>
- </template>
- <script>
- exportdefault{
- 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方法来冻结数据,冻结之后数据也就不能再修改了。示例如下:
- letlongList=[
- {name:'monkeysoft'},
- ...
- ]
- this.longList=Object.freeze(longList)
©本文为清一色官方代发,观点仅代表作者本人,与清一色无关。清一色对文中陈述、观点判断保持中立,不对所包含内容的准确性、可靠性或完整性提供任何明示或暗示的保证。本文不作为投资理财建议,请读者仅作参考,并请自行承担全部责任。文中部分文字/图片/视频/音频等来源于网络,如侵犯到著作权人的权利,请与我们联系(微信/QQ:1074760229)。转载请注明出处:清一色财经