什么是 mvvm?
MVVM 是 Model-View-ViewModel 的缩写。mvvm 是一种设计思想。Model 层代表数据模型,也可以在 Model 中定义数据修改和操作的业务逻辑;View 代表 UI 组件,它负责将数据模型转化成 UI 展现出来,ViewModel 是一个同步 View 和 Model 的对象。
简述Vue的响应式原理
当一个Vue实例创建时,vue会遍历data选项的属性,用 Object.defineProperty 将它们转为 getter/setter并且在内部追踪相关依赖,在属性被访问和修改时通知变化。
每个组件实例都有相应的 watcher 程序实例,它会在组件渲染的过程中把属性记录为依赖,之后当依赖项的 setter 被调用时,会通知 watcher 重新计算,从而致使它关联的组件得以更新。
vue生命周期的理解
总共分为 8 个阶段创建前/后,载入前/后,更新前/后,销毁前/后。
创建前/后: 在 beforeCreate 阶段,vue 实例的挂载元素 el 还没有。
载入前/后:在 beforeMount 阶段,vue 实例的$el 和 data 都初始化了,但还是挂载之前为虚拟的 dom 节点,data.message 还未替换。在 mounted 阶段,vue 实例挂载完成,data.message 成功渲染。
更新前/后:当 data 变化时,会触发 beforeUpdate 和 updated 方法。
销毁前/后:在执行 destroy 方法后,对 data 的改变不会再触发周期函数,说明此时 vue 实例已经解除了事件监听以及和 dom 的绑定,但是 dom 结构依然存在。
为什么vue中data必须是一个函数?
当重用组件时,由于数据对象都指向同一个data对象,当在一个组件中修改data时,其他重用的组件中的data会同时被修改;而使用返回对象的函数,由于每次返回的都是一个新对象(Object的实例),引用地址不同,则不会出现这个问题。
vue-router有哪几种导航钩子?
三种。
一种是全局导航钩子:router.beforeEach(to,from,next),作用:跳转前进行判断拦截。
第二种:组件内的钩子;
第三种:单独路由独享组件
<!-- 组件内的钩子 -->
const Foo = {
template: `...`,
beforeRouteEnter (to, from, next) {
// 在渲染该组件的对应路由被 confirm 前调用
// 不!能!获取组件实例 `this`
// 因为当守卫执行前,组件实例还没被创建
},
beforeRouteUpdate (to, from, next) {
// 在当前路由改变,但是该组件被复用时调用
// 举例来说,对于一个带有动态参数的路径 /foo/:id,在 /foo/1 和 /foo/2 之间跳转的时候,
// 由于会渲染同样的 Foo 组件,因此组件实例会被复用。而这个钩子就会在这个情况下被调用。
// 可以访问组件实例 `this`
},
beforeRouteLeave (to, from, next) {
// 导航离开该组件的对应路由时调用
// 可以访问组件实例 `this`
}
}
<!--路由独享的守卫-->
const router = new VueRouter({
routes: [
{
path: '/foo',
component: Foo,
beforeEnter: (to, from, next) => {
// ...
}
}
]
})
计算属性和watch的区别 ?
计算属性是用来一些数据需要随着其它数据变动而变动时用的.
基于它们的响应式依赖进行缓存的。只在相关响应式依赖发生改变时它们才会重新求值。依赖还没有发生改变 , 计算属性会立即返回之前的计算结果,而不会再次执行函数.
watch是用来监听数据变动的. 当需要在数据变化时执行异步或开销较大的操作时,这个方式是最有用的。
vue 组件通信 ?
父传递子
父:自定义属性名 + 数据(要传递)=> :value=“数据”
子:props ["父组件上的自定义属性名“] =>进行数据接收)
子传递父
在父组件中注册子组件并在子组件标签上绑定自定义事件的监听。
子:this.$emit(‘自定义事件名称’, 数据) 子组件标签上绑定@自定义事件名称=‘回调函数’
父:methods: {自定义事件() {//逻辑处理} }
的作用是什么?
保持这些组件的状态,以避免反复重渲染导致的性能问题, 缓存动态组件的行为
$nextTick ?
将回调延迟到下次 DOM 更新循环之后执行,在修改数据之后立即执行.
常用的事件修饰符
.stop .prevent .once .self: 只当事件是从事件绑定的元素本身触发时才触发回调
Vue子组件调用父组件的方法
- this.$parent
- $emit
axios的特点有哪些?
- axios是一个基于promise的HTTP库,支持promise的所有API;
- 它可以拦截请求和响应;
- 它可以转换请求数据和响应数据,并对响应回来的内容自动转换为json类型的数据;
- 它安全性更高,客户端支持防御XSRF;
vue中的 ref 是什么?
ref 被用来给元素或子组件注册引用信息。引用信息将会注册在父组件的 $refs 对象上。如果在普通的 DOM 元素上使用,引用指向的就是 DOM 元素;如果用在子组件上,引用就指向组件实例。
vue.js的两个核心是什么?
数据驱动、组件系统
vue如何兼容ie的问题。
babel-polyfill插件
页面刷新vuex被清空解决办法?
vuex-persistedstate
import Vue from 'vue'
import Vuex from 'vuex'
import * as Cookies from 'js-cookie'
import createPersistedState from 'vuex-persistedstate'
import createLogger from 'vuex/dist/logger'
import actions from './actions'
import * as getters from './getters'
import state from './state'
import mutations from './mutations'
import player from './modules/player/index'
Vue.use(Vuex)
// webpack 中 生产模式或开发
const debug = process.env.NODE_ENV !== 'production'
const store = new Vuex.Store({
state,
getters,
mutations,
actions,
modules: {
player
},
// 严格模式
strict: debug,
plugins: [
// vuex-persistedstate,使vuex状态持久化(缓存到本地)
createPersistedState({
storage: {
// cookie / localStorage
getItem: key => Cookies.get(key),
setItem: (key, value) => Cookies.set(key, value, {
expires: 3,
secure: true
}),
removeItem: key => Cookies.remove(key)
}
}),
debug ? createLogger() : false
]
})
export default store
如何优化SPA应用的首屏加载速度慢的问题?
- 公用js库外部CDN引入
- 路由懒加载
- 骨架屏或Loading图. 优化用户体验
DOM 渲染在哪个周期中就已经完成?
mounted, 注意 mounted 不会承诺所有的子组件也都一起被挂载。如果你希望等到整个视图都渲染完毕,可以用 vm.$nextTick 替换掉 mounted
mounted: function () {
this.$nextTick(function () {
// Code that will run only after the
// entire view has been rendered
})
}
vue中的diff算法是怎样实现的 ?
diff算法是一种优化手段,将前后两个模块(vNode: virtual DOM)进行差异化对比,修补(更新真实的DOM)差异的过程叫做patch(打补丁)
diff的过程就是调用名为patch的函数,比较新旧节点,一边比较一边给真实的DOM打补丁。
virtual DOM是将真实的 DOM 的数据抽取出来,以对象的形式模拟树形结构,diff算法比较的也是virtual DOM
<div>
<p>Hello World</p>
</div>
// 转换成虚拟节点 类似于下面这种
const Vnode = {
tag:'div',
children:[
{tag:'p',text:'Hello World'}
]
}
谈谈你对vue的双向数据绑定原理的理解
vue.js 是采用数据劫持结合发布者-订阅者模式的方式,通过Object.defineProperty()来劫持各个属性的setter,getter,在数据变动时发布消息给订阅者,触发相应的监听回调。
第一步:需要observe的数据对象进行递归遍历,包括子属性对象的属性,都加上 setter和getter。这样的话,给这个对象的某个值赋值,就会触发setter,那么就能监听到了数据变化
第二步:compile解析模板指令,将模板中的变量替换成数据,然后初始化渲染页面视图,并将每个指令对应的节点绑定更新函数,添加监听数据的订阅者,一旦数据有变动,收到通知,更新视图
第三步:Watcher订阅者是Observer和Compile之间通信的桥梁,主要做的事情是:
1、在自身实例化时往属性订阅器(dep)里面添加自己
2、自身必须有一个update()方法
3、待属性变动dep.notice()通知时,能调用自身的update()方法,并触发Compile中绑定的回调,则功成身退。
第四步:MVVM作为数据绑定的入口,整合Observer、Compile和Watcher三者,通过Observer来监听自己的model数据变化,通过Compile来解析编译模板指令,最终利用Watcher搭起Observer和Compile之间的通信桥梁,达到数据变化 -> 视图更新;视图交互变化(input) -> 数据model变更的双向绑定效果。
MVVM如何实现模板绑定,依赖是如何收集的?
transition: 过渡的实现原理
vue组件间的交互有七种你知道几种?
请详细说出vue生命周期的执行过程
vue-router: 官方路由的实现原理
vue-cli3.0如何实现的?
说说hash路由和history路由,你能自己编写一个前端路由吗?
你能手写vuex状态管理吗?
待续…