1.Vue生命周期:
Vue实例从创建到销毁的过程,就是声明周期。从创建实例、初始化数据、编译模板、挂载DOM(->渲染)、更新(->渲染)、卸载等一系列过程,我们称之为Vue的生命周期。
共分为八个阶段,如下:
创建前/后,载入前/后,更新前/后、销毁前/后。
- beforeCreate:可以在这加个loading事件,在加载实例时触发
- created:初始化完成时的事件写在这里,如在这结束loading事件,异步请求也适宜在这里调用。
- beforeMount
- mounted:挂载元素,获取到DOM节点。
- beforeUpdate
- updated:如果对数据统一处理,在这里写上相应函数。
- beforeDestroy:可以做一个确认停止事件的确认框。
- destroyed
2.Vue的生命周期的作用:
它的生命周期中有很多事件钩子函数,让我们在控制整个Vue实例的过程时,更容易形成好的逻辑。
生命周期钩子函数(11个) | 类型 | 详细 |
---|---|---|
beforeCreate | Function | 在实例初始化之后 ,数据观测(data observer)和event/watch事件配置之前被调用 |
created | Function | 在实例创建完成后 被立即调用。在这一步,实例已经完成以下配置:数据观测(data observer) ,属性和方法的运算 ,watch/event事件的回调 。然而挂载阶段还没开始,$el属性目前不可见。 |
beforeMount | Function | 在挂载开始之前 被调用,相关的render函数首次被调用 |
mounted | Function | el 被新创建的vm.$el 替换,并挂载到实例上之后 调用该钩子。如果root实例挂载了一个文档内元素,当mounted被调用时vm.$el也在文档内 |
beforeUpdate | Function | 数据更新时调用 ,发生在虚拟DOM打补丁之前。这是适合更新之前访问现有的DOM,比如手动移除已添加的事件监听器。该钩子在服务器端渲染期间不被调用,因为只有初次渲染才会在服务器端运行 |
updated | Function | 由于数据更新导致的虚拟DOM重新渲染和打补丁 ,在这之后 会调用该钩子。 |
activated | Function | keep-alive组件激活时调用 。该钩子在服务器端渲染期间不被调用。 |
deactivated | Function | keep-alive组件停用时调用 。该钩子在服务器端渲染期间不被调用。 |
beforeDestory | Function | 实例销毁之前 调用。在这一步,实例仍然完全可用。该钩子在服务器端渲染期间不被调用。 |
destroyed | Function | 实例销毁后 调用。调用后,实例指示的所有东西都会解绑定,所有事件监听器会被移除,所有的子实例也会被销毁。该钩子在服务器端渲染期间不被调用。 |
errorCaptured(2.5.0+ 新增) | (err: Error, vm: Component, info: string) => ?boolean | 当捕获一个来自子孙组件时被调用。此钩子会收到三个参数:错误对象、发生错误的组件实例以及一个包含错误来源信息的字符串。此钩子可以返回 false 以阻止该错误继续向上传播。 |
注意:
-
mounted
、updated
不会承诺所有的子组件也都一起被挂载。如果你希望等到整个视图
都渲染完毕
,可以用vm.$nextTick
替换掉mounted
、updated
:
updated: function () {
this.$nextTick(function () {
// Code that will run only after the
// entire view has been re-rendered
})
}
- http请求建议在
created
生命周期内发出。需要页面加载完成之后的话就用mounted
。
4.MVVM概念:Model-View-ViewModel
·MVVM的核心是ViewModel层,它就像是一个中转站,负责转换Model中的数据对象来让数据变得更容易管理和使用,该层向上与视图层进行双向数据绑定,向下与Model层通过接口请求进行数据交互,起承上启下作用
- View层:View层是视图层,也就是用户界面。前端主要有HTML+CSS构建。
- Model层:Model是指数据模型,泛指后端进行的各种业务逻辑处理和数据操控,对于前端来说就是后端提供的API接口。
- ViewModel层:ViewModel是前端开发人员组织 生成和维护的视图数据层。在这一层,前端开发者对从后端获取的Model数据进行转换处理,做二次封装,以生成符合View层使用与其视图数据模型。需要注意的是ViewModel所封装出来的视图数据模型包括视图的状态和行为两部分,而Model层的数据模型只包含状态,比如页面的这一块展示什么,而页面加载进来时发生什么,点击这一块发生什么,这一块滚动时发生什么这些都属于视图行为(交互),视图状态和行为都封装在了 ViewModel 里。这样的封装使得 ViewModel 可以完整地去描述 View 层。
//具体实现
//View层
{{message}}
//ViewModel层
var app = new Vue({
el: '#app',
data: { // 用于描述视图状态
message: 'Hello Vue!',
},
methods: { // 用于描述视图行为
showMessage(){
let vm = this;
alert(vm.message);
}
},
created(){
let vm = this;
// Ajax 获取 Model 层的数据
ajax({
url: '/your/server/data/api',
success(res){
vm.message = res;
}
});
}
})
//Model层
{
"url": "/your/server/data/api",
"res": {
"success": true,
"name": "IoveC",
"domain": "www.cnblogs.com"
}
}
4.Vue是如何实现数据双向绑定的:
·Vue数据双向绑定主要是指:数据变化更新视图,视图变化更新数据。
即:
- 输入框内容变化时,Data 中的数据同步变化。即 View => Data 的变化。
- Data 中的数据变化时,文本节点的内容同步变化。即 Data => View 的变化。
其中,View变化更新Data,可以通过事件监听的方式来实现。所以Vue的数据双向绑定的工作主要是如何根据Data变化更新View。
Vue主要通过以下四个步骤来实现数据双向绑定
:
- 实现一个
监听器Observer
:对数据对象进行遍历,包括子属性对象的属性,利用Object.defineProperty()对属性都加上 setter和getter。这样的话,给这个对象的某个值赋值,就会触发setter,那么就能监听到数据的变化了。 - 实现一个
解析器Compile
:解析Vue模板指令,将模板中的变量都替换成数据,然后初始化渲染页面视图,并将每个指令对应的节点绑定更新函数,添加监听数据的订阅者,一旦数据有变动,收到通知,调用更新函数进行数据更新。 - 实现一个
订阅者Watcher
:Watcher订阅者是监听器Observer和解析器Compile之间通信的桥梁,主要的任务是订阅Observer中的属性值变化的消息,当收到属性变化的消息时,触发解析器Compile中对应的更新函数。 - 实现一个
订阅器Dep
:订阅器采用 发布-订阅 设计模式,用来收集订阅者Watcher,对监听器Observer和解析器Compile进行统一管理。
4.v-show和v-if的区别:
·编译过程:
v-if 是 真正 的 条件渲染,因为它会确保在切换过程中条件块内的事件监听器
和子组件
适当地被销毁
和重建
。v-show
的元素始终会
被渲染并保留在 DOM 中
。v-show
只是简单地切换
元素的 CSS 属性display
。
·编译条件:
v-if 是惰性的:如果在初始渲染时条件为假,则什么也不做。直到条件第一次变为真时,才会开始渲染条件块。v-show
不管初始条件是什么,元素总是会被渲染,并且只是简单地基于 CSS 进行切换。
·性能消耗:
v-if有更高的切换消耗。v-show有更高的初始渲染消耗
。
·应用场景:
v-if适合运行时条件很少改变时使用。v-show适合频繁切换
`
6.绑定class的数组用法:
·对象方法:v-bind:class="{ active: isActive, 'text-danger': hasError }"
当isActive和hasError为true时,才会将active和text-danger两个样式添加到class中。
·数组方法:
·绑定内联样式:
data: {
activeColor: 'red',
fontSize: 30
}
7.组件之间的传值通信:
<1>父组件传值给子组件:使用props
{{ msg }}
<2>子组件向父组件通信:
在父组件
中 通过v-on
监听 当前实例上的 自定义事件。
在子组件
中 通过'$emit'
触发 当前实例上的 自定义事件。
10.Computed和Watch:
<1>Computed:
·computed是计算属性,更多用于计算值的场景
·computed具有缓存性,computed的值在getter执行后是会缓存的,只有在它依赖的属性值改变之后,下一次获取computed的值时才会重新调用对应的getter来计算
·computed适用于计算比较消耗性能的计算场景
<2>Watch:
·更多的是观察的作用,类似于某些数据的监听回调,用于观察props、$emit或者本组件的值,当数据变化时来执行回调进行后续操作
·无缓存性,页面重新渲染时值不变化也会执行
<3>用法:
1. 当我们要进行数值计算,而且依赖于其他数据,那么把这个数据设计为computed
2. 如果你需要在某个数据变化时做一些事情,使用watch来观察这个数据变化
11.构建vue-cli工程都用到了那些技术以及它们的作用:
·vue.js
:vue-cli工程的核心,主要特点是双向数据绑定和组件系统;
·vue-router
:vue.js的路由框架;
·vuex
:专为vue.js应用项目开发的状态管理器,主要用于维护vue组件间共用的一些变量和方法;
·axios
(或者 fetch、ajax):用于发起GET、POST等http请求,基于promise设计实现;
·vux
:一个专为vue设计的移动端UI组件库;
·创建一个emit.js
文件,用于管理vue的事件机制;
·webpack
:模块加载和vue-cli工程打包器
12.vue-cli的常用命令:
·npm install
:下载node_modules资源包的命令;
·npm run dev
:启动vue-cli开发环境的命令;
·npm run build
:vue-cli生成生产环境部署资源的命令;
·npm run build --report
:vue-cli生成生产环境部署资源,并查看文件大小的命令。
13.vue-cli工程中文件夹及文件的用处:
·build文件夹
:用于存放webpack相关配置和脚本。例如经常需要用到webpack.dev.config.js来配置less、sass、stylus等css预处理器,或者用来配置UI库;
·config文件夹
:主要存放配置文件,用于区分开发环境和生产环境的不同。常用到config.js配置开发环境的端口号、是否开启热加载或者设置生产环境的静态资源相对路径、是否开启gzip压缩、npm run build命令打包生成静态资源的名称和路径等。(webpack.*.config.js);
·dist文件夹
:存放npm run build打包生成的静态资源文件,用于生产部署;
·node_modules
:存放npm install下载的开发环境和生产环境的依赖包;
·src文件夹
:存放项目源码及需要引用的资源文件;
·src/assets
:存放项目中需要用到的资源文件,js、css、image等;
·src/components
:存放vue开发中一些公共组件;
·src/emit
:自己配置的vue集中式事件机制管理;
·src/router
:vue-router vue路由的配置文件;
·src/service
:自己配置的vue请求后台的接口方法;
·src/page
:存放vue页面组件;
·src/util
:存放公共js方法;
·src/vuex
:存放vuex vue的状态管理器;
·src/app.vue
:使用标签
·src/main.js
:vue-cli工程的入口文件;
·src/index.html
:设置项目的一些meta头信息和提供
·
package.json
:用于管理node_modules依赖包和启动、打包项目的npm命令。
14.config文件夹 下 index.js 的对于工程 开发环境 和 生产环境 的配置:
·port
:设置端口号;
·autoOpenBrowser
:启动工程时,自动打开浏览器;
·proxyTable
:vue设置的代理,以解决跨域问题
15.package.json配置:
·scripts
:配置npm run xxx命令调用node执行的.js文件;
·dependencies
:生产环境依赖包的名称和版本号,这些依赖包会被打包进生产环境的JS文件里面;
·devDependencies
:开发环境依赖包的名称和版本号,这些依赖包只用于代码开发的时候,不会打包生产环境的JS文件里面。
16.vue.js的两个核心:
·双向数据绑定
,也叫数据驱动:Vue.js数据观测原理在技术实现上,利用的是ES5 Object.defineProperty和存储器属性getter、setter,可称为基于依赖收集的观测机制。核心是VM(ViewModel),保证数据和视图的一致性;
·组件系统
:组件系统的核心选项
template(模板):模板声明了数据和最终展现给用户的DOM之间的映射关系;
Data(初始数据):一个组件的初始数据状态。对于可复用的组件来说,这通常是私有的状态;
props(接收的外部参数):组件之间通过参数来进行数据的传递和共享;
methods(方法):对数据的改动操作一般都在组件的方法内进行;
lifecycle hooks(生命周期钩子函数):一个组件会触发多个声明周期钩子函数;
assets(私有资源):Vue.js中将用户自定义的指令、过滤器、组件等统称为资源。一个组件可以声明自己的私有资源。私有资源只有该组件及它的子组件可以调用。
17.对于Vue是一套 构建用户界面 的 渐进式框架 的理解:
渐进式的含义是:没有多做职责之外的事情;
vue.js只提供了vue-cli生态中最核心的部分组件系统
和双向数据绑定
。像vuex、vue-router都属于围绕vue.js开发的库。
18.vue的常用指令:
·v-if
:根据表达式的布尔值对元素进行渲染。在切换时,元素及它的数据绑定/组件被销毁或重建;
·v-show
:根据表达式的布尔值,切换元素的display CSS属性值;
·v-for
:循环指令,基于一个数组或对象渲染一个列表。vue2.0以上必须配合key值使用;
·v-bind
:动态的绑定一个或多个特性,或一个组件prop到表达式;
·v-on
:用于监听指定元素的DOM事件,比如点击事件。绑定事件监听器;
·v-model
:实现表单输入和应用状态之间的双向绑定;
·v-pre
:跳过这个元素和它的子元素编译的过程。可以用来显示原始Mustache标签。跳过大量没有指令的节点会加快编译;
·v-once
:只渲染元素和组件一次。随后的重新渲染,元素/组件及其所有的子节点都被视为静态内容并跳过。这可以优化更新的性能。
19.vue常用的修饰符:
v-on 指令常用修饰符:
.stop - 调用 event.stopPropagation(),禁止事件冒泡。
.prevent - 调用 event.preventDefault(),阻止事件默认行为。
.capture - 添加事件侦听器时使用 capture 模式。
.self - 只当事件是从侦听器绑定的元素本身触发时才触发回调。
.{keyCode | keyAlias} - 只当事件是从特定键触发时才触发回调。
.native - 监听组件根元素的原生事件。
.once - 只触发一次回调。
.left - (2.2.0) 只当点击鼠标左键时触发。
.right - (2.2.0) 只当点击鼠标右键时触发。
.middle - (2.2.0) 只当点击鼠标中键时触发。
.passive - (2.3.0) 以 { passive: true } 模式添加侦听器
v-bind 指令常用修饰符:
.prop - 作为一个 DOM property 绑定而不是作为 attribute 绑定。
.camel - (2.1.0+) 将 kebab-case 特性名转换为 camelCase.
.sync (2.3.0+) 语法糖,会扩展成一个更新父组件绑定值的 v-on 侦听器。
v-model 指令常用修饰符:
.lazy - 取代 input 监听 change 事件
.number - 输入字符串转为数字
.trim - 输入首尾空格过滤
20.v-on监听多个方法:
但是同一种事件类型的方法,vue-cli工程会报错,例如:
21.vue中key值的作用:
主要用在 Vue 的虚拟 DOM 算法,在新旧 nodes 对比时辨识 VNodes。如果不使用 key,Vue 会使用一种最大限度减少动态元素并且尽可能的尝试就地修改/复用相同类型元素的算法。而使用 key 时,它会基于 key 的变化重新排列元素顺序,并且会移除 key 不存在的元素。
有相同父元素的子元素必须有独特的 key。重复的 key 会造成渲染错误。
22.vue事件中使用event对象:
event click
showEvent(event){
console.log(event.target.dataset.id)
event.preventDefault();
event.stopPropagation();
}
23.$nextTick():
·作用
:将回调延迟到下次 DOM 更新循环之后执行。在修改数据之后立即使用它,然后等待 DOM 更新。它跟全局方法Vue.nextTick
一样,不同的是回调的this
自动绑定到调用它的实例上。
Vue.component('example', {
template: '{{ message }}',
data: function () {
return {
message: '未更新'
}
},
methods: {
updateMessage: function () {
this.message = '已更新'
console.log(this.$el.textContent) // => '未更新'
this.$nextTick(function () {
console.log(this.$el.textContent) // => '已更新'
})
}
}
})
24.Vue 组件中 data 为什么必须是函数?
Vue.component('my-component', {
template: 'OK',
data() {
return {} // 返回一个唯一的对象,不要和其他组件共用一个对象进行返回
},
})
这个操作是一个简易操作,实际上,它
- 首先需要创建一个组件构造器,
- 然后注册组件。
- 注册组件的本质其实就是建立一个组件构造器的引用。
- 使用组件才是真正创建一个组件实例。
- 所以,注册组件其实并不产生新的组件类,但会产生一个可以用来实例化的新方式。
类比引用数据类型
Object是引用数据类型,如果不用function 返回,每个组件的data 都是内存的同一个地址,一个数据改变了其他也改变了;
javascipt只有函数构成作用域(注意理解作用域,只有函数的{}
构成作用域,对象的{}
以及 if(){}
都不构成作用域),data是一个函数时,每个组件实例都有自己的作用域,每个实例相互独立,不会相互影响
const MyComponent = function() {};
MyComponent.prototype.data = {
a: 1,
b: 2,
}
const component1 = new MyComponent();
const component2 = new MyComponent();
component1.data.a === component2.data.a; // true;
component1.data.b = 5;
component2.data.b // 5
如果两个实例同时引用一个对象,那么当你修改其中一个属性的时候,另外一个实例也会跟着改;
两个实例应该有自己各自的域才对,需要通过下面的方法来进行处理
const MyComponent = function() {
this.data = this.data();
};
MyComponent.prototype.data = function() {
return {
a: 1,
b: 2,
}
};
参考:https://www.jianshu.com/p/839...
25.v-for 与 v-if 的优先级
当它们处于同一节点时,v-for优先级高于v-if。
//只显示完成了的
{{ todo }}
26.vue中 keep-alive 组件的作用:
·作用
:主要用于保留组件状态或避免重新渲染;
有一个`列表页面`和一个`详情页面`,那么用户就会经常执行打开`详情=>返回列表=>打开详情`这样的话 列表 和 详情 都是一个`频率很高`的页面,那么就可以`对列表组件`使用` `进行缓存,这样用户每次`返回列表`的时候,都能`从缓存中快速渲染`,而`不是重新渲染`。
·属性
:
- include:字符串或正则表达式,只有匹配的组件
会被缓存
。 - exclude:字符串或正则表达式,任何匹配的组件都
不会被缓存
。
·用法
:
包裹动态组件
时,会缓存
不活动的组件实例,而不是销毁
它们。和
相似,
是一个抽象组件:它自身不会渲染一个 DOM 元素,也不会出现在父组件链中。
注意:
`是用在其一个
直属的子组件被开关的情形。如果你在其中有
v-for则不会工作。如果有上述的
多个条件性的子元素,
要求同时
只有一个`子元素被渲染。
·include 和 exclude 属性的使用
:
27.vue中编写可复用的组件:
·Vue.js组件API主要的三部分:prop、事件、slot;
- prop允许外部环境(父组件)传递数据给可复用组件,在vue-cli工程中也可以使用vuex等传递数据;
- 事件允许组件触发外部环境的action;(可复用组件传递给父组件)
- slot允许外部环境(父组件)将内容插入到组件的视图结构中。
fsfs
28.vue监听键盘事件中的按键
可以为v-on监听键盘事件的时候添加按键修饰符
//基本用法,直接使用keycode,但是难以记住
常规按键修饰符
:.enter、.tab、.delete、.esc、.space、.up、.down、.left、.right
//使用按键别名
新增修饰符
:.ctrl、.shift、.alt、.meta
仅在按下相应按键时才触发鼠标
或键盘事件
的监听器。
请注意修饰键与常规按键不同,在和 keyup 事件一起用时,事件触发时修饰键必须处于按下状态。换句话说,只有在按住 ctrl 的情况下释放其它按键,才能触发 keyup.ctrl。而单单释放 ctrl 也不会触发事件。
//使用按键修饰符
//ALT+C
//Ctrl + Click
doSomething
.exact
:修饰符允许你控制由精确的系统修饰符组合触发的事件。
自定义按键修饰符别名
:config.keyCodes
// 可以使用 `v-on:keyup.f1`
Vue.config.keyCodes.f1 = 112
29.vue更新数组时触发视图更新的方法:
·push()、pop()、sort()、reverse()、shift()、unshift()、splice()
·替换数组的方法:用新数组去覆盖旧的数组去触发视图更新
filter()、concat()、slice()这些方法都会返回一个新数组
items = items.filter((item)=>{
return item.message > 0;
})
//不会重新渲染整个数组,而是重新渲染修改的数组项(新增或删除的等等)
·不会触发视图更新的方法:
当你利用索引直接设置一个项时,vm.items[indexOfItem] = newValue
当你修改数组的长度时,vm.items.length = newLength
替换办法:
// 一下两种都可以解决第一个问题
Vue.set(vm.items, indexOfItem, newValue)
vm.items.splice(indexOfItem, 1, newValue)
//第二个修改数组长度问题
vm.items.splice(newLength)
30.vue中对象更改检测的注意事项
·Vue不能检测对象属性的添加
或删除
,无法响应式的重新渲染视图。但是原属性的修改可以响应。
//解决办法:Vue.set(object, key, value)
var vm = new Vue({
data: {
user: {
name: 'Anika'
}
}
})
Vue.set(user,'age',20);
//也可以使用 `vm.$set`实例方法,它只是全局`Vue.set`的别名
//vm是当前实例,一般组件中用this即可
//vm.$set(user,'age',20);
//添加多个属性可以利用Object.assign()方法覆盖原对象
vm.user = Object.assign({},vm.user,{
age: 20,
favor: 'apple'
})
31.过滤器
·调用过滤器
{{ message | capitalize }}
·创建过滤器
//在一个组件的选项中定义本地的过滤器
filters: {
capitalize: function (value) {
if (!value) return ''
value = value.toString()
return value.charAt(0).toUpperCase() + value.slice(1)
}
}
//在创建 Vue 实例之前全局定义过滤器
Vue.filter('capitalize', function (value) {
if (!value) return ''
value = value.toString()
return value.charAt(0).toUpperCase() + value.slice(1)
})
new Vue({
// ...
})
·项目中常用的自定义文件创建方法
//src/filter/filter.js
function filterOne(n){
return n + 10;
}
function filterTwo(n){
return n + 5;
}
export{
filterOne,
filterTwo
}
//main.js
import * as filters from './filter/filter.js'
//遍历所有导出的过滤器并添加到全局过滤器
Object.keys(filters).forEach((key) => {
Vue.filter(key, filters[key]);
})
32.常用的vue-cli脚手架模板:webpack
npm init webpack my-project 创建项目
33.组件以及JS中使用全局常量
·组件中使用全局常量:
//src/const/const.js
export default{
install (Vue,options){
vue.prototype.global = {
title: '全局',
isBack: true,
isAdd: false
};
}
}
//main.js中全局引入
import constant from './const/const.js'
vue.user(constant);
//组件中调用
this.global.title
{{ gloabal.title }}
·JS中使用常量
//src/const/type.js
export const TEST_ADD = "TEST_ADD"
export const TEST_DEC = "TEST_DEC"
//js文件中引入
import * as types from '../types'
types.TEST_ADD
34.计算属性的缓存和方法调用的区别:得到的结果是一样的
·计算属性是基于它们的依赖进行缓存的,只在相关依赖发生改变的时候才会重新求值。而每当触发重新渲染时,调用方法总会再次执行函数。
·使用计算属性还是methods取决于是否需要缓存,当遍历数组和做大量计算时,应当使用计算属性将结果缓存下来。
·计算属性是根据依赖自动执行的,methods需要事件调用。
Vue-router
1.vue-router响应 路由参数 的变化:用watch监听
//例如/user?id=1到/user?id=2
watch:{
'$route'(to,from){
//if(to.path !== from.path)
//if(to.params.id !== from.params.id)
if(to.query.id !== from.query.id){
this.id = to.query.id;
this.init(); //重新加载数据,自定义函数
}
}
}
//使用beforRouteUpdate() vue-router的内置钩子函数
beforeRouteUpdate(to,from,next){
if(to.fullPath !== from.fullPath){
next();
this.changeUser();
}
},
methods:{
changeUser:()=>{
getUserInfo({userId:this.$route.params.id}).then(res => {
if(res.success){
this.userInfo = res.data;
}else{
....
}
})
}
}
//使用v-bind:key,阻止组件复用,只要路由变化就重新创建这个组件
2.vue-router的导航守卫(导航钩子):导航守卫主要用于路由正在发生改变时,通过跳转或者取消的方式守卫导航。
参数或查询的改变并不会触发进入/离开的导航守卫。你可以通过观察 $route
对象来应对这些变化,或使用beforeRouteUpdate
的组件内守卫
·router.beforeEach(to,from,next)(全局守卫):
·router.beforeResolve(to,from,next)(全局解析守卫):
·router.afterEach(to,from)(全局后置守卫):
·beforeEnter(to,from,next)(路由独享的守卫):
·beforeRouteEnter(to,from,next)、beforeRouteUpdate(to,from,next)、 beforeRouteLeave(to,from,next)(组件内的守卫):
注意
:确保要调用next
方法,否则钩子就不会被 resolved
。
3.vue-router的几种实例方法以及参数传递:
vue-router的实例方法
实例方法 | 说明 |
---|---|
this.$router.push(location, onComplete?, onAbort?) | 这个方法会 向history添加一个新的记录 ,所以当用户点击浏览器后退按钮时,则回退到之前的URL;点击 |
this.$router.replace(location, onComplete?, onAbort?) | 这个方法不会 向history添加一个新的记录,而是替换掉当前的history记录,所以点击后退按钮时不会回退 |
this.$router.go(n) | 参数是一个整数,作用是在history记录中向前或者向后后退几步 |
- onComplete以及onAbort回调会在导航成功完成(在所有的异步钩子被解析之后)或者导航终止(导航的相同的路由、或在当前导航完成之前导航到另一个路由)的时候进行调用;
- 如果目标路由和当前路由只是参数不同(/user/1 -> /user/2),则需要使用组件内的导航守卫beforeRouteUpdate来响应这个变化(抓取渲染页面数据信息)
参数传递的方式:params、query、meta三种
// 字符串,不带参数
this.$router.push('home')
// 对象,不带参数
this.$router.push({ path: 'home' })
// params(推荐):命名的路由,params 必须和 name 搭配使用
this.$router.push({ name:'user',params: { userId: 123 }})
// 这里的 params 不生效
this.$router.push({ path:'/user',params: { userId: 123 }})
// query:带查询参数,变成 /register?plan=private
this.$router.push({ path: 'register', query: { plan: 'private' }})
//meta方式:路由元信息
export default new Router({
routes: [
{
path: '/user',
name: 'user',
component: user,
meta:{
title:'个人中心'
}
}
]
})
//通过 $route 对象获取,注意是route
this.$route.params.userId
this.$route.query.userId
this.$route.meta.title
4.$route和$router的区别:$route
是“路由信息对象”,包含path、fullPath、params、query、name、hash、matched等路由信息参数;$router
是“路由实例对象”,包括了路由的跳转方法和钩子函数等。
- 动态路由的匹配及使用:
const router = new Router({
routes:[
{
path: '/user/:id', //匹配/user/bar、/user/foo等等
component: User
}
]
})
//template中获取
this.$route.params.id
6.嵌套路由:
const router = new Router({
routes:[{
path: '/user/:id',
component: User,
children: [
//不设置这个子路由将无法匹配/user/:id
{
path:'', //匹配/user/:id,渲染UserHome组件
component: UserHome
},
{
path: 'profile', //匹配/user/:id/profile
component: UserProfile
}
]
}]
})
7.
·支持用户在具有路由功能的应用中点击导航。可以通过to
属性指定目标地址,当目标路由成功激活时,链接元素自动设置一个表示激活的CSS类名。
属性 | 类型 | 声明 | 示例 |
---|---|---|---|
to | StringLocation | 表示目标路由的链接。当被点击后,内部会立刻把to的值传到router.push(),所以这个值可以是一个字符串或者描述目标位置的对象 | |
replace | boolean(默认false) | 设置为true时,点击会调用router.replace()方法,于是导航后就不会留下history记录 | |
append | boolean(默认false) | 设置为true后,则在当前相对路径前添加基路径。例如/a -> /b,会变成/a/b,如果没配置就单纯是/b | |
tag | string(默认‘a’) | 可以设置成别的标签,例如 | |
active-class | string(默认router-link-active) | 设置激活链接时使用的css类名。默认值可以通过路由的构造选项linkActiveClass来全局配置 | |
exact | boolean(默认false) | "是否激活" 默认类名的依据是inclusive match (全包含匹配) 。 举个例子,如果当前的路径是 /a 开头的,那么也会被设置 CSS 类名。 |
这个链接只会在地址为 / 的时候被激活: |
event | stringArray(默认click) | 声明可以用来触发导航的事件。 |
8.动态加载路由组件(懒加载)
·把不同路由对应的组件分割成不同的代码块,然后当路由被访问的时候才加载对应组件
·结合 Vue 的异步组件
和 Webpack 的代码分割
功能,轻松实现路由组件的懒加载。
//第一步,在/src/router/index.js里面异步引入组件.vue
const index = () => import('../page/list/index.vue')
//第二步,配置路由
const router = new Router({
routes: [
{
path: '/index',
component: index,
name: 'index'
}
]
})
//第三步,配置webpack.base.config.js的output属性,添加chunkFileName
output: {
path: config.build.assetsRoot,
filename: '[name].js',
//新增chunFilename属性
chunkFilename: '[name].js',
publicPath: process.env.NODE_ENV === 'production'
? config.build.assetsPublicPath
: config.dev.assetsPublicPath
},
Vuex
1.Vuex概念:
·vuex是一个专门为vue.js应用程序开发的状态管理器。它采用 集中式存储 管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。
·vuex就是专门解决页面与页面之间需要的共享变量的创建、维护和变更的问题
。
·有了vue-router,可以将一个组件视为一个页面来使用。由于组件只维护自身的状态(data),组件创建时或者说进入路由时它们被初始化,切换至其他的组件页时当前页自然要被销毁,从而导致data也随之销毁。
页面与页面之间总会产生各种需要的共享变量,如果通过$router.param或者$router.meta来传递是远远不够的,所以就需要vuex来实现这个需求。
2.vuex的核心概念:
·每一个vuex应用的核心就是store(仓库)。store基本上就是一个容器,它包含着你的应用中的大部分状态state。
·vuex和单纯的全局对象的不同:
- Vuex的状态存储是响应式的。当Vue组件从store中读取状态的时候,如果store中的状态发生变化,那么相应的组件也会得到高效的更新;
- 你不能直接改变store中的状态。改变store中的状态的唯一途径就是显示的提交(commit)mutation。这样可以使我们方便的追踪每一个状态的变化。
- state:Vuex store实例的
根状态对象
。用于定义共享的状态变量。 - Action:
动作
,向store发出调用通知,执行本地或者远端的某一操作(可以理解为store的methods)。 - Mutations:
修改器
,它只用于修改state中定义的状态变量。 - getter:
读取器
,外部程序通过它获取状态变量的具体值,或者在取值前做一些计算(可以认为是store的计算属性)。
3.Vuex在vue-cli中的应用:
·下载Vuex依赖包:npm install vuex --save
·在src/main.js中引入:
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
·创建src/store/store.js:导出Vuex.Store实例
import Vue from 'vue'
import Vuex from 'Vuex'
//index.js存放action、mutations、getter 也可以把他们拆分成单独文件再引入
import index from './index.js'
Vue.use(Vuex)
export default new Vuex.Store({
index
})
·创建src/store/index.js:存放action、mutations、getter
import * as types from './types'
const state = {
//vuex初始化值
count: 0
}
const actions = {
increment({ commit },n){
commit(types.TEST_INCREMENT,n)
},
decrement({ commit },state){
commit(types.TEST_DECREMENT,n)
}
}
const getters = {
count: state => state.count
}
const mutations = {
[types.TEST_INCREMENT](state, n){
console.log(n)
state.count = state.count + n + 5
},
[types.TEST_DECREMENT](state, status){
state.count = state.count - 3
}
}
export default {
state,
actions,
getters,
mutations
}
·创建 src/store/types.js:存放常量
export const TEST_INCREMENT = 'TEST_INCREMENT'
export const TEST_DECREMENT = 'TEST_DECREMENT'
4.组件中使用vuex的值和修改值
·直接获取、修改
//获取:state\getter
this.$store.state.count
this.$store.getters.count
//修改
this.$store.actions('increment')
this.$store.actions('increment',{value:123})
·通过辅助函数获取、修改:mapState、mapGetters、mapActions
也就是将vuex的变量或者方法映射到vue组件this指针上,通过map获取到的变量或者方法,可通过 this 直接使用或者调用。
computed:{
mapState([
'count'
])
}
computed:{
mapGetters([
'count'
])
}
methods:{
mapActions({
increment:'increment',
decrement:'decrement'
})
}
5.vuex中使用异步修改:
·在调用Vuex的Action中的方法时,用promise实现异步修改
const actions = {
asyncIncrement({ commit }, n){
return new Promise(resolve => {
setTimeout(()=>{
commit(types.TEST_INCREMENT,n);
resolve();
},3000)
})
}
}
axios
1.axios的基本写法及安装
·npm install axios --save
//post请求
axios.post('/user',{name: 'abc'}).then( res => {
console.log(res.updateName);
});
axios({
method: 'POST',
url: '/user',
data:{
name: 'abc'
}
});
//get请求
axios.get('/user?ID=1234').then( res =>{
console.log(res.data);
});
axios('/user/1234').then( res =>{
consoe.log(res.status);
})
2.axios的特点:
- Axios是一个基于Promise的HTTP库,支持Promise的所有API
- 它可以拦截请求和响应
- 它可以转换请求数据和响应数据,并对响应回来的内容自动转换为JSON类型的数据
- 安全性更高,客户端支持防御CSRF跨域请求伪造
3.解决跨域问题:
·vue-cli项目中通过node.js代理服务器来实现跨域请求
//在config/index.js文件里配置dev对象的proxyTable对象
//仅适用于开发环境,生产环境没解决
dev:{
env: require('./dev.env'),
port: 8080,
autoOpenBrowser: false,
assetsSubDirectory: 'static',
assetsPublicPath: '/',
proxyTable:{
'/api': { //请求服务器接口文件夹名称
target: 'http://www.abc.com', //目标接口域名
changeOrigin: true, //是否跨域
pathRewrite: {
'^/api': '/api' //重写接口
}
},
cssSourceMap: false
}
//'http://localhost:8080/api' ===> 'http://www.abc.com/api'
·在服务器响应客户端的时候,带上Access-Control-Allow-Origin:* 头信息 (推荐)
·通过jQuery的jsonp形式解决跨域问题