一个VUE项目的主树:
assets文件夹是放静态资源;
components是放组件;
router是定义路由相关的配置;
view视图;
app.vue是一个应用主组件;
main.js是入口文件
知识点:
1.MVC和MVVM
MVC是Model-View- Controller的简写,分别表示:
Model(数据模型),用于存放数据
View(视图),也就是用户界面
Controller(y业务逻辑)是Model和View的协调者,Controller把Model中的数据拿过来给View使用
关系:用户操作> View (负责接受用户的输入操作)>Controller(业务逻辑处理)>Model(数据持久化)>View(将结果通过View反馈给用户)
缺点:1.所有业务逻辑都在Controller里操作,逻辑复杂且不利于维护,
2.大量的DOM 操作使页面渲染性能降低,加载速度变慢,影响用户体验。
3.当 Model 频繁发生变化,需要主动更新到View ;当用户的操作导致Model发生变化,同样需要将变化的数据同步到Model中, 这样的工作不仅繁琐,而且很难维护复杂多变的数据状态。
MVVM是Model-View-ViewModel的简写,分别表示:
Movel(数据模型)
View(视图)
ViewModel 是一个同步View 和 Model的对象
核心是双向数据绑定,View和Model之间并没有直接的联系,是通过ViewModel进行交互,View的变动,自动反映在ViewModel上,反之亦然,这样就保证视图和数据的一致性。
2.vue的优点是什么?
· 低耦合。视图(View)可以独立于Model变化和修改,一个ViewModel可以绑定到不同的"View"上,当View变化的时候Model可以不变,当Model变化的时候View也可以不变。
· 可重用性。一些视图逻辑放在一个ViewModel里面,让很多view重用视图逻辑。
· 独立开发。开发人员可以专注于业务逻辑和数据的开发(ViewModel),设计人员可以专注于页面设计。
· 可测试。界面素来是比较难于测试的,而现在测试可以针对ViewModel来写。
3.vue的生命周期
第一对用于简单的ajax请求,页面初始化。
beforeCreate
实例对象刚创建,元素DOM和数据都还没有初始化,没有绑定属性。
created
实例对象完成创建,属性已绑定,但DOM未生成,数据data已经初始化完成,方法也已经可以调用,但是DOM为渲染。
第二对马上渲染真实的DOM,获取vnode信息,ajax请求。
beforeMount
组件挂载之前触发,虚拟DOM创建已完成。DOM未完成挂载,数据也初始化完成,但是数据的双向绑定还是显示{{}},这是因为Vue采用了Virtual DOM(虚拟Dom)技术,先占住了一个坑。
mounted
组件挂载完成触发,真实DOM完成,数据和DOM都完成挂载,在上一个周期占位的数据把值给渲染进去。一般请求会放在这个地方,因为这边请求改变数据之后刚好能渲染。
第三对
beforeUpdate
数据更新前触发,diff算法对比之后重新渲染。只要是页面数据改变了都会触发,数据更新之前,页面数据还是原来的数据,当你请求赋值一个数据的时候会执行这个周期,如果没有数据改变不执行。
updated
组件更新完成,不能更改数据,负责死循环。只要是页面数据改变了都会触发,数据更新完毕,页面的数据是更新完成的。beforeUpdate和updated要谨慎使用,因为页面更新数据的时候都会触发,在这里操作数据很影响性能和容易死循环。
第四对
beforeDestroy
实例对象销毁之前触发,清除计时器和事件。这个周期是在组件销毁之前执行,在我项目开发中,觉得这个其实有点类似路由钩子beforeRouterLeave,都是在路由离开的时候执行,只不过beforeDestroy无法阻止路由跳转,但是可以做一些路由离开的时候操作,因为这个周期里面还可以使用data和method。比如一个倒计时组件,如果在路由跳转的时候没有清除,这个定时器还是在的,这时候就可以在这个里面清除计时器。
Destroyed
实例对象销毁后触发,剩余DOM空壳。
4.vue双向绑定原理
Vue数据双向绑定(即数据响应式),是利用了Object.defineProperty()数据劫持重新定义了,对象获取属性值get和设置属性值set的操作来实现的。
监听器Observer,劫持并监听所有属性,有变动的,就通知订阅者。
订阅者Watcher,可以收到属性的变化通知并执行相应的函数,从而更新视图。
解析器Compile,解析每个节点的相关指令,并根据初始化模板data数据以及初始化相应的订阅器。替换数据v-model, v-on
5.组件的传值
a.父组件与子组件传值
父组件通过标签上面定义传值 :eg='data' 父组件中 data(){return {data:'egdata'}}.
子组件通过props方法接受数据 props:['eg'] , 在props 中添加了元素之后,就不需要在 data 中再添加变量了.
b.子组件向父组件传递数据
子组件通过$emit方法传递参数触发事件,在父组件监听事件$on( )
子组件部分:
父组件中:
c.同级传值
1.query或params传参,this.$router.push( )
2.sessionstore传参
6.路由之间跳转
声明式(标签跳转) 编程式( js跳转)
①.直接修改地址栏中的路由地址 ②通过router-link实现跳转 ③通过js的编程的方式
vue路由两种方式:name和<router-link>中的to传参
<router-link:to = "{name: xxx, params: { key :value }}"> valuestring </router-link>
vue-router利用url传参
7.vue计算属性
watch:监听属性,监听数的变化,监听对象。
computed:计算属性,对属性业务逻辑的操作,不循环。它对数据处理后,缓存内存里面。方法对任务操作。
8.vuex是什么?怎么使用?哪种功能场景使用它?
vue框架中状态管理,处理组件间的通讯。
使用:在main.js引入store,注入。新建一个目录store,….. export 。
场景有:单页应用中,组件之间的状态。音乐播放、登录状态、加入购物车
main.js:
import store from './store'
new Vue({
el:'#app',
store
})
属性有五种,分别是 State、 Getter、Mutation 、Action、 Module
· vuex的State特性
A、Vuex就是一个仓库,仓库里面放了很多对象。其中state就是数据源存放地,对应于一般Vue对象里面的data
B、state里面存放的数据是响应式的,Vue组件从store中读取数据,若是store中的数据发生改变,依赖这个数据的组件也会发生更新
C、它通过mapState把全局的 state 和 getters 映射到当前组件的 computed 计算属性中
· vuex的Getter特性
A、getters 可以对State进行计算操作,它就是Store的计算属性
B、 虽然在组件内也可以做计算属性,但是getters 可以在多组件之间复用
C、 如果一个状态只在一个组件内使用,是可以不用getters
· vuex的Mutation特性
Action 类似于 mutation,不同在于:Action 提交的是 mutation,而不是直接变更状态;Action 可以包含任意异步操作。
(3)不用Vuex会带来什么问题?
· 可维护性会下降,想修改数据要维护三个地方;
· 可读性会下降,因为一个组件里的数据,根本就看不出来是从哪来的;
· 增加耦合,大量的上传派发,会让耦合性大大增加,本来Vue用Component就是为了减少耦合,现在这么用,和组件化的初衷相背。
9.Vue中引入组件的步骤?
1)采用ES6的import ... from ...语法或CommonJS的require()方法引入组件
2)对组件进行注册,代码如下
1. // 注册
2. Vue.component('my-component', {
template: '<div>A custom component!</div>'
})
使用组件<my-component></my-component>
10.vue.cli中怎样使用自定义的组件?
第一步:在components目录新建你的组件文件(smithButton.vue),script一定要export default {
第二步:在需要用的页面(组件)中导入:import smithButton from ‘../components/smithButton.vue’
第三步:注入到vue的子组件的components属性上面,components:{smithButton}
第四步:在template视图view中使用,<smith-button> </smith-button>
问题有:smithButton命名,使用的时候则smith-button。
11.vue的虚拟DOM
Virtual DOM算法,简单总结下包括几个步骤:
- 用JS对象描述出DOM树的结构,然后在初始化构建中,用这个描述树去构建真正的DOM,并实际展现到页面中
- 当有数据状态变更时,重新构建一个新的JS的DOM树,通过新旧对比DOM数的变化diff,并记录两棵树差异
- 把步骤2中对应的差异通过步骤1重新构建真正的DOM,并重新渲染到页面中,这样整个虚拟DOM的操作就完成了,视图也就更新了
12.自定义指令(v-check、v-focus)的方法有哪些?它有哪些钩子函数?还有哪些钩子函数参数?
全局定义指令:在vue对象的directive方法里面有两个参数,一个是指令名称,另外一个是函数。
组件内定义指令:directives
钩子函数:bind(绑定事件触发)、inserted(节点插入的时候触发)、update(组件内相关更新)
钩子函数参数:el、binding
13.怎么定义vue-router的动态路由?怎么获取传过来的动态参数?
在router目录下的index.js文件中,对path属性加上/:id。 使用router对象的params.id
14.active-class是哪个组件的属性?嵌套路由怎么定义?
vue-router模块的router-link组件。
嵌套路由顾名思义就是路由的多层嵌套。 一级路由里面使用children数组配置子路由,就是嵌套路由。
15.为什么避免 v-if 和 v-for 用在一起?
当 Vue 处理指令时,v-for 比 v-if 具有更高的优先级,这意味着 v-if 将分别重复运行于每个 v-for 循环中。通过v-if 移动到容器元素,不会再重复遍历列表中的每个值。
16.为什么使用key?
当有相同标签名的元素切换时,需要通过 key 特性设置唯一的值来标记以让 Vue 区分它们,否则 Vue 为了效率只会替换相同标签内部的内容。
17.4种vue当中的指令和它的用法
v-if:判断是否隐藏;v-for:数据循环;v-bind:class:绑定一个属性;v-model:实现双向绑定
18.怎么定义vue-router的动态路由以及如何获取传过来的动态参数?
在router目录下的index.js文件中,对path属性加上/:id。使用router对象的params.id。
19.<keep-alive></keep-alive>的作用是什么?
<keep-alive></keep-alive> 包裹动态组件时,会缓存不活动的组件实例,主要用于保留组件状态或避免重新渲染。
20.v-show和v-if指令的共同点和不同点
v-show指令是通过修改元素的display的CSS属性让其显示或者隐藏
v-if指令是直接销毁和重建DOM达到让元素显示和隐藏的效果
21.vue中v-if与v-show的区别以及使用场景
v-if 是通过控制dom节点的存在与否来控制元素的显隐;
v-show是通过设置DOM元素的display样式,block为显示,none为隐藏;
v-if 有更高的切换消耗;
v-show有更高的初始渲染消耗;
v-if切换局部编译/卸载的过程中合适地销毁和重建内部的事件监听和子组件;
v-show只是简单的基于css切换;
场景:如果需要非常频繁地切换,则使用 v-show 较好;如果在运行时条件很少改变,则使用 v-if 较好
· v-show指令是通过修改元素的display的CSS属性让其显示或者隐藏
· v-if指令是直接销毁和重建DOM达到让元素显示和隐藏的效果
22.vue常用的修饰符
事件修饰符
.stop:用来阻止单击事件的冒泡
.self:表示当前事件发生在元素本身而不是子元素的时候进行触发
.prevent:表示提交事件不再进行重新加载
.capture:表示事件倾听,在事件发生的时候进行调用
表单修饰符(重点):
.lazy - 取代 input 监听 change 事件
.number - 输入字符串转为有效的数字
.trim - 输入首尾空格过滤
按键修饰符:
.enter
.tab
.delete
鼠标按键修饰符
.left
.right
.middle
23.axios是什么?怎么使用?它实现的登录流程?
登陆流程为:1、提交登陆表单,拿到后台返回的数据 2、将数据存入vuex
登录状态token,和用户名user存在sessionStorage里,以便组件使用,如果token为true表示用户已经登陆
axios是基于promise(诺言)用于浏览器和node.js是http客户端。
axios的作用是什么呢:axios主要是用于向后台发起请求的,还有在请求中做更多是可控功能。
特点:支持浏览器和node.js
支持promise
能拦截请求和响应
能转换请求和响应数据
能取消请求
自动转换JSON数据
浏览器支持防止CSRF(跨站请求伪造)