Vue基础内容

1.Vue生命周期:
Vue实例从创建到销毁的过程,就是声明周期。从创建实例、初始化数据、编译模板、挂载DOM(->渲染)、更新(->渲染)、卸载等一系列过程,我们称之为Vue的生命周期。
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 以阻止该错误继续向上传播。

注意:

  • mountedupdated不会承诺所有的子组件也都一起被挂载。如果你希望等到整个视图渲染完毕,可以用vm.$nextTick替换掉mountedupdated
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层通过接口请求进行数据交互,起承上启下作用
Vue基础内容_第1张图片

  • 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数据双向绑定主要是指:数据变化更新视图,视图变化更新数据。
Vue基础内容_第2张图片

即:

  • 输入框内容变化时,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进行统一管理。

Vue基础内容_第3张图片

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





<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工程中文件夹及文件的用处:
Vue基础内容_第4张图片
·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:使用标签渲染整个工程的.vue组件;
·src/main.js:vue-cli工程的入口文件;
·src/index.html:设置项目的一些meta头信息和提供

用于挂载vue节点;
·package.json:用于管理node_modules依赖包和启动、打包项目的npm命令。

14.config文件夹 下 index.js 的对于工程 开发环境 和 生产环境 的配置:
Vue基础内容_第5张图片
·port:设置端口号;
·autoOpenBrowser:启动工程时,自动打开浏览器;
·proxyTable:vue设置的代理,以解决跨域问题

15.package.json配置:
Vue基础内容_第6张图片
·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.push()
    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是“路由实例对象”,包括了路由的跳转方法和钩子函数等。

    1. 动态路由的匹配及使用:
    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(),所以这个值可以是一个字符串或者描述目标位置的对象 Home
    replace boolean(默认false) 设置为true时,点击会调用router.replace()方法,于是导航后就不会留下history记录 Home
    append boolean(默认false) 设置为true后,则在当前相对路径前添加基路径。例如/a -> /b,会变成/a/b,如果没配置就单纯是/b
    tag string(默认‘a’) 可以设置成别的标签,例如
  • foo
    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。这样可以使我们方便的追踪每一个状态的变化。

    Vue基础内容_第7张图片

    • 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形式解决跨域问题

    你可能感兴趣的:(前端,vue.js)