原文链接:www.jianshu.com/p/b1dd80f4d…
一,MVC(Model-View-Controller)设计模式
一个简单的流程:
1. 用户和view交互触发事件;
2. 控制器的事件处理器被触发;
3. 控制器从模型中请求数据,并将其交给视图;
4. 视图将数据呈现给用户;
真正处理业务逻辑的是Model而不是controller;controller只是对页面节点事件的注册和控制;
二,Model-View-ViewModel设计模式(数据驱动型)
View(视图)
m:model数据模型层 v:view视图层 vm:ViewModel vue采用的是MVVM模式,这是从mvc衍生过来的 MVVM让视图与viewmodel直接的关系特别紧密,就是为了解决mvc反馈不及时的问题。
说到MVVM就要说一下双向绑定和数据劫持的原理,
1,双向绑定的原理是什么?
一句话概括:当视图改变的时候更新模型层,当模型改变的时候更新视图层。
双向绑定原理采用了数据劫持&发布-订阅者模式:
vue在创建vm的时候,会将数据配置在实例当中,然后使用Object.defineProperty对这些数据进行处理,为这些数据添加getter与setter方法。当获取数据的时候,会触发对应的getter方法,数据变化,当设置数据的时候,会触发对应的setter方法,从而进一步触发vm上的watcher方法,然后数据变化,vm更新视图。
2,数据劫持
数据劫持是通过Object.defineProperty()来劫持各个属性的setter,和getter。在数据变动时发布消息给订阅者,触发响应的监听回调。
let _data = {}
let value = 111;
Object.defineProperty(_data,"msg",{
get(){
return value;
},
set(val){
value = val
}
})
console.log(_data.msg)
//获取数据触发getter()方法
_data.msg = 222;
//设置数据会调用getter方法
复制代码
3,mvvm与mvc的最大区别:
MVVM实现了view与model的自动同步,当model属性改变的时候,不需要再自己手动操作dom元素去改变view的显示,而是改变属性后该属性对应的view曾会自动改变。
三,active-class
active-class是什么?
是vue路由中router-link的属性,链接激活时使用的css类名。
在vue-router中要使用active-class有两种方法:
1,在路由js文件中配置linkActiveClass
2. 在router-link中写入active-class
四,怎么定义vue-router的动态路由?怎么获取传过来的参数?
在router下的index.js中,对path属性加上/:id.使用时用params.id.
五,路由之间的跳转
1,声明式(标签跳转)
router-link
<router-link :to = "{name:'index',query:{id:'参数'}}">
复制代码
2,编程式(js跳转)
this.$router.push({path:'/master',query:{id:'参数'}})<br>
this.$router.gp(n)
复制代码
六,vue.cli中怎样使用自定义组件?
1,在components目录下新建自己的组件文件(myPage.vue),记得一定要export default{}
2,在需要使用的页面中导入:import myPage from '@/components/myPage.vue'
3, 注入到vue组件的components属性上面,components:{myPage};
4, 在template视图vew中使用,
<my-page></my-page>
复制代码
七,vue生命周期
总共分为8个阶段创建前/后,载入前/后,更新前/后,销毁前/后。
1,创建前/后:
在beforeCreate阶段,vue实例的挂载元素el和数据对象data都为undefined,还未初始化。在created阶段,vue实例的数据对象data有了,el还没有。
2,载入前/后:
在beforeMount阶段,vue实例的$el和data都初始化了,但是载入之前为虚拟的dom节点,data.message还未替换。在mounted阶段,vue实例挂载完成,data.message成功渲染。
3,更新前/后:
当data变化时,会触发beforeUpdate和updata方法。
4,销毁前/后:
在执行destroy方法后,对data的修改不会再触发周期函数,说明此时vue实例已经解除了事件监听以及和dom的绑定,但是dom结构依然存在。
什么是生命周期
Vue实例从创建到销毁的过程,就是生命周期。开始创建->初始化数据->编译模板,挂载dom->渲染,更新->渲染,卸载这一系列过程就叫做生命周期。
vue生命周期的作用是什么?
它的生命周期中有多个事件钩子,让我们能够控制整个vue实例从创建到销毁的过程。
第一次加载页面会触发哪几个钩子?
会触发 beforeCreate,created,beforeMount,mounted这几个钩子。
dom渲染在哪个周期就已经完成了?
在mounted的时候,在beforeMount阶段还是虚拟dom节点,data.message还没替换。
每个周期具体适合哪些场景?
beforecreate:可以在这加个loading事件,在加载实例时触发。
created : 初始化完成时的事件写在这里,如在这结束loading事件,异步请求也适宜在这里调用
mounted : 挂载元素,获取到DOM节点
updated : 如果对数据统一处理,在这里写上相应函数
beforeDestroy : 可以做一个确认停止事件的确认框
nextTick : 更新数据后立即操作dom
八,什么是虚拟dom
可以看作是一个使用了javaScript模拟了dom结构的树形结构,这个树结构包含整个dom结构的信息。
<ul id = "list">
<li class = "item">item1</li>
<li class = "item">item2</li>
</ul>
复制代码
{
tag:'ul',
attr:{
id:'list'
},
children:[
{
tag:'li',
attrs:{
className:'item'
},
children:['item1']
},{
tag:'li',
attrs:{
className:'item'
},
children:['item2']
}
]
}
复制代码
为什么要使用虚拟DOM?
1,使用原声js和jquery写页面的时候会发现操作dom是一件非常繁琐的事情,往往是DOM标签和js逻辑同时写在js文件里,如果没有好的代码规范的话会显得1代码非常冗余混乱,耦合性高,难维护。
2,而且浏览器一遍又一遍渲染DOM是非常消耗性能的,常常会出现页面卡死的情况;所以尽量减少对DOM操作成为优化前端性能的必要手段。
虚拟dom就是将DOM的对比放在了js层,通过对比不同之处来选择性渲染dom节点,提高渲染效率。
九,组件之间的传值
父组件与子组件传值
父组件通过标签上面定义传值,子组件通过props方法接收数据。
//父组件通过标签上面定义传值
<template>
<Main :obj = "data"><Main>
</template>
<script>
//引入子组件
import Main form "./main"
export default{
name:"parent",
data(){
return {
data:"我是向子组件传递的数据"
}
},
//初始化组件
components:{
Main
}
}
</script>
//子组件通过props方法接受数据
<template>
<div>{{data}}</div>
</template>
<script>
export default{
name:"Main",
props:["obj"]
}
</script>
复制代码
子组件向父组件传值
子组件向父组件传递数据,子组件通过$emit方法传递。
//父组件
<template>
<div @events = "eventChild"></div>
</template>
<script>
//引入子组件
import Main from "./Main";
export default{
name:"parent",
data(){
return {
}
},
//初始化组件
components:{
Main
},
methods:{
eventChild:function(data){
data就是子组件的data
}
}
}
</script>
//子组件
<template>
<button @click = "subParant"></button>
</template>
<script>
//引入子组件
import Main from "./Main";
export default{
name:"parent",
data(){
return {
data:"我是传递给父组件的值"
}
},
//初始化组件
components:{
Main
},
methods:{
subParant:function(){
this.$emit("events",this.data)
}
}
}
</script>
复制代码
父传子,把数据放到子组件的自定义属性上。子传父,数据存到了methods里面。
兄弟之间传值
1,新建一个js然后引入vue,实例化vue,暴露这个实例;
2,在要传播的地方引入刚才定义的实例;
3,通过vueEmit.on('名称',function(){
})
十,vuex面试题
1,有哪几种属性
有5种,分别是state,mutation,getter,action,module
2,vuex的state特性是什么?
vuex就是一个仓库,仓库里放了很多对象,其中state就是数据源存放地,对应于一般vue对象里的data
state里面存放的数据是响应式的,若是store中state数据发生改变,依赖这些数据的组件也会发生更新
3,vuex的getter特性是什么?
getter可以对state进行计算操作,它就是store的计算属性
getters可以在多个组件复用。
4,vuex的mutation特性是什么?
mutation,改变states中数据的方法,action类似mutation,不同在于action提交的是mutation,而不是直接变更状态,action可以包含任意异步操作。
5,vue中的ajax请求代码应该写在组件的methods中还是vuex的action中
如果请求来的数据不被其他组件公用,仅仅写在请求组件的methods,不需要放入vuex的state里。如果被其他地方复用,请将请求放到action里。
6,不用vuex会带来什么问题
可维护性下降,你要修改数据的话,得维护多个地方。可读性下降,不知道数据从何而来,增加耦合。
十一,零碎整理
1,vue如何实现按需加载配合webpack设置
webpack中提供了require.ensure()来实现按需加载。
不进行页面按需加载得引入方式
import home from './home.vue'
进行页面按需加载的引入方式:const home =r =>require.ensure([],()=>r())
复制代码
2,mint-ui是什么?哪些常用指令?
mint-ui是饿了么前端团队推出的基于Vue.js的移动端组件库。
全局引入
第一步:npm install nint-ui -S;第二步:在主文件中 import Mint from 'mint-ui';引入style.css;第三步:注册。Vue.use(Mint);
局部引入
import {Toast} from 'mint-ui';
3,vue-router有哪几种导航钩子?
三种,全局导航钩子:router.beforeEach(to,from,next),作用:跳转前进行判断拦截。第二种:组件内的钩子;第三种,单独路由独享组件。