Vue项目中的性能优化
注意对象层级的嵌套, 不需要响应式的数据不放到data中 v-if和v-show区分使用场景 computed和watch区分使用场景 v-for 遍历必须加key,并且是id值,避免同时和v-if一起使用 列表数据较多时和表格性能优化-虚拟列表和虚拟表格 防止内存泄漏,组件销毁后把全局变量和事件销毁 懒加载(图片懒加载、路由懒加载) 按需引入第三方插件 适当采用 keep-alive缓存组件 防抖、节流 预渲染
.mixin的使用场景和原理
场景:相同或相似的代码在不同的组件中使用,
原理:类似"对象的继承",当组件初始化时会调用 mergeOptions 方法进行合并,采用策略模式针对不同的属性进行合并。
keep-alive使用场景和原理
场景:实现组件缓存,当组件切换时不会对当前组件进行卸载。
常用的两个属性 include/exclude,允许组件有条件的进行缓存 两个生命周期 activated/deactivated,用来得知当前组件是否处于活跃状态。 keep-alive 中还运用了 LRU(最近最少使用)算法,选择最近最久未使用的组件予以淘汰。
.set 方法原理
修改数据 不会触发视图更新的两种情况分别是: 在实例创建之后添加新的属性到实例上(给响应式对象新增属性) 直接更改数组下标来修改数组的值
原理:
当给对象新增不存在的属性时,首先会把新的属性进行响应式跟踪,vue给对象和数组本身都增加了__ob__属性,是Observer实例 触发对象__ob__的dep收集到的 watcher 去更新 修改数组索引时 调用数组本身的 splice 方法去更新数组
Vue.extend 作用和原理
创建一个“子类”。参数是一个包含组件选项的对象。 子类构造器是 Vue组件的核心 api 实现思路就是使用原型继承的方法返回了 Vue的子类 并且利用 mergeOption 把传入组件的options和父类的options进行了合并。
自定义指令、原理
本质是装饰器
,是vue对于HTML元素的扩展,给HTML元素增加自定义功能。vue 编译DOM时,会找到指令对象
,执行指令的相关方法。
自定义指令有五个生命周期,bind、inserted、update、componentUpdated、unbind
bind:只调用一次,指令第一次绑定到元素时调用。在这里可以进行一次性的初始化设置。 inserted被绑定元素插入父节点时调用 (仅保证父节点存在,但不一定已被插入文档中)。 update被绑定于元素所在的模板更新时调用,而无论绑定值是否变化。通过比较更新前后的绑定值,可以忽略不必要的模板更新。 componentUpdated被绑定元素所在模板完成一次更新周期时调用 unbind只调用一次,指令与元素解绑时调用
原理:
1.在生成 ast 语法树时,遇到指令会给当前元素添加 directives 属性 2.通过 genDirectives 生成指令代码 3.在 patch 前将指令的钩子提取到 cbs 中,在 patch 过程中调用对应的钩子 4.当执行指令对应钩子函数时,调用对应指令定义的方法
生命周期钩子是如何实现的
核心是利用订阅发布模式先把用户传入的周期钩子订阅好,然后在创建组件实例的过程中会一次执行对应的钩子方法(发布)
vue-router 如何响应路由参数的变化
什么是路由参数的变化:当使用路由参数时,从 /user/foo导航到 /user/bar,原来的组件实例会被复用。因为两个路由都渲染同个组件,比起销毁再创建,复用则显得更加高效。
watch : {
$route ( to, from ) {
console. log ( to) ;
console. log ( from)
}
}
beforeRouterEnter ( to, from, next ) {
next ( )
}
Vue中 data中变量的数据值发生改变,界面没有跟着更新,原因?
1.如果data里面定义了对象,对象里面的键值没有,getter/setter函数没法监听到属性值的数据变化,会导致此现象的发生。 解决方法:Vue.set(obj,key,value) this,$set(obj,key,value)
多层父子组件通讯
需要通讯的组件不是直接的父子组件,而是祖父和孙子,嵌套的层级比较多的情况下,需要传递的事件和属性比较多,会导致代码混乱,这个时候就需要用到Vue提供的更高阶方法:provide/inject
父子组件通讯方式有哪些?
父组件–>子组件:自定义属性 props 子组件–>父组件:自定义事件 $emit EventBus Vuex v-model
v-model的方式:
我们都在表单中使用过 v-model 来绑定数据,其实组件之间也是可以用 v-model 进行双向绑定的
v-model 的本质就是绑定一个属性和事件
< aa class = "abc" v- model= "test" > < / aa>
< template>
< div>
< ul>
< li> { { '里面的值:' + msg} } < / li>
< button @click= "fn2" > 里面改变外面< / button>
< / ul>
< / div>
< / template>
< script>
export default {
model : {
prop : 'msg' ,
event : 'cc'
}
} ,
props : {
msg : ''
} ,
methods : {
fn2 ( ) {
this , $emit ( 'cc' , this , msg+ 2 )
}
}
< / script>
简述Vue的生命周期(vue2.0)
常用8个 beforeCreate阶段、create阶段 beforeMounted、mounted beforeUpdate、update beforeDestroy、destroy 分别为:创建前/后,载入前/后,更新前/后,销毁前/后。
第一次页面加载会触发哪几个钩子
beforeCreate、create、beforeMount、mounted
Vue实现数据双向绑定的原理
采用数据劫持结合发布者-订阅者模式的方式,通过Object.defineProperty() 来劫持各个属性的 setter,getter,在数据变动时发布消息给订阅者,触发相应监听回调。 当把普通javascript对象传给Vue实例来作为他的data选项时,Vue将遍历它的属性,用Object.defineProperty将它们转为getter/setter。 用户看不到getter/setter,但是在内部它们让Vue追踪依赖,在属性被访问和修改时通知变化。 数据双向绑定 将MVVM作为数据绑定的入口,整合 Observer,Compile和Watcher三者,通过Observer来监听数据变化,通过 Compile来解析模板指令,最终利用 watcher搭起二者的通信桥梁,达到数据变化–>视图更新;视图交互变化–>数据model变更双向绑定效果。
简单实现双向数据绑定
< body>
< div>
< input type= "text" id= "txt"
< p id= "show" > < / p>
< / div>
< / body>
< script type= "text/javascript" >
var obj = { }
Object. defineProperty ( obj, 'txt' , {
get : function ( ) {
return obj
} ,
set : function ( newValue ) {
document. getElementById ( 'txt' ) , value= newValue
document. getElementById ( 'show' ) , innerHTML = newValue
}
} )
document. getElementById ( 'txt' ) . addEventListener ( 'keyup' , function ( e ) {
obj. txt = e. target. value
} )
< script>
Vuex刷新页面数据丢失怎么解决?
1.将vuex中的数据直接保存到浏览器缓存中(sessionStorage、localStorage、cookie) 2.在页面刷新时再次请求数据,使之动态更新vuex数据 3.在父页面向后台请求远程数据,并且在页面刷新前将vuex的数据先保存到 sessionStorage(以防请求数据量过大页面加载时拿不到返回的数据)
简单讲述 vuex
1.vuex是专门为vue.js提供的一种状态``管理模式
,它采用的是集中式储存
和管理所有组件的状态和数据
。 Vue Component–>Dispatch–>Actions–>Commit–>Mutations–>Mutate–>State–>Render–>Vue Component
有5种属性,state
、mutation
、action
、getter
、module
state: vuex使用单一状态树,即每个应用将仅仅包含一个store实例,但单一状态树和模块化并不冲突。存放的数据状态,不可以直接修改里面的数据。 getters:类似vue的计算属性,主要用来过滤一些数据。 mutations:定义的方法动态修改Vuex的store中的状态或数据。 actions:可以理解为通过将mutations里面的处理数据的方法变成可异步的处理数据的方法,view层通过 store.dispath来分发action
const store = new Vuex. Store ( {
state : {
count : 0
} ,
mutations : {
increment ( state ) {
state. count++
}
} ,
actions : {
increment ( context ) {
context. commit ( 'increment' )
}
}
} )
modules:当项目复杂时,可以让每一个模块拥有自己的state、mutation、action、getters
const moduleA = {
state : { ... } ,
mutations : { ... } ,
actions : { ... } ,
getters : { ... }
}
const moduleB = {
state : { ... } ,
mutations : { ... } ,
actions : { ... } ,
}
const store = new Vuex. Store ( {
modules : {
a : moduleA,
b : moduleB
}
} )
vue如何自定义一个过滤器
< div id= "app" >
< input type= "text" v- model= "msg" / >
{ { msg | userFilters ( 过滤器名称) } }
< / div>
< script>
var vm = new Vue ( {
el : "el" ,
data : {
msg : ''
} ,
filters : {
userFilters : function ( v ) {
if ( ! v) return '' ...
return v
}
}
} )
Vue. filter ( 'userFilter' , function ( v ) {
if ( ! v) return ''
...
return v
}
< / script>
对keep-alive的了解?
keep-alive 包裹动态组件时,会缓存不活动的组件实例,主要用于保留组件状态或避免重新渲染 使用方法:
< keep- alive>
< component>
< ! -- 该组件将被缓存! -- >
< / component>
< / keep- alive>