对于MVVM的理解
MVVM是Model-View-ViewModel缩写,也就是把MVC中的Controller演变成ViewModel。Model层代表数据模型,View代表UI组件,ViewModel是View和Model层的桥梁,数据会绑定到viewModel层并自动将数据渲染到页面中,视图变化的时候会通知viewModel层更新数据。
MVVM 是 Model-View-ViewModel 的缩写
Model: 代表数据模型,也可以在Model中定义数据修改和操作的业务逻辑。我们可以把Model称为数据层,因为它仅仅关注数据本身,不关心任何行为
View: 用户操作界面。当ViewModel对Model进行更新的时候,会通过数据绑定更新到View
ViewModel:业务逻辑层,View需要什么数据,ViewModel要提供这个数据;View有某些操作,ViewModel就要响应这些操作,所以可以说它是Model for View.
MVVM模式简化了界面与业务的依赖,解决了数据频繁更新。MVVM 在使用当中,利用双向绑定技术,使得 Model 变化时,ViewModel 会自动更新,而 ViewModel 变化时,View 也会自动变化。
Vue生命周期
vue实例从创建到销毁的过程,就是生命周期。从开始创建、初始化数据、编译模板、挂载Dom→渲染、更新→渲染、销毁等一系列过程被称之为vue生命周期。
vue生命周期挂在了很多钩子函数,我们可以更方便和更有逻辑的控制整个vue的实例化的过程
vue生命周期分为八个阶段 创建前/后,加载前/后 ,更新前/后,销毁前/后
页面第一次加载的时候 会触发beforeCreate、created、beforeMount、mounted这几个钩子,在mounted的时候会渲染完成DOM。
Vue实现数据双向绑定的原理:Object.defineProperty()
vue实现数据双向绑定主要是:采用数据劫持结合发布者-订阅者模式的方式,通过 Object.defineProperty() 来劫持各个属性的setter,getter,在数据变动时发布消息给订阅者,触发相应监听回调。当把一个普通 Javascript 对象传给 Vue 实例来作为它的 data 选项时,Vue 将遍历它的属性,用 Object.defineProperty() 将它们转为 getter/setter。用户看不到 getter/setter,但是在内部它们让 Vue追踪依赖,在属性被访问和修改时通知变化。
vue的数据双向绑定 将MVVM作为数据绑定的入口,整合Observer,Compile和Watcher三者,通过Observer来监听自己的model的数据变化,通过Compile来解析编译模板指令(vue中是用来解析 {{}}),最终利用watcher搭起observer和Compile之间的通信桥梁,达到数据变化 —>视图更新;视图交互变化(input)—>数据model变更双向绑定效果。
Vue组件之间传递参数
父子之间传递参数:父组件传给子组件:子组件通过props方法接受数据;子组件传给父组件:$emit 方法传递参数
非父子组件间的数据传递,兄弟组件传值 用eventBus(适合小项目)或者VUEX
Vue路由
路由模式:hash模式 和 history模式
hash模式:在浏览器中符号“#”,#以及#后面的字符称之为hash,用 window.location.hash 读取。特点:hash虽然在URL中,但不被包括在HTTP请求中;用来指导浏览器动作,对服务端安全无用,hash不会重加载页面。
history模式:history采用HTML5的新特性;且提供了两个新方法:pushState(), replaceState()可以对浏览器历史记录栈进行修改,以及popState事件的监听到状态变更
路由钩子函数
全局钩子函数(beforeEach、afterEach)
路由独享的钩子函数(beforeEnter)
组件内钩子函数(beforeRouterEnter、beforeRouterUpdate、beforeRouterLeave)
beforeEach一共接收三个参数,分别是to、from、next;to:即将进入的路由对象;from:正要离开的路由对象;next:路由的控制参数;
AfterEach和beforeEach一样都是属于全局守卫钩子,都是在main.js中进行调用;其中AfterEach比beforeEach少一个next参数;to:即将要进入的路由对象;from:正要离开的路由对象;
beforeEneter 指定的路由才有的钩子函数,通常这类路由独享的钩子函数我们是在路由配置文件中进行配置,只能设置改变前的钩子,不能设置改变后的钩子,只能在设置的路由 才能触发这个钩子函数,其他页面是不会触发的,也有to,from,next三个参数
beforeRouterEnter(to,from,next)是唯一一个不能使用this的钩子函数,因为此时的vue实例还没有创建;to:即将要进入的路由对象;from:正要离开的路由对象;next:路由控制参数
beforeRouterUpdate(to,from,next) 在路由发生修改的时候进行调用
beforeRouterLeave(to,from,next) 在路由离开该组件时调用;
路由之间跳转
<router-link :to="index"> 或者 router.push('index')
$route和$router的区别
$route是“路由信息对象”,包括path,params,hash,query,fullPath,matched,name等路由信息参数;而$router是“路由实例”对象包括了路由的跳转方法,钩子函数等
例如 this.$router.push({
path: "/ems/emsAddPlan",
query: { id: this.$route.query.id }
});
v-if 和 v-show 区别
v-if按照条件是否渲染,v-show是display的block或none;
如何让CSS只在当前组件中起作用?
将当前组件的<style>修改为<style scoped>
scoped样式穿透:使用/deep/或者另外写一个style样式 不加scoped
<keep-alive></keep-alive>的作用是什么?
keep-alive可以实现组件缓存,当组件切换时不会对当前组件进行卸载
<keep-alive></keep-alive> 包裹动态组件时,会缓存不活动的组件实例,主要用于保留组件状态或避免重新渲染
比如有一个列表和一个详情,那么用户就会经常执行打开详情=>返回列表=>打开详情…这样的话列表和详情都是一个频率很高的页面,那么就可以对列表组件使用<keep-alive></keep-alive>进行缓存,这样用户每次返回列表的时候,都能从缓存中快速渲染,而不是重新渲染
常用的两个属性include/exclude,允许组件有条件的进行缓存
两个生命周期activated/deactivated,用来得知当前组件是否处于活跃状态
指令v-el的作用是什么?
提供一个在页面上已存在的 DOM元素作为 Vue实例的挂载目标.可以是 CSS 选择器,也可以是一个 HTMLElement 实例
在Vue中使用插件的步骤
采用ES6的import ... from ...语法或CommonJS的require()方法引入插件
使用全局方法Vue.use( plugin )使用插件,可以传入一个选项对象Vue.use(MyPlugin, { someOption: true })
Vue 组件 data 为什么必须是函数
每个组件都是 Vue 的实例。
组件共享 data 属性,当 data 的值是同一个引用类型的值时,改变其中一个会影响其他
Vue computed 实现
初始化 data, 使用 Object.defineProperty 把这些属性全部转为 getter/setter。
初始化 computed, 遍历 computed 里的每个属性,每个 computed 属性都是一个 watch 实例。每个属性提供的函数作为属性的 getter,使用 Object.defineProperty 转化。
Object.defineProperty getter 依赖收集。用于依赖发生变化时,触发属性重新计算。
若出现当前 computed 计算属性嵌套其他 computed 计算属性时,先进行其他的依赖收集
computed和watch区别
当页面中有某些数据依赖其他数据进行变动的时候,可以使用计算属性computed
watch用于观察和监听页面上的vue实例,如果要在数据变化的同时进行异步操作或者是比较大的开销,那么watch为最佳选择
vue修饰符
stop:阻止事件的冒泡
prevent:阻止事件的默认行为
once:只触发一次
self:只触发自己的事件行为时,才会执行
vue.extend和vue.component
extend是构造一个组件的语法器。然后这个组件你可以作用到Vue.component这个全局注册方法里还可以在任意vue模板里使用组件。也可以作用到vue实例或者某个组件中的components属性中并在内部使用apple组件。
Vue.component你可以创建 ,也可以取组件。
vue的优点是什么
低耦合。视图(View)可以独立于Model变化和修改,一个ViewModel可以绑定到不同的"View"上,当View变化的时候Model可以不变,当Model变化的时候View也可以不变
可重用性。你可以把一些视图逻辑放在一个ViewModel里面,让很多view重用这段视图逻辑
可测试。界面素来是比较难于测试的,而现在测试可以针对ViewModel来写
vue项目中的性能优化
代码层面:
1 不要在模板里面写过多表达式
2 循环调用子组件时添加key,并且避免使用v-for的时候同时使用v-if
3 频繁切换的使用v-show,不频繁切换的使用v-if
4 尽量少用float,可以用flex
5 按需加载,可以用require或者import()按需加载需要的组件
6 路由懒加载,图片懒加载,第三方插件按需引入
7 区分 computed 和 watch 的使用
8 通过 addEventListener添加的事件在组件销毁时要用 removeEventListener 手动移除这些事件的监听
9 SSR服务端渲染,首屏加载速度快,SEO效果好
Webpack 层面优化:
1 对图片进行压缩
2 使用 CommonsChunkPlugin 插件提取公共代码
3 提取组件的 CSS
4 优化 SourceMap
5 构建结果输出分析,利用 webpack-bundle-analyzer 可视化分析工具
Vue的SPA 如何优化加载速度
减少入口文件体积
静态资源本地缓存
开启Gzip压缩
使用SSR,nuxt.js
Vue与Angular以及React的区别?
Vue与AngularJS的区别
Angular采用TypeScript开发, 而Vue可以使用javascript也可以使用TypeScript
AngularJS依赖对数据做脏检查,所以Watcher越多越慢;Vue.js使用基于依赖追踪的观察并且使用异步队列更新,所有的数据都是独立触发的。
AngularJS社区完善, Vue的学习成本较小
Vue与React的区别
vue组件分为全局注册和局部注册,在react中都是通过import相应组件,然后模版中引用;
props是可以动态变化的,子组件也实时更新,在react中官方建议props要像纯函数那样,输入输出一致对应,而且不太建议通过props来更改视图;
子组件一般要显示地调用props选项来声明它期待获得的数据。而在react中不必需,另两者都有props校验机制;
每个Vue实例都实现了事件接口,方便父子组件通信,小型项目中不需要引入状态管理机制,而react必需自己实现;
使用插槽分发内容,使得可以混合父组件的内容与子组件自己的模板;
多了指令系统,让模版可以实现更丰富的功能,而React只能使用JSX语法;
Vue增加的语法糖computed和watch,而在React中需要自己写一套逻辑来实现;
react的思路是all in js,通过js来生成html,所以设计了jsx,还有通过js来操作css,社区的styled-component、jss等;而 vue是把html,css,js组合到一起,用各自的处理方式,vue有单文件组件,可以把html、css、js写到一个文件中,html提供了模板引擎来处理。
react做的事情很少,很多都交给社区去做,vue很多东西都是内置的,写起来确实方便一些, 比如 redux的combineReducer就对应vuex的modules, 比如reselect就对应vuex的getter和vue组件的computed, vuex的mutation是直接改变的原始数据,而redux的reducer是返回一个全新的state,所以redux结合immutable来优化性能,vue不需要。
react是整体的思路的就是函数式,所以推崇纯组件,数据不可变,单向数据流,当然需要双向的地方也可以做到,比如结合redux-form,组件的横向拆分一般是通过高阶组件。而vue是数据可变的,双向绑定,声明式的写法,vue组件的横向拆分很多情况下用mixin
vuex是什么?怎么使用?哪种功能场景使用它?
vuex 就是一个仓库,仓库里放了很多对象。其中 state 就是数据源存放地,对应于一般 vue 对象里面的 data
state 里面存放的数据是响应式的,vue 组件从 store 读取数据,若是 store 中的数据发生改变,依赖这相数据的组件也会发生更新
它通过 mapState 把全局的 state 和 getters 映射到当前组件的 computed 计算属性。
Vuex有5种属性: 分别是 state、getter、mutation、action、module;