转发补充教你如何学好Vue文档

7次阅读

共计 27912 个字符,预计需要花费 70 分钟才能阅读完成。

从新对博客内容进行了修改,为了防止本人的文字引来不必要的歧义,所以删本人对于技术方面的,打算这一分类更多的采纳援用为主。

本文转自简书《教你如何学好 vue《文档》》,但对内容有所删减(Vue 历史、作者以及案例)以及补充,若想理解还请移步至原文。


课程目录

  • ECMAScript 6
  • Vue.js
  • Vue CLI
  • Vuex
  • Vue Router
  • axios
  • webpack
  • Vue SSR
  • RESTful

前置常识

  • HTML
  • CSS
  • JavaScript
  • 根本的 ECMAScript 6 语法
  • 根本的 Ajax 应用
  • node 命令行操作
  • npm 命令
  • 根本的 Git 操作

ECMAScript 6 罕用的根底知识点

ES6 介绍

ECMAScript 6.0(以下简称 ES6)是 JavaScript 语言的下一代规范,曾经在 2015 年 6 月正式公布了也叫 ECMAScript 2015。它的指标,是使得 JavaScript 语言能够用来编写简单的大型应用程序,成为企业级开发语言

let 和 const 命令

ES6 新增了 let 命令,用来申明变量。它的用法相似于 var,然而所申明的变量,只在 let 命令所在的代码块内无效。

{
    let a = 10;
    var b = 1;
}
a // ReferenceError: a is not defined.
b // 1

for (let i = 0; i < 10; i++) {// ...}
console.log(i); // ReferenceError: i is not defined

const申明一个只读的常量。一旦申明,常量的值就不能扭转。

const PI = 3.1415;
PI // 3.1415
PI = 3; // TypeError: Assignment to constant variable.

const foo = {};

// 为 foo 增加一个属性,能够胜利
foo.prop = 123;
foo.prop // 123

// 将 foo 指向另一个对象,就会报错
foo = {}; // TypeError: "foo" is read-only

const let 不存在变量晋升


变量的解构赋值

let a = 1;
let b = 2;
let c = 3;

// ES6 容许写成上面这样。let [a, b, c] = [1, 2, 3];

// 对象的解构赋值
let {foo, bar} = {foo: 'aaa', bar: 'bbb'};
foo // "aaa"
bar // "bbb"

let {bar, foo} = {foo: 'aaa', bar: 'bbb'};
foo // "aaa"
bar // "bbb"

let {baz} = {foo: 'aaa', bar: 'bbb'};
baz // undefined

模板字符串

let place = "world"
// 变量 place 没有申明
let msg = `Hello, ${place}`;

对象的扩大

属性的简洁表示法

const foo = 'bar';
const baz = {foo};
baz // {foo: "bar"}
// 等同于
const baz = {foo: foo};

function f(x, y) {return {x, y};
}
// 等同于
function f(x, y) {return {x: x, y: y};
}
f(1, 2) // Object {x: 1, y: 2}

函数的扩大

函数的扩大 ES6 容许应用 =>(箭头)定义函数。

var f = v => v;
// 等同于
var f = function (v) {return v;};

如果箭头函数的代码块局部多于一条语句,就要应用大括号将它们括起来,并且应用 return 语句返回。

var sum = (num1, num2) => {return num1 + num2;}

箭头函数有几个应用留神点:

  • 函数体内的 this 对象,就是定义时所在的对象,而不是应用时所在的对象
  • 不能够当作构造函数,也就是说,不能够应用 new 命令,否则会抛出一个谬误
  • 不能够应用 arguments 对象,该对象在函数体内不存在。如果要用,能够用 rest 参数代替。
  • 第一点尤其值得注意。this 对象的指向是可变的,然而在箭头函数中,它是固定的。

Promise

Promise 是异步编程的一种解决方案,比传统的解决方案——回调函数和事件——更正当和更弱小。它由社区最早提出和实现,ES6 将其写进了语言规范,对立了用法,原生提供了 Promise 对象。

Promise 对象是一个构造函数,用来生成 Promise 实例。上面代码发明了一个 Promise 实例。

const promise = new Promise(function(resolve, reject) {if (/* 异步操作胜利 */){resolve(value); // 容器状态为胜利
     } else {reject(error); // 容器状态为失败
     }
});

promise.then(function() {console.log('resolved.');
});

对于谬误返回的捕捉

// bad
promise.then(function(data) {// success}, function(err) {// error});

// good
promise.then(function(data) { //cb
    // success
}).catch(function(err) {// error});

内容补充:为什么要用 Promise?

因为 Javascript 是单线程的,所以对于一般函数来讲执行程序是 fun1 > fun2 > fun3 > fun4,但如是多个异步函数,则这种多线程操作就会导致执行程序不固定,为此咱们为了能保障执行程序就须要在一个异步函数中再去运行另一个异步函数,这个行为称之为 回调天堂

Promise 自身是一个同步函数。它能够了解为一个容器,该容器用来监控其中异步函数的执行后果。

Promise 函数执行后,能够通过链式追加 .then() 决定函数胜利或失败后须要操作的内容。

promise.all() 能够将多个 Promise 实例包装成一个新的 Promise 实例。胜利的时候返回的是一个后果数组,而失败的时候则返回最先被 reject 失败状态的值。

promise.race() 顾名思义,就是赛跑的意思,Promise.race([p1, p2, p3]) 外面哪个后果取得的快,就返回那个后果,不论后果自身是胜利状态还是失败状态。

async/ awite

ES2017 规范引入了 async 函数,使得异步操作变得更加不便。async 函数是什么?一句话,它就是 Generator 函数的语法糖。

根本用法

async 函数返回一个 Promise 对象,能够应用 then 办法增加回调函数。当函数执行的时候,一旦遇到 await 就会先返回,等到异步操作实现,再接着执行函数体内前面的语句。

function timeout(ms) {return new Promise((resolve) => {setTimeout(resolve, ms);
    });
}
async function asyncPrint(value, ms) {await timeout(ms);
    console.log(value);
}
asyncPrint('hello world', 50); // 下面代码指定 50 毫秒当前,输入 hello world。

返回 Promise 对象

async function f() {return 'hello world';}
f().then(v =&gt; console.log(v)) // "hello world"

Module

历史上,JavaScript 始终没有模块(module)体系,无奈将一个大程序拆分成相互依赖的小文件,再用简略的办法拼装起来。其余语言都有这项性能,比方 Ruby 的 require、Python 的 import,甚至就连 CSS 都有 @import,然而 JavaScript 任何这方面的反对都没有,这对开发大型的、简单的我的项目造成了微小阻碍。

在 ES6 之前,社区制订了一些模块加载计划,最次要的有 CommonJS 和 AMD(require.js 库,专门用于在浏览器中进行模块化开发,简直曾经淘汰了)两种。前者用于服务器(Node.js),后者用于浏览器。ES6 在语言规范的层面上,实现了模块性能,而且实现得相当简略,齐全能够取代 CommonJS 和 AMD 标准,成为浏览器和服务器通用的模块解决方案。

为了学习不便,咱们这里应用 Node.js 环境来举例说明 ES6 模块规定

这是一个 Node 文件,将其命名为 foo.js,内容如下:

// export 也用于导出
// 然而能够屡次应用
export const a = 1
export const b = 2
export const c = 3
export const d = 4

function add(x, y) {return x + y}

// 等价于 module.exports = add
// export default 只能应用一次
export default add

// 模块中有多个成员,个别都应用 export xxx
// 如果只有一个成员,那就 export default

补充内容:module.export 与 export 的区别
export 导出的源码逻辑如下
module = {export: {}}
var export = module.export
也就是说 export === module.export
当 module.export 内有多个属性的时候,也能够通过 export 导出
但若想独自导出办法或变量时,则只能应用 export default
因为当 export 重定义方法后就与 module.export 脱离了分割

将 foo.js 注入我的项目入口文件 main.js:

// 加载 export default 导出的成员
// import foo from './foo'
// console.log(foo)

// 按需加载 export 导出的成员
// import {a, b} from './foo.mjs'
// console.log(a, b)

// 一次性加载所有成员(包含 default 成员)
// import * as foo from './foo.mjs'
// console.log(foo)
// console.log(foo.a)
// console.log(foo.default(10, 3)) // 很少这样去拜访 default 成员

// 为了不便,先加载默认 default 成员,而后加载其它 export 成员
// import abc, {a, b} from './foo'
// console.log(abc) // export default 成员
// console.log(a, b) //

// 能够应用 as 起别名
import {a as aa} from './foo'
console.log(aa)
// console.log(foo(1, 2))

补充内容:
import * as xxx from ‘xxx’ // 会将若干 export 导出的内容组合成一个对象返回
import xxx from ‘xxx’ // 只会导出这个默认的对象作为一个对象


Vue 根底

  • 官网文档:https://cn.vuejs.org/

Vue 是什么?

它自身只是一个用于数据驱动视图更新的库,但随着衍生生态的倒退,现在曾经有了 Vue RouterVuexVue CLIVue Server Renderer 等性能库,所以当 Vue 和这些外围性能库联合到一起的时候,咱们称之为一个框架(Vue 全家桶)。

Vue.js 不反对 IE8 及其以下版本, 因为 Vue 应用了 IE8 无奈模仿的 ECMAScript 5 个性。但它反对所有兼容 ECMAScript 5 的浏览器。最新稳固版本:2.6.10

装置

  • 间接下载

    • 开发版本:https://vuejs.org/js/vue.js
    • 生产版本:https://vuejs.org/js/vue.min.js
  • CDN

    <script src="https://cdn.jsdelivr.net/npm/vue"></script> // 最新稳定版
    <script src="https://cdn.jsdelivr.net/npm/vue@2.6.10/dist/vue.js"></script> // 指定版本
  • 应用 npm 下载(最好创立一个 package.json 文件,用来存储第三方包依赖信息)

    npm install vue // 最新稳定版
    npm install vue@版本号 // 指定版本

创立了第一个 Vue 利用

<meta charset="UTF-8">
<title>Document</title>
<div id="app">
    {{message}}
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.10/dist/vue.js"></script>
<script>
    new Vue({
        el: '#app', // 实例选项
        data: {message: 'Hello Vue.js!' // 申明式渲染}
    })
</script>

实例选项 – el

  • 类型:string | Element:
  • 具体:提供一个在页面上已存在的 DOM 元素作为 Vue 实例的挂载指标。能够是 CSS 选择器,也能够是一个 HTMLElement 实例。在实例挂载之后,元素能够用 vm.$el 拜访
  • 留神:el 不能是 html、body 节点

实例选项 – data

  • 类型:Object | Function
new Vue({
    el: '#app',
    data(){return {message:"demo"}
    }
})

new Vue({
    el: '#app',
    data:{message:"demo"}
})

组件的定义只承受 function,模板中拜访的数据必须初始化到 data 中

模板语法

插值 {{}}

// 文本
<p>{{message}}</p>
<span>{{message}}</span>
<strong>{{message}}</strong>

// JavaScript 表达式
<p>{{number + 1}}</p>
<p>{{number + 1 > 10 ? 'number 大于 10' : 'number 小于 10'}}</p>
<p>{{arr}}</p>
<p>{{message.split('').reverse().join('') }}</p>

v- 指令

指令 (Directives) 是带有 v- 前缀的非凡个性。指令个性的值预期是单个 JavaScript 表达式 (v-for 是例外情况,稍后咱们再探讨)

  • v-if:指令用于条件性地渲染一块内容。这块内容只会在指令的表达式返回真值的时候被渲染。

    <h1 v-if="awesome">Vue is awesome!</h1>
  • v-else

    <div v-if="Math.random() > 0.5">
        Now you see me
    </div>
    <div v-else>
        Now you don't
    </div>
  • v-else-if

    <div v-if="type ==='A'">
        A
    </div>
    <div v-else-if="type ==='B'">
        B
    </div>
    <div v-else>
        Not A/B
    </div>
  • v-show

    <h1 v-show="ok">Hello!</h1>

一般来说,v-if 有更高的切换开销,而 v-show 有更高的初始渲染开销。因而,如果须要十分频繁地切换,则应用 v-show 较好;如果在运行时条件很少扭转,则应用 v-if 较好

  • v-text

    <div v-text="text"></div> // 带标签的内容不会被解析
  • v-html

    <div v-text="text"></div> // 带标签的内容会被解析
  • v-model(表单输出绑定):

    <input v-model="test"/> // 这个指令是一个语法糖,个别只用于 input 标签
  • v-for(列表渲染)

    v-for="item in todos"
    v-for="(item, index) in todos"
  • v-bind(绑定指令)

    绑定指令能绑定元素上的任何属性,罕用的比方 id, style, class, src, … 也能绑定自定义属性。

    操作元素的 class 列表和内联款式是数据绑定的一个常见需要, 因为它们都是属性,所以咱们能够用 v-bind 解决它们, 在将 v-bind 用于 class 和 style 时,Vue.js 做了专门的加强。表达式后果的类型除了字符串之外,还能够是对象或数组

    Class 绑定

    // 个别应用
    // class 的值就是变量 className 的值
    <div v-bind:class="className"></div>
    <div v-bind:class="className?'a':'b'"></div>
    
    // 对象语法
    // 如果变量 isActive 值为真则有 active 这个类,否则没有
    <div v-bind:class="{active: isActive}"></div>
    <script>
    data: {isActive: true}
    </script>
    // 渲染为
    <div class="active"></div>
    
    // 数组语法(应用偏少)<div v-bind:class="[activeClass, errorClass]"></div>
    <script>
    data: {
        activeClass: 'active',
        errorClass: 'text-danger'
    }
    </script>
    // 渲染为
    <div class="active text-danger"></div>

    Style 绑定

    // 对象语法
    <div v-bind:style="{color: activeColor, fontSize: fontSize +'px'}"></div>
    <script>
    data: {
        activeColor: 'red',
        fontSize: 30
    }
    </script>
    // 间接绑定到一个款式对象通常更好,这会让模板更清晰
    <div v-bind:style="styleObject"></div>
    <script>
    data: {
        styleObject: {
            color: 'red',
            fontSize: '13px'
        }
    }
    </script>

    缩写

    <a v-bind:href="url">...</a> // 残缺语法
    <a :href="url">...</a> // 缩写
  • v-on(监听指令)

    能够用 v-on 指令监听 DOM 事件,并在触发时运行一些 JavaScript 代码。

    <div id="example-1">
        <button v-on:click="counter += 1">Add 1</button>
        <p>The button above has been clicked {{counter}} times.</p>
    </div>
    
    var example1 = new Vue({
        el: '#example-1',
        data: {counter: 0}
    })

    许多事件处理逻辑会更为简单,所以间接把 JavaScript 代码写在 v-on 指令中是不可行的。因而 v-on 还能够接管一个须要调用的办法名称

    <div id="example-2">
        <!-- `greet` 是在上面定义的办法名 -->
        <button v-on:click="greet">Greet</button>
        <!-- DOM 的原生事件,能够用非凡变量 $event 把它传入办法 -->
        <button v-on:click="say('hi')">Say hi</button>
    </div>
    var example2 = new Vue({
        el: '#example-2',
        data: {name: 'Vue.js'},
        methods: { // 在 `methods` 对象中定义方法
            greet: function (event) {alert('Hello' + this.name + '!') // `this` 在办法里指向以后 Vue 实例
                if (event) { // `event` 是原生 DOM 事件
                    alert(event.target.tagName)
                }
            },
            say: function (message,ev) {alert(message)
                console.log(ev)
            }
        }
    })

    缩写

    <a v-on:click="doSomething">...</a> // 残缺语法
    <a @click="doSomething">...</a> // 缩写

    补充内容:修饰符
    .stop 阻止事件冒泡
    .self 当事件在该元素自身触发时才触发事件
    .capture 增加事件侦听器是,应用事件捕捉模式
    .prevent 阻止默认事件
    .once 事件只触发一次

slot 插槽(补充)

补充内容:《vue 中的 slot(插槽)》

插槽(Slot)是 Vue 提出来的一个概念,正如名字一样,插槽用于决定将所携带的内容,插入到指定的某个地位,从而使模板分块,具备模块化的特质和更大的重用性。

插槽显不显示、怎么显示是由父组件来管制的,而插槽在哪里显示就由子组件来进行管制。

<template>
<div>
    <slotOne1>
        <p style="color:red"> 我是父组件插槽内容 </p>
    </slotOne1>
</div>
</template>

在父组件援用的子组件中写入想要显示的内容,<p style=”color:red”> 我是父组件插槽内容 </p> 为组件插槽显示的内容

<template>
    <div class="slotOne1">
        <slot></slot>
    </div>
</template>

在子组件中写入 slot,slot 所在的地位承接的就是父组件中 <p style=”color:red”> 我是父组件插槽内容 </p>

具名插槽

<template>
    <div class="slottwo">
        <slot name="header"></slot>
        <slot></slot>
        <slot name="footer"></slot>
    </div>
</template>

在子组件中定义了三个 slot 标签,其中有两个别离增加了 name 属性 header 和 footer

<template>
  <div>
    <slot-two>
        <p> 啦啦啦,啦啦啦,我是卖报的小里手 </p>
        <template slot="header">
            <p> 我是 name 为 header 的 slot</p>
        </template>
        <p slot="footer"> 我是 name 为 footer 的 slot</p>
    </slot-two>
  </div>
</template>

在父组件中应用 template 并写入对应的 slot 值来指定该内容在子组件中事实的地位(当然也不必必须写到 template),没有对应值的其余内容会被放到子组件中没有增加 name 属性的 slot 中

计算属性 (computed)

  • 计算属性是依据源数据衍生进去的新数据,既然是衍生的数据,那只有源数据在 data 中申明过即可,同时,计算属性的试图更新必须依赖于 data 属性的更新,此外衍生进去的新数据不能在 data 中有定义
  • 计算属性的名称就是计算属性处理函数的名称,应用时能够在模版中绑定计算属性,绑定办法与 data 中的一般属性统一
  • 计算结果并返回,只有当被计算的值产生扭转时才会触发
  • 计算属性是在 DOM 执行实现后执行,该属性有缓存性能
// 根底用法
data() {
    return {str: 'string'}
}
computed: {beautifyStr() {return this.str.split('');
    }
}

监听器(watch)

对 data 属性的监听,阐明属性是在 data 中申明过的属性更新时调用监听函数,可选参数别离为新值和旧值,对属性从新设置值只有跟原来的值相等就不会触发函数调用,这一点跟计算属性是类似的,监听某一个值,当被监听的值发生变化时,执行对应的操作,与 computed 的区别是,watch 更加实用于监听某一个值的变动并做对应的操作,比方申请后盾接口等,而 computed 实用于计算已有的值并返回后果

// 根底用法
new Vue({
    el: '#id',
    data: {
        firstName: 'Leo',
        lastName: 'Alan',
        obj1: {a: 0}
    },
    watch: {
        // 监听 firstName, 当 firstName 发生变化时就会执行该函数
        firstName(newName, oldName) {
            // 执行须要的操作...
            // 注:初始化不会执行,只有当被监听的值 (firstName) 发生变化时才会执行
        },
        // 监听 lastName
        lastName: {handler(newName, oldName) {// 执行须要的操作...},
            immediate: true // true: 初始化时就会先执行一遍该监听对应的操作
        },
        obj1: {handler() {// 执行须要的操作...},
            deep: true // 该属性默认值为 false.
            // 当被监听的值是对象,只有 deep 为 true 时,对应属性的值 (obj1.a) 发生变化时能力触发监听事件,然而这样十分耗费性能
        },
        // 监听对象具体的属性,deep 就不须要设置为 true 了
        'obj1.a': {handler() {// 执行须要的操作...}
        }
    }
})

Vue-Cli 脚手架

Vue CLI 是 Vue 的脚手架工具,它能够帮忙咱们疾速生成 Vue 根底我的项目代码,提供开箱即用的性能个性。

  • 官网文档:https://cli.vuejs.org/
  • GitHub:https://github.com/vuejs/vue-cli

装置

// > 依赖要求:Vue CLI 须要 Node.js 8.9 或更高版本 (举荐 8.11.0+)。npm install -g @vue/cli

在终端中输出 vue --version 若能够打印出版本号,则代表装置胜利。

创立我的项目

运行以下命令来创立一个新我的项目

vue create my-project

内容补充:输出命令后,会跳出如下问题

Project name (baoge) 项目名称(留神这里的名字不能有大写字母,如果有会报错)
Project description (A Vue.js project) 我的项目形容,也可间接点击回车,应用默认名字
Author () 作者
Runtime + Compiler: recommended for most users 运行加编译,既然曾经说了举荐,就选它了
Runtime-only: about 6KB lighter min+gzip, but templates (or any Vue-specificHTML) are ONLY allowed in .vue files – render functions are required elsewhere 仅运行时,曾经有举荐了就抉择第一个了
Install vue-router? (Y/n) 是否装置 vue-router,这是官网的路由,大多数状况下都应用,这里就输出 y 后回车即可
Use ESLint to lint your code? (Y/n) 是否应用 ESLint 治理代码,ESLint 是个代码格调管理工具
Pick an ESLint preset (Use arrow keys) 抉择一个 ESLint 预设,编写 vue 我的项目时的代码格调,间接 y 回车
Setup unit tests with Karma + Mocha? (Y/n) 是否装置单元测试
Setup e2e tests with Nightwatch(Y/n)? 是否装置 e2e 测试

配置实现后,能够看到目录下多出了一个我的项目文件夹,而后 cd 进入这个文件夹

启动开发模式

npm run serve

我的项目打包

npm run build

代码查看

npm run lint

开发期间不要敞开命令窗口,如果关了,就从新 npm run serve
浏览器中关上 http://localhost:8080/ 看到 vue 初始页面,则阐明初始化创立胜利了

我的项目的目录构造

node_modules // 第三方包存储目录
public // 动态资源,已被托管
src // 源代码
    assets // 资源目录,存储动态资源,例如图片等
    components // 存储其它组件的目录
    App.vue // 根组件
    main.js // 入口文件
.gitignore // git 疏忽文件
babel.config.js // 不必关怀
package.json // 包阐明文件
README.md // 我的项目阐明文件
package-lock.json // 包的版本锁定文件

我的项目的启动过程

找到 main.js 入口 > 加载 Vue > 加载 App 组件 > 创立 Vue 实例 > 将 App 组件替换到入口节点

创立单文件组件

组件 Component 是 Vue.js 最弱小的性能之一。组件能够扩大 HTML 元素,封装可重用的代码。

举荐把通用组件创立到 components 目录中

单文件组件只是承载组件的容器而已,既不是全局也不是部分,如果要应用这个单文件组件,必须注册

单文件组件模板构造如下:

<template>
    <div>foo 组件 </div>
</template>

<script>
export default {data() {},
    methods: {}}
</script>

<style></style>
  • template 只能有一个根节点(template 自身不算)
  • script 用来配置组件的选项(data、methods、watch……)
  • style<style> 标签有 scoped 属性时,它的 CSS 只作用于以后组件中的元素

全局注册应用

在 main.js 文件中,能够在任何组件中应用

import Vue from 'vue'
import Com1 from './components/Com1.vue'

Vue.component('Com1', Com1)
// 接下来就能够在任何组件中应用 Com1 组件了

部分注册应用

在某个组价中部分注册应用

<template>
    <div>
        <!-- 应用 Com2 组件 -->
        <Com2></Com2>
    </div>
</template>

<script>
import Com2 from './components/Com2'

export default {
    components: {Com2}
}
</script>

组件的生命周期

组件的有几个阶段

  • 初始化阶段

    beforeCreate

    示意组件创立前的筹备工作,为事件的公布订阅和生命周期的开始做初始化
    这个钩子函数中数据拿不到,实在 DOM 也拿不到,这个钩子在我的项目中咱们没有什么理论用处

    beforeCreate () { // 示意组件创立前的筹备工作(初始化事件和生命周期)console.log('beforeCreate')
        console.log(this.msg) // undefind
        console.log(document.querySelector('p')) // null 没有实在 DOM
    }

    created

    示意组件创立完结,这个钩子函数中数据拿到了,然而实在 DOM 没有拿到
    这个钩子函数在我的项目个别数据申请,而后能够进行一次默认数据的批改

    created () { // 组件创立完结
        console.log('created')
        console.log(this.msg) //(vue.js) 有数据
        console.log(document.querySelector('p')) //null 没有实在 DOM
        axios({url: './data.json'}).then( res => {this.msg = res}).catch( error => {throw error})
    }

    beforeMounte

    示意组件装载前的筹备工作,判断 el 选项有没有,判断 template 选项有没有,如果没有那么须要手动装载,如果有那么通过 render 函数进行模板的渲染
    这个钩子函数中数据拿到了,实在 DOM 没有拿到,这个钩子函数在我的项目中数据申请,它也能够进行一次数据批改

    beforeMount () {console.log('beforeMount')
        console.log(this.msg) //(vue.js) 有数据
        console.log(document.querySelector('p')) //null 没有实在 DOM
        // axios({
        //     url: './data.json'
        // })
        //   .then( res => {
        //       this.msg = res
        //   })
        //   .catch( error => {
        //       throw error
        //   })
    }

    mounted

    示意组件装载完结,就是咱们能够在视图中看到了,这个钩子函数中数据拿到了,实在 DOM 也拿到了
    这个钩子函数在我的项目 DOM 操作就能够进行了,第三方库的实例化

    mounted () {console.log('mount')
        console.log(this.msg) //(vue.js) 有数据
        console.log(document.querySelector('p')) // 有实在 DOM
        axios({url: './data.json'}).then( res => {this.msg = res}).catch( error => {throw error})
    }

    总结:由上比照,咱们能够晓得,数据申请越提前越好一些,created 罕用于数据的申请和数据的批改,第三方库的实例化常在 mounted 中进行书写

  • 运行中阶段

    beforeUpdate

    示意数据更新前的筹备工作。这个钩子不被动执行,当数据批改了才会执行。这个钩子函数中数据拿到了,并且拿到的是批改后的数据,DOM 也输入了
    这个钩子函数更多的工作内容为:生成新的 VDOM , 而后通过 diff 算法进行两次 VDOM 比照
    这个钩子在我的项目中因为他次要做的事件是外部进行的,所以对咱们而言没有太多的操作意义

    updated

    示意数据更新完结。通过 render 函数渲染实在 DOM。这个钩子函数的执行也是当数据批改的时候才执行。这个钩子函数中数据拿到了,DOM 也拿到了。

    总结:数据更新,也要进行 DOM 操作那么,咱们应用 update 这个钩子

  • 销毁阶段

    beforeDestroy

    destroyed

    这两个钩子无差别,在我的项目中做善后工作。手动革除一些计时器和一些办法,还有第三方实例化进去的对象

    Vue.component ('LifeCircle', {
        template: '#life-circle',
        methods: {destroy () {this.$destroy()
            }
        },
        created () {this.timer = setInterval( () => {console.log('1')
            },1000)
        },
        beforeDestroy () {console.log('beforeDestory')
        },
        destroyed () {console.log('destroyed')
            clearInterval(this.timer)
            // 如果是用 $destroy 这个办法来革除组件,那么咱们必须手动革除这个组件的外壳
            document.querySelector('#app div').remove()}
    })
    new Vue ({
        el: '#app',
        data: {flag: true}
    })

组件通信

组件就像零散的积木,咱们须要把这些积木依照肯定的规定拼装起来,而且要让它们相互之间能进行通信,这样能力形成一个有机的残缺零碎。

在实在的利用中,组件最终会形成树形构造,就像人类社会中的家族树一样

在树形构造外面,组件之间有几种典型的关系:父子关系、兄弟关系、没有间接关系。

相应地,组件之间有以下几种典型的通信计划:

间接的父子关系

  • 父组件通过 this.$refs 拜访子组件
  • 子组件 this.$parent 拜访其父组件
  • 父组件 this.$children 拜访其子组件
  • 父组件通过 Props 给子组件下发数据
    咱们能够用 v-bind 来动静地将 prop 绑定到父组件的数据。每当父组件的数据变动时,该变动也会传导给子组件

    // HelloWorld.vue
    <div>
        <child :myMessage="parentMsg"></child> // 父组件动静变量 parentMsg,通过 myMessage 传递给子组件
    </div>

    子组件通过 prop 属性承受,prop 中的变量名不能在 data 中定义

    <script>
    import HelloWorld from './components/HelloWorld.vue'
    export default {
        name: 'app',
        props: ['myMessage'] // 通过 props 接管到传递过去的数据,props 是一个数组对象
        components: {HelloWorld}
    }
    </script>

    Prop 是单向绑定的,当父组件的属性变动时,将传导给子组件,然而反过来不会,这是为了避免子组件无意间批改了父组件的状态。
    每次父组件更新时,子组件的所有 prop 都会更新为最新值。这意味着你不应该在子组件外部扭转 prop。如果你这么做了,Vue 会在控制台给出正告。

    Prop 验证

    咱们能够为组件的 prop 指定验证规定。如果传入的数据不符合要求,Vue 会收回正告。这对于开发给别人应用的组件十分有用。要指定验证规定,须要用对象的模式来定义 prop。

    export default {
        props: {propA: Number, // 根底类型检测 (`null` 指容许任何类型)
            propB: [String, Number], // 可能是多种类型
            propC: {
                type: String,
                required: true // 必传且是字符串
            },
            propD: {
                type: Number,
                default: 100 // 数值且有默认值
            },
            propE: {
                type: Object,
                default: function () { // 数组 / 对象的默认值该当由一个工厂函数返回
                    return {message: 'hello'}
                }
            },
            propF: {validator: function (value) { // 自定义验证函数
                    return value > 10
                }
            }
        }
    }

    type 能够是上面原生结构器:

    • String
    • Number
    • Boolean
    • Function
    • Object
    • Array
    • Symbol type 也能够是一个自定义结构器函数,应用 instanceof 检测。当 prop 验证失败,Vue 会抛出正告 (如果应用的是开发版本)。留神 prop 会在组件实例创立之前进行校验,所以在 default 或 validator 函数里,诸如 data、computed 或 methods 等实例属性还无奈应用。
  • 子组件通过 事件 形式给父组件发送音讯
    父组件应用 prop 传递数据给子组件。但子组件怎么跟父组件通信呢?
    须要在子组件中调用 $emit() 办法公布一个事件

    methods: {incrementCounter: function () {
            this.counter += 1
            this.$emit('increment') // 公布一个名字叫 increment 的事件
            // this.$emit(事件名, '参数对象");
        }
    }

    在父组件中提供一个子组件外部公布的事件处理函数

    new Vue({
        methods: {incrementTotal: function () {this.total += 1}
        }
    });

    在应用子组件的模板的标签上订阅子组件外部公布的事件

    <div id="counter-event-example">
        <!--
            订阅子组件外部公布的 increment 事件
            当子组件外部 $commit('increment') 公布的时候,就会调用到父组件中的 incrementTotal 办法
        -->
        <button-counter v-on:increment="incrementTotal"></button-counter>
    </div>

没有间接关系

  • 简略场景:借助于事件机制进行通信
    有时候,非父子关系的两个组件之间也须要通信。在简略的场景下,能够应用一个空的 Vue 实例作为事件总线:

    var bus = new Vue();
    // 触发组件 A 中的事件
    bus.$emit('id-selected', 1);
    
    // 在组件 B 创立的钩子中监听事件
    bus.$on('id-selected', function (id) {// ...});
  • 简单场景:应用状态治理容器(例如 Vue 生态中的 Vuex、React 生态中的 Redux、Mobx 等)
    在简单的状况下,咱们应该思考应用专门的状态管理模式。

利用 sessionStorage 和 localStorage 进行通信


axios

Vue 不像 jQuery 内置了 ajax 申请函数,在 Vue 中没有提供这样的性能。所以当咱们须要在 Vue 中和服务端进行通信的时候可抉择的形式会更灵便一些。

留神:Vue 不提供的起因是为了让 Vue 自身更专一于视图局部,放弃其渐进灵便的个性

axios 是一个基于 Promise 的第三方 HTTP 客户端申请库,能够用于浏览器或者 Node.js。axios 自身和 Vue 没有一毛钱关系,只是简略纯正的封装了 HTTP 申请性能。能够运行在任何反对 JavaScript 环境的平台。

axios 依赖原生的 ECMAScript 6 Promise 反对。如果浏览器不反对 ECMAScript 6 Promise,能够应用 es6-promise 进行兼容解决

装置

npm install axios

执行一个 GET 申请

const axios = require('axios');

// Make a request for a user with a given ID
axios.get('/user?ID=12345').then(function (response) {
    // handle success
    console.log(response);
}).catch(function (error) {
    // handle error
    console.log(error);
}).finally(function () {// always executed});

// Want to use async/await? Add the `async` keyword to your outer function/method.
async function getUser() {
    try {const response = await axios.get('/user?ID=12345');
        console.log(response);
    } catch (error) {console.error(error);
    }
}

执行一个 POST 申请

axios.post('/user', {
    firstName: 'Fred',
    lastName: 'Flintstone'
}).then(function(response) {console.log(response)
}).catch(function(error) {console.log(error)
})

执行多个并发申请

function getUserAccount() {return axios.get('/user/12345')
}

function getUserPermissions() {return axios.get('/user/12345/permissions')
}

axios.all([getUserAccount(), getUserPermissions()]).then(axios.spread(function(acct, perms) {// Both requests are now complete})
)

axios API

axios(config),咱们能够像应用 $.ajax() 一样来应用 axios

// Send a POST request
axios({
    method: 'post',
    url: '/user/12345',
    data: {
        firstName: 'Fred',
        lastName: 'Flintstone'
    }
})

// GET request for remote image
axios({
    method: 'get',
    url: 'http://bit.ly/2mTM3nY',
    responseType: 'stream'
}).then(function(response) {response.data.pipe(fs.createWriteStream('ada_lovelace.jpg'))
})

Vuex

补充内容:以下补充参考《VueX(Vue 状态管理模式)》

Vuex 是一个专为 Vue.js 利用程序开发的状态管理模式。它采纳集中式存储管理利用的所有组件的状态,能够帮忙咱们治理共享状态,并以相应的规定保障状态以一种可预测的形式发生变化。

如果您不打算开发大型单页利用,应用 Vuex 可能是繁琐冗余的。的确是如此——如果您的利用够简略,您最好不要应用 Vuex。一个简略的 store 模式就足够您所需了。然而,如果您须要构建一个中大型单页利用,您很可能会思考如何更好地在组件内部治理状态,Vuex 将会成为自然而然的抉择。

VueX 中的核心内容

在 VueX 对象中,其实不止有 state , 还有用来操作 state 中数据的办法集,以及当咱们须要对 state 中的数据须要加工的办法集等等成员。
成员列表:

  • state 寄存状态
  • mutations state 成员操作
  • getters 加工 state 成员给外界
  • actions 异步操作
  • modules 模块化状态治理

VueX 的工作流程

首先,Vue 组件如果调用某个 VueX 的办法过程中须要向后端申请时或者说呈现异步操作时,须要 dispatch VueX 中 actions 的办法,以保证数据的同步。能够说,action 的存在就是为了让 mutations 中的办法能在异步操作中起作用。

如果没有异步操作,那么咱们就能够间接在组件内提交状态中的 M utations 中本人编写的办法来达成对 state 成员的操作。留神,1.3.3 节中有提到,不倡议在组件中间接对 state 中的成员进行操作,这是因为间接批改 (例如:this.$store.state.name = ‘hello’) 的话不能被 VueDevtools 所监控到。

最初被批改后的 state 成员会被渲染到组件的原地位当中去。

装置

npm install vuex --save

创立仓库

在 src 文件目录下新建一个名为 store 的文件夹,为不便引入并在 store 文件夹里新建一个 index.js(如果脚手架生成有 vuex 那间接跳到 3 步)

import Vue from 'vue';
import Vuex from 'vuex';

// 挂载 Vuex
Vue.use(Vuex);

// 创立 VueX 对象
const store = new Vuex.Store({
    state:{name:'helloVueX' // 寄存的键值对就是所要治理的状态}
})

export default store;

将 store 挂载到以后我的项目的 Vue 实例(main.js),这样一来就能够在任何一个组件外面应用 this.$store 了

import Vue from 'vue';
import Vuex from 'vuex';
import store from './store'// 引入 store
new Vue({
    // el: '#app',
    store // store: store,将咱们创立的 Vuex 实例挂载到这个 vue 实例中
    render: h => h(App),
}).$mount('#app')

补充内容:Vue 的挂在形式一共,别离为
el
$mount() 手动挂载到节点;
template 以组件模式注入;
render 以原生 js 的写法注入;

在组件中应用 Vuex,例如在 App.vue 中,咱们要将 state 中定义的 name 拿来在 h1 标签中显示

<template>
    <div id='app'>
        name:
        <h1>{{$store.state.name}}</h1>
    </div>
</template>

或者要在组件办法中应用

methods:{add(){console.log(this.$store.state.name) // 留神,请不要在此处更改 state 中的状态的值
    }
},

state:状态

设置仓库要保留的值和操作那些值的办法
回到 store 文件的 index.js 外面,咱们先申明一个 state 变量,并赋值一个空对象给它,外面轻易定义两个初始属性值;而后再在实例化的 Vuex.Store 外面传入一个空对象,并把刚申明的变量 state 仍外面

import Vue from 'vue';
import Vuex from 'vuex';

// 挂载 Vuex
Vue.use(Vuex);

const state = { // 要设置的全局拜访的 state 对象
    showFooter: true,
    changableNum: 0 // 要设置的初始属性值
};
const store = new Vuex.Store({state});
export default store;

mutations:更改状态

mutations 是操作 state 数据的办法的汇合,比方对该数据的批改、减少、删除等等
具体的用法就是给外面的办法传入参数 state 或额定的参数,而后利用 vue 的双向数据驱动进行值的扭转,同样的定义好之后也把这个 mutations 扔进 Vuex.Store 外面
mutattions 也是一个对象,都有默认的形参([state] [,payload])

  • state 是以后 VueX 对象中的 state
  • payload 是该办法在被调用时传递参数应用的

例如,咱们编写一个办法,当被执行时,能把下例中的 name 值批改为 ‘jack’,咱们只须要这样做

import Vue from 'vue'
import Vuex from 'vuex'

// 挂载 Vuex
Vue.use(Vuex)

const store = new Vuex.store({
    state:{name:'helloVueX'},
    mutations:{edit(state){// es6 语法,等同 edit:funcion(){...}
            state.name = 'jack'
        }
    }
})

export default store

而在组件中,咱们须要这样去调用这个 mutation ——例如在 App.vue 的某个 method 中

this.$store.commit('edit')

在理论生产过程中,会遇到须要在提交某个 mutation 时须要携带一些参数给办法应用

// 单个值提交时
this.$store.commit('edit')

// 当须要多参提交时,举荐把他们放在一个对象中来提交
this.$store.commit('edit',{age: 15,sex: '男'})

接管挂载的参数

edit(state,payload){
    state.name = 'jack'
    console.log(payload) // 15 或 {age: 15,sex: '男'}
}

另一种提交形式

this.$store.commit({
    type:'edit',
    payload:{
        age: 15,
        sex: '男'
    }
})

增删 state 中的成员

为了配合 Vue 的响应式数据,咱们在 Mutations 的办法中,该当应用 Vue 提供的办法来进行操作。如果应用 delete 或者 xx.xx = xx 的模式去删或增,则 Vue 不能对数据进行实时响应。

  • Vue.set 为某个对象设置成员的值,若不存在则新增

    例如对 state 对象中增加一个 age 成员

    Vue.set(state, 'age', 15)
  • Vue.delete 删除成员

    将刚刚增加的 age 成员删除

    Vue.delete(state, 'age')

getters:计算属性

vuex 官网 API 提供了一个 getters,和 vue 计算属性 computed 一样,来实时监听 state 值的变动(最新状态),并把它也仍进 Vuex.Store 外面

getters 中的办法有两个默认参数

  • state 以后 VueX 对象中的状态对象
  • getters 以后 getters 对象,用于将 getters 下的其余 getter 拿来用
getters:{nameInfo(state){return "姓名:" + state.name // 以后 VueX 对象中的状态对象},
    fullInfo(state, getters){ // 参数 getters 用于将 getters 下的其余 getter,这里也就是 nameInfo 拿来用
        return getters.nameInfo + '年龄:' + state.age
    }
}

组件中调用

this.$store.getters.fullInfo

actions:异步操作

因为间接在 mutation 办法中进行异步操作,将会引起数据生效。所以提供了 Actions 来专门进行异步操作,最终提交 mutation 办法

Actions 中的办法有两个默认参数,Action 提交的是 mutation,而不是间接变更状态

  • context 上下文 (相当于箭头函数中的 this) 对象
  • payload 挂载参数

因为 setTimeout 是异步操作,所以须要应用 actions,请看如下示例

const store = new Vuex.Store({
    state: {name: ''},
    mutations: {edit(state, payload){
            state.name = 'jack'
            console.log(payload) // 15 或 {age: 15,sex: '男'}
        }
    },
    actions: {aEdit(context, payload){setTimeout(() => {context.commit('edit', payload) // 通过 commit 提交 mutation 的形式来批改数据状态
            }, 2000)
        }
    }
})

在组件中调用

this.$store.dispatch('aEdit', {age: 15})

Models

当我的项目宏大,状态十分多时,能够采纳模块化管理模式。Vuex 容许咱们将 store 宰割成模块(module)。每个模块领有本人的 state、mutation、action、getter、甚至是嵌套子模块——从上至下进行同样形式的宰割。

models:{
    a:{state:{},
        getters:{},
        ....
    }
}

组件内调用模块 a 的状态

this.$store.state.a

而提交或者 dispatch 某个办法和以前一样, 会主动执行所有模块内的对应 type 的办法

this.$store.dispatch('aEditKey')

模块中 mutations 和 getters 中的办法承受的第一个参数是本身部分模块外部的 state

models: {
    a: {state: {key: 5},
        mutations: {editKey (state) {state.key = 9}
        }
    }
}

getters 中办法的第三个参数是根节点状态

models: {
    a: {state: {key: 5},
        getters: {getKeyCount (state, getter, rootState) {return  rootState.key + state.key}
        }
    }
}

actions 中办法获取部分模块状态是 context.state, 根节点状态是 context.rootState

models: {
    a: {state: {key: 5},
        actions: {aEidtKey (context) {if (context.state.key === context.rootState.key) {context.commit('editKey')
                }
            }
        }
    }
}

mapState、mapMutations、mapActions、mapGetters

补充内容:高级用法《对于 mapState,mapGetters,mapMutations,mapActions 的学习笔记》

总结:

  • 把须要共享的状态放到 Vuex 容器中进行治理,不须要共享的还是放到组件外部去治理
  • 容器也反对计算属性 getters
  • 批改容器的状态务必通过 mutation 函数,不要在 mutation 函数中执行异步操作去批改 state
  • 因为只有 mutation 能力扭转 state, 如果须要须要执行异步操作批改 state 须要如下操作

    • 定义 action
    • 在 action 中执行异步操作
    • 在 action 中执行异步操作完结只有通过 commit 提交 mutation 的形式来批改数据状态

补充内容:Vue 倡议咱们 mutation 类型用大写常量示意

简略一句话:非异步操作批改状态应用 mutation,异步操作批改状态应用 action。其次咱们应用 Vuex 并不意味着你须要将所有的状态放入 Vuex。尽管将所有的状态放到 Vuex 会使状态变动更显式和易调试,但也会使代码变得简短和不直观。如果有些状态严格属于单个组件,最好还是作为组件的部分状态。你应该依据你的利用开发须要进行衡量和确定。


第八章 Vue-router

补充内容:以下补充参考《从头开始学习 vue-router》
这里的路由并不是指咱们平时所说的硬件路由器,这里的路由就是 SPA(单页利用)的门路管理器。再艰深的说,vue-router 就是 WebApp 的链接门路管理系统。
vue-router 是 Vue.js 官网的路由插件,它和 vue.js 是深度集成的,适宜用于构建单页面利用。vue 的单页面利用是基于路由和组件的,路由用于设定拜访门路,并将门路和组件映射起来。传统的页面利用,是用一些超链接来实现页面切换和跳转的。在 vue-router 单页面利用中,则是门路之间的切换,也就是组件的切换。路由模块的实质 就是建设起 url 和页面之间的映射关系。
至于咱们为啥不能用 a 标签,这是因为用 Vue 做的都是单页利用(当你的我的项目筹备打包时,运行 npm run build 时,就会生成 dist 文件夹,这外面只有动态资源和一个 index.html 页面),所以你写的 标签是不起作用的,你必须应用 vue-router 来进行治理。

应用脚手架初始化的时候能够初始化装置 vue-router,如果没有就手动下载和应用

什么是单页利用

单页利用(英语:single-page application,缩写 SPA):在传统的网页利用中,浏览器更多的是充当一个展现层,路由解决、服务调用、页面跳转流程都由服务端来解决。即 MVC 都放在服务器端,SPA 技术将逻辑从服务器转移到了客户端。这导致 Web 服务器倒退为一个纯数据 API 或 Web 服务。这种架构的转变在一些圈子中被称为“瘦服务器架构”,以强调复杂性已从服务端转移到客户端,并认为这最终升高了零碎的整体复杂性。

传统的网站有以下特点

重服务端,因为 MVC 都存在于服务器上,因而这类利用在开发资源和开发的重心都偏差后端,往往是后端工程师来主导整个我的项目开发;
页面频繁刷新,因为浏览器端只是一个展示层,当页面性能有所变动的时,页面就刷新,这会导致资源的节约,用户须要破费额定的工夫期待页面刷新,用户体验不佳。

而单页面利用,只有一张 Web 页面的利用,是一种从 Web 服务器加载的富客户端,单页面跳转仅刷新部分资源,公共资源 (js、css 等) 仅需加载一次。

单页利用的优缺点

  • 长处

    • 无刷新体验,这个应该是最显著的有点,因为路由散发间接在浏览器端实现,页面不会加载整个页面,而是只更新某个指定的容器中内容。对用户的响应十分及时,因而晋升了用户体验
    • 加重服务器压力,服务器只用出数据就能够,不必管展现逻辑和页面合成,吞吐能力会进步几倍
    • 齐全的前端组件化,前端开发不再以页面为单位,更多地采纳组件化的思维,代码构造和组织形式更加规范化,便于批改和调整
    • 良好的前后端拆散开发,前端负责界面显示,后端负责数据存储和计算,各司其职,不会把前后端的逻辑混淆在一起
  • 毛病

    • 不利于 SEO,单页页面,数据在前端渲染,就意味着没有 SEO,或者须要应用变通的计划(不过目前能够配置服务端渲染来解决这个问题,但还不够足够成熟)
    • 首次加载耗时绝对增多,要在一个页面上为用户提供产品的所有性能,在这个页面加载的时候,首先要加载大量的动态资源,这个加载工夫绝对比拟长
    • 较高的前端开发门槛,对开发人员技能程度要求较高,不再是『切切图,画画页面这么简略』
    • 低版本浏览器兼容差

vue-router 实现原理

vue-router 在实现单页面前端路由时,提供了两种形式:Hash 模式和 History 模式;依据 mode 参数来决定采纳哪一种形式。

  • Hash 模式(默认)

    应用 URL 的 hash 来模仿一个残缺的 URL,于是当 URL 扭转时,页面不会从新加载。hash(#)是 URL 的锚点,代表的是网页中的一个地位,单单扭转 #后的局部,浏览器只会滚动到相应地位,不会从新加载网页,也就是说 hash 呈现在 URL 中,但不会被蕴含在 http 申请中,对后端齐全没有影响,因而扭转 hash 不会从新加载页面;同时每一次扭转 #后的局部,都会在浏览器的拜访历史中减少一个记录,应用“后退”按钮,就能够回到上一个地位;所以说 Hash 模式通过锚点值的扭转,依据不同的值,渲染指定 DOM 地位的不同数据。hash 模式的原理是 onhashchange 事件(监测 hash 值变动),能够在 window 对象上监听这个事件。

  • History 模式

    因为 hash 模式会在 url 中自带 #,如果不想要很丑的 hash,咱们能够用路由的 history 模式,只须要在配置路由规定时,退出 ”mode: ‘history'”,这种模式充分利用了 html5 history interface 中新增的 pushState() 和 replaceState() 办法。这两个办法利用于浏览器记录栈,在以后已有的 back、forward、go 根底之上,它们提供了对历史记录批改的性能。只是当它们执行批改时,尽管扭转了以后的 URL,但浏览器不会立刻向后端发送申请。

    // main.js 文件中
    const router = new VueRouter({
        mode: 'history',
        routes: [...]
    })

装置

npm install vue-router

应用

新建 router 文件夹,而后建设一个 index.js 文件,写入路由的代码

import Vue from 'vue' // 引入 Vue
import Router from 'vue-router' // 引入 vue-router
import Hello from '@/components/HelloWorld' // 引入组件目录下的 HelloWorld.vue 组件
import Demo from '@/components/Demo' // 引入组件目录下的 Demo.vue 组件

Vue.use(Router) // Vue 全局应用 Router

export default new Router({
    // 配置路由,这里是个数组
    // 每一个链接都是一个对象
    routes: [{
        path: '/', // 链接门路 当门路为 http://localhost:8080/#/ 显示此组件
        name: 'Hello', // 路由名称,component: Hello // 对应要显示的组件
    }, { // 每一个链接都是一个对象
        path: '/demo', // 链接门路,当门路为 http://localhost:8080/#/demo 显示此组件
        name: 'Demo', // 路由名称,component: Demo // 对应要显示的组件
    }]
})

在 main.js 全局注册 router

import Vue from 'vue'
import App from './App.vue'
import router from "./router/index.js" // 导入路由
Vue.config.productionTip = false

new Vue({
    // el: '#app',
    router, // 应用路由
}).$mount('#app')

在 App.js 中要应用 router-view 组件

<template>
    <div id="app">
        <router-view></router-view> // 路由匹配到的组件将渲染在这里
    </div>
</template>

路由跳转形式

申明式导航

<template>
    <div id="app">
        <p>
            <router-link to="home">Home</router-link> // 字符串的模式

            // 上面几种为动静绑定
            <router-link :to="index">Home</router-link>
            <script>
            export default {data () {
                    return {index: '/'}
                }
            }
            </script>

            // 这个门路就是路由中配置的门路
            <router-link :to="{path:'/home'}">Home</router-link>
            // 在路由的配置的时候,增加一个 name 属性
            <router-link :to="{name:'User'}">User</router-link>

            // 间接路由带查问参数 query,地址栏变成 /apple?color=red
            <router-link :to="{path:'apple', query: {color:'red'}}">to apple</router-link>
        </p>
        <router-view></router-view> // 路由匹配到的组件将渲染在这里
    </div>
</template>

内容补充:《vue2.0 中 router-link 详解》
在 vue2.0 中,原来的 v-link 指令曾经被 <router-link> 组件代替了
<router-link> 组件反对用户在具备路由性能的利用中点击导航。默认渲染为带有正确连贯的 标签
<router-link> 组件的属性有:
to(必选参数):类型 string/location。示意指标路由的链接,该值能够是一个字符串,也能够是动静绑定的形容指标地位的对象
tag:类型: string 默认值: ‘a’。如果想要 <router-link> 渲染成某种标签,例如 <li>。于是咱们应用 tag
active-class:类型: string 默认值: “router-link-active”。设置链接激活时应用的 CSS 类名
exact-active-class:类型: string 默认值: “router-link-exact-active”。配置当链接被准确匹配的时候应该激活的 class
exact:类型: boolean 默认值: false。” 是否激活 ” 默认类名的根据是 inclusive match (全蕴含匹配)
event:类型: string | Array<string> 默认值: ‘click’。申明能够用来触发导航的事件。能够是一个字符串
replace:类型: boolean 默认值: false。设置 replace 属性的话,当点击时,会调用 router.replace() 而不是 router.push(),于是导航后不会留下 history 记录
append:类型: boolean 默认值: false。设置 append 属性后,则在以后 (绝对) 门路前增加基门路

编程式导航

除了应用 创立 a 标签来定义导航链接,咱们还能够借助 router 的实例办法,通过编写代码来实现后退和后退 this.router.go(1):性能跟咱们浏览器上的后退和后退按钮一样,这在业务逻辑中常常用到。比方条件不满足时,咱们须要后退。

app.vue 文件里退出一个按钮,按钮并绑定一个 goback() 办法

<button @click="goback"> 后退 </button>
<script>
export default {
    name: 'app',
    methods: {goback () {this.$router.go(-1);
        }
    }
}
</script>

编程式导航都作用就是跳转,比方咱们判断用户名和明码正确时,须要跳转到用户核心页面或者首页,都用到这个编程的办法 this.$router.push 来操作路由。

export default {
    name: 'app',
    methods:{goHome(){this.$router.push('/'); // 字符串
            this.$router.push({name: 'applename', query: {color: 'red'}}); // 命名路由带查问参数 query,地址栏变成 /apple?color=red
        }
    }
}

补充内容:动静路由的获取参数办法
在组件中:{{$route.params.color}}
在 js 里:this.$route.params.color

子路由

export default new Router({
    routes: [{
        path: '/',
        name: 'Hello',
        component: Hello
    }, {
        // 对某个路由应用子路由,那么需得在 Hi1 组件内应用 <router-view></router-view> 否则切换
        // 了子路由也无奈显示进去
        path: '/h1',
        name: 'Hi1',
        component: Hi1,  // 当拜访 /h1 的时候显示 Hi1 这个组件
        children: [{
            path: '/',
            component: Hi1
        }, {
            path: 'h2',
            component: Hi2
        }]
    }]
})

路由重定向

重定向也是通过 routes 配置来实现,上面例子是从 /a 重定向到 /b

const router = new VueRouter({
 routes: [{
     path: '/a',
     redirect: '/b'
 }]
})

重定向的指标也能够是一个命名的路由

const router = new VueRouter({
    routes: [{
        path: '/a',
        redirect: {name: 'foo'}
    }]
})

路由守卫(全局前置守卫 beforEach、全局后置钩子 afterEach(少用)、路由独享的守卫 beforeEnter、组件内的守卫)

补充内容:《路由守卫》

路由跳转前做一些验证,比方登录验证,是网站中的广泛需要。对此,vue-route 提供的 beforeRouteUpdate 能够不便地实现导航守卫(navigation-guards)。

正文完
 0