楼主较懒相关代码即代码截图不全,索性把代码也给大家在文章最后自取。

1.Vue是什么

elementUI步骤条二级_vue.js

2.Vue的特点

1.采用组件话模式,提高代码复用率、且代码更好的维护。

elementUI步骤条二级_vue.js_02

一个“.vue”其中包含“html”“css”“js”文件,就是一个组件,使用只调用“.vue”就可以使用其组件。

2.声明式编码,让编码人员无需直接操作Dom,提高开发效率。

elementUI步骤条二级_数据_03


elementUI步骤条二级_逆序_04

3.使用虚拟DOM+优秀的Diff算法,精良复用DOM节点。

elementUI步骤条二级_vue.js_05


elementUI步骤条二级_Vue_06

elementUI步骤条二级_Vue_07

4.学习vue之前要掌握的JavaScript基础知识?

elementUI步骤条二级_逆序_08

3.Vue原理图

elementUI步骤条二级_Vue_09

4.Vue官网API是 Vue的字典

Cn.vuejs.org

第一章vue核心

1. 1初始vue

  1. 1.想让vue工作,就必须创建一个vue实例,且要传入一个配置对象
    2.root容器里的代码依然符合html规范,只不过混入了一些特殊的vue语法,
    3.root容器里的代码被称为【vue模板】
    vue模板:1.准保好以个容器
    2.创建vue实例
    3.把容器放到实例中解析(扫描html是否有vue的语法如:{{name}})2)1.容器于实例时一对一的关系
    2.区分:js表达式 和 js代码
    <1.表达式:一个表达式会产生一个值,可以放在仍和一个需要值得地方 如:1. a
    2 a+b 3.x=== y ? ‘a’ : ‘b’
    <2.js代码(语句) 如: if判断
    3.真实开发中有一个vue实例,并且会配合这组件一起使用
    4.{{…}}中的…要写js表达式,且…可以自动读取到data中的所有属性
    5.一旦data中的数据发生变化,那么页面 中用到该数据的地方会自动更新

1.2模板语法

vue模板语法有2大类:

1.插值语法:

功能:用于解析标签体内容。

写法:{{…}}…是js表达式。且可以直接读取到data中的所有属性。

2.指令语法:

功能:用于解析标签(包括:标签属性、标签体内容、绑定事件…)。 举例:v-bind:href="**" 或 简写为 :href="

插值语句

elementUI步骤条二级_elementUI步骤条二级_10


elementUI步骤条二级_数据_11

指令语句

elementUI步骤条二级_vue.js_12


elementUI步骤条二级_Vue_13

1.3.数据绑定

Vue中有2种数据绑定的方式:

1.单向绑定(v-bind):数据只能从data流向页面。

2. 双向绑定(v-model):数据不仅能从data流向页面,还可以从页面流向data。 备注:

1.双向绑定一般都应用在表单类元素上(如:input、select等)

2.v-model:value 可以简写为 v-model,因为v-model默认收集的就是value值。

单向绑定&双向绑定

elementUI步骤条二级_数据_14

和 v-model 简写

1.4. el与data的两种写法

data与el的两种写法:

1.el有两种写法

(1)…new vu时候配置属性

(2).先创建vue实例,随后在通过vm.$mount(’#root‘)指定el的值。

2.data有2种写法

(1)对象式

(2)函数式

3.一个重要的原则:

由vue管理的函数,一定不要写箭头函数,一旦泄露箭头函数this就不再是

vue实例了。

el的两种写法

elementUI步骤条二级_vue.js_15

Data的两种写法

elementUI步骤条二级_Vue_16

1.5.MVVM模型

1.M 模型(Model):对应data中的数据

2.V 视图(View)模型

3.VM:视图模型(ViewModel):Vue实例对象

elementUI步骤条二级_elementUI步骤条二级_17

**Plain javaScript objects:**一般js对象。

DOM:页面

**VUE:**VUE缔造的实例对象

VueModel:

Data Bindings:数据绑定

DomListeners:Dom结构,Listeneers监听器监听者

elementUI步骤条二级_数据_18

1.6数据代理

1.6.1回顾Object.defineProperty方法

1.Object.defineProperty

Object.defineProperty:为一个对象定义属性的意思(define:定义) (Property:属性) 1.Object.defineProperty能否遍历

1.Object.defineProperty本是枚举类型不可遍历,添加enumerable:ture后可以遍 历(enumerable:true//控制属性是否可以枚举,默认值false)

(1)使用Object.defineProperty方法不可以被console.log(person)直接遍历,添加enumerable:true后可以被遍历。

(2)console.log(Object.keys())无法遍历出Object.defineProperty方法中的值因为不可枚举。

2.Object.defineProperty基本配置项

(1)enumerable:true,//控制属性是否可以枚举,默认值false

(2)writable:true,//控制属性是否可以被修改,默认值false

(3)configurable:true//控制属性是否可以被删除,默认值false

elementUI步骤条二级_数据_19

Get()

当有人读取person的属性是get函数(getter)就会被调用,其返回值就是age的值

elementUI步骤条二级_Vue_20

Set()

当修改person的ages属性是set函数(setter)就会被调用,且会修改的具体的值

elementUI步骤条二级_数据_21

1.6.2什么是数据代理

数据代理:通过一个对象代理对另一个对象进行读/写操作

1.6.3vue中的数据代理

1.Vue中的数据代码: 通过vm对象来代理data对象中属性的操作(读/写) 2.Vue中数据代理的好处: 更加方便的操作data中的数据

3.基本原理:

通过object.defineProperty()把对象中所有属性添加到vm上。

为每一个添加到vm上的属性,都指定一个getter/setter

在getter/setter内部去操作(读/写)data中对应用的属性

elementUI步骤条二级_elementUI步骤条二级_22

1.7.事件处理

1.7.1事件的基本使用

事件的基本使用:

1.使用v-on:xxx 或 @xxx 绑定事件,其中xxx是事件名:

2.事件的回避需要配置methods对象中,最终会在vm上

3.methods中配置的函数,不要用箭头函数:否则this就不是vml

4.methods中配置的函数,都是被vue所管理的函数,this的指向是vm 或 组件实例对象

5.@click=“demo” 和 @click = "demo($Sevent)"效果一致,但后者可以传参;

elementUI步骤条二级_数据_23

1.7.2事件修饰符

Vue中的事件修饰符:

1.prevent:阻止默认事件(常用);

2.stop:阻止事件冒泡(常用);

3.once:事件只触发一次(常用);

4.capture:使用事件的捕获模式;

5.self:只有event.target是当前操作的元素时才触发事件;

6.passive:事件的默认行为立即执行,无需等待事件回调执行完毕;

elementUI步骤条二级_vue.js_24


@scroll滚动条滚动

@where滚动轮的滚动

passive:事件的默认行为立即执行,无需等待事件回调执行完毕

elementUI步骤条二级_vue.js_25

1.7.3键盘事件

1.vue中常有的案件别名:
回车 enter
删除 delete(捕获“删除”和“推格”建)
退出 esc
空格 space
换行 tab (特殊:必须配合keyCodes)
上 up
下 down
左 left
右 right
2.vue未提供别名的按键:可以使用案件原始的key值去绑定:但注意要转为kebab-case(短横线命名)
3.系统修饰键(用法特殊)ctrl、alt、shift、meta
(1).配合keyup使用:按下修饰符的同时,在按下其他键,随后释放其他键,事件才被触发
(2).配合keydown使用:正常触发
4.也可以使用keyCodes去指定具体的按键(不推荐)
5.vue.configkeyCodes.自定义键名 = 键码. 可以制定案件==按键列名

1.8计算属性

计算属性:
1.定义:要用的属性不存在,要通过已有属性计算得来。
2.原理:底层借助了object.definerperty方法提供的getter和setter。
3.get函数什么时候执行?
(1).初次读取会执行一次
(2).等依赖的数据发生改变时会被再次调用。
4.优势:与methods实现相比,内部有缓存机制(复用),效率更高,调式方便。
5.备注:
1.计算属性最终会出现在vm上,直接读取使用即可
2.如果计算属性要被修改,那必须写set函数去响应修改。list中要引起计算时依赖的数据发生变化
关键字:computed不属于data属性 他是计算属性
Computed中的get 和 set
get有什么作用?
当有人读取full Name,get就会被调用且返回值为full Name的值
get什么时候的调用?

  1. 初次读取fullName
  2. 所依赖的数据发生变化时
    set什么时候被调用?
    当fullName被修改的时候

简写

1.9监听事件

1.9.1监听

监视属性watch:
1.当被监视属性变化时,回调函数自动调用,进行相关操作
2.监视的属性必须存在,才能进行监视
3.监视的两种写法:
(1).new Vue 时传入watch配置
(2).通过vm.$watch监视
Handler监视属性关键词
Immediate:true进入代码后立即执行监听属性无需响应式变化
newvalue:获取vue修改前的的值 oldvalue:获取vue修改后的值

1.9.2深度监听

深度监视:
(1).Vue中的watch默认不监视对象内部值的改变(一层)
(2).配置deep:true可以监测对象内部值改变(多层)
备注:
(1).Vue自身可以监测对象内部值的改变,但Vue提供的watch默认不可以!
(2).使用watch时根据的具体结构,决定是否才有深度监控
Deep开启深度监视
Vue可以监视到多层级改变但vue所提供的watch无法检测到多层级数据的改变

1.9.3监听简写
1.9.4watch实现事件监听

computed和watch之间的区别:
1.computed能完成的功能,watch都可以完成。
2.watch能完成的功能,computed不一定能完成。例如:watch可以 进行异步操作。
两个重要的小原则:
1.所被vue管理的函数:最好写成普通函数,这样this的指向才是vm或组件实例对象。
2.所有不被vue所管理的函数(定时器的回调函数、Ajax的回调函数等): 最好写成箭头函数,这样this的指向才能是vm或组件实例对象

1.10 class与style绑定

1.10.1理解

1.在应用界面中,某个(些)元素的样式是变化的
2.class/style绑定就是专门用来实现动态效果的技术

1.10.2 class绑定

  1. :class = “xxx”
  2. 表达式是字符串’classA’
  3. 表达式是对象:{classA:isA,classB:isB}
  4. 表达式是数组

1.11条件渲染

1.11.1条件渲染指令

1.v-if与v-else
2.v-show

1.11.2比较v-if、v-else-if与v-show

1.如果需要频繁切换v-show较好
2.当条件不成立时,v-if的所有子书点不会解析(项目中使用)
条件渲染:
1.v-else-if
写法:
(1)v-if= “表达式”
(2)v-else- if=“表达式”
(3)v-else = “表达式”
适用于:切换频率较低的场景
特点:不展示的dom元素为被移除。
注意:v-if可以和:v-else-iv-else一起使用,但要求结构不能被“打断”
2.v-show
写法:v-show=“表达式”
适用于:切换频率较高的场景
特点:不展示的dom元素为被移除。仅仅使用样式隐藏掉
3.备注:使用v-if的时,元素可能无法获取到,而使用v-show一定可以获取到

1.12列表渲染

1.12.1v-for遍历

v-for指令:
1.用于展示列表数据
2.语法:v-for = “(item , index) in xx” :key=“index”
3.可遍历:数组,对象,字符串(用的很少),指定次数(用的很少)

1.12.2key的作用与原理

面试题:react vue中的key有什么作用?(key的内部原理)

  1. 虚拟DOM中key的作用:key是虚拟DOM中对象的标识,当数据发生变化时,vue会根据新数据生成新的虚拟DOM,随后vue进行更新虚拟DOM与旧虚拟DOM的差异比较,比较规则如下
  2. 对比规则
    a. 旧虚拟DOM中找到了与新虚拟DOM相同key
    i. 若虚拟DOM中内容没变,直接使用之前的真实DOM
    ii. 若虚拟DOM中内容变了,则生成新的真实DOM,随后替换掉页面中之前的真实DOM
    b. 旧虚拟DOM中未找到与新虚拟DOM相同的key
    创建新的真实DOM,随后渲染到页面
  3. 用index作为key可能会引发的问题
    a. 若对数据进行逆序添加、逆序删除等破坏顺序操作,会产生没必要的真实DOM更新界面效果没问题,但效率低
    b. 若结构中还包含输入类的DOM :会产生错误DOM更新界面有问题
  4. 开发中如何选择key?
    a. 做好使用每一条数据的唯一标识作为key,比如id、手机号
    b. 如果不存在对数据的逆序添加,逆序删除等破坏顺序操作,仅用渲染列表用于展示
    使用index作为key是没有 问题的

示例:

elementUI步骤条二级_elementUI步骤条二级_26

1.12.3Vue数据监视
  1. vue会监视data中所有层次的数据
  2. 如何监测对象中的数据?
    通过setter实现监视,且要在new Vue时就传入要监测的数据。
    (1).对象中后追加的属性,Vue默认不做响应式处理
    (2).如需给后添加属性做相应式请使用如下API:
    Vue.set(target.propertyName/index.value)或
    vm.elementUI步骤条二级_elementUI步骤条二级_27set()
    特别注意:Vue.set()和vm.$set() 不能给vm 或 vm的根数据对象 添加属性修改数组

1.13收集表单数据

收集表单数据:
若: 则v-model收集的是value值,用户输入的就是value值。
若:,则v-model收集的是value值,且要给标签配置value值。
若:
1.没有配置input的value属性,那么收集的就是checked(勾选or未勾选,是布尔值)
2.配置input的value属性:
(1).v-model的初始值是非数组,那么收集的就是checked(勾选or未勾选, 是布尔值)
(2).v-model的初始值是数组,那么收集的就是value组成的数组
备注:v-model的三个修饰符:
lazy:失去焦点再收集数据
number:输入字符串转为有效的数字
trim:输入首尾空格过滤

1.14过滤器

过滤器:定一:对要显示的数据进行特定格式化后在显示(适用于一些简单逻辑的处理)
语法:
    1.注册过滤:Vue.filter(name,callback)或new Vue{fillers:{}}
    2.使用过滤器:{{xxx | 过滤器名}}  或 v-bind:属性 = "xxx | 过滤器名"
备注:
    1.过滤器也可以接收额外参数、多个过滤器也可以串联
    2.并没有改变原木的数据,是产生新的对应的数据

1.15自定义指令

自定义指令总结:
      一、定义语法:
           (1).局部指令:
               new Vue({
                   directives:(指令:配置对象)      
               })
               或
               new Vue({
                   directives(指令:回调函数)
               }}
            (2).全局指令:
               Vue.directive(指令,配置对象) 或  Vue.directives(指令名,回调函数)
      二、配置对象中常用的3个回调:
            (1).bind:指令与元素成功绑定时调用。
            (2).inserted:指令所在元素被插入页面调用。
            (3).update:指令所在模板结构被重新解析时调用。
      三、备注:
            1.指令定义时不加v-,但使用时要加v-
            2.指令名如果是多个单词,要使用kebab-case命名方式,不要用cameClase命名。

使用v-big指令:

  1. 使用v-big指令需要创建big方法
  2. V-big有两个默认参数
    big函数何时会被调用?
    1.指令与元素成功绑定时(一上来)。
    2.指令所在的模板被重新解析时。

1.16生命周期

1.16.1引出生命周期

生命周期:
1.又名:声明周期回调函数,生命周期函数,生命周期钩子。
2.是什么:vue在关键时刻帮我们调用的一些特殊名称的函数。
3.生命周期函数的名字不可更改,按函数的具体内容是程序员根据需求编写的。
4.生命周期函数中的this指向是vm或组件实例对象。
Mounted

1.16.2分析生命周期

beforeCreate() vue实例对象创建之前【数据监测、数据代理创建之前】

created()vue实例创建后【数据监测、数据代理创建完毕】

beforeMount()挂载之前【对DOM操作均无效】

mounted()挂载完毕【初始化操作】

beforeUpdate()更新之前【旧的数据】

updated()更新完毕【新的数据】

beforeDestroy()即将删除vue实例对象

destroyed()已经删除vue实例对象

elementUI步骤条二级_elementUI步骤条二级_28

1.16.3总结生命周期

常用的生命周期钩子:
1.mounted:发送Ajax请求,启动定时器,绑定自定义事件,订阅消息等【初始化操作】。
2.beforeDestroy:请求定时器,解绑自定义事件、取消订阅消息等【首位工作】。
关于销毁vue实例:
1.销毁后借助vue开发工具看不到任何信息。
2.销毁后自定义事件会失败,但原生DOM事件依然有效。
3.一般不会再beforeDestroy操作数据,因为即便操作数据,也不会触发更新流程了。

第二章组件化编程

组件的定义:实现应用中局部功能代码和资源的集合

elementUI步骤条二级_数据_29


elementUI步骤条二级_elementUI步骤条二级_30


elementUI步骤条二级_vue.js_31

模块:

  1. 理解: 向外提供特定功能的 js 程序, 一般就是一个 js 文件
  2. 为什么: js 文件很多很复杂
  3. 作用: 复用 js, 简化 js 的编写, 提高 js 运行效率
    组件:
  4. 理解: 用来实现局部(特定)功能效果的代码集合(html/css/js/image……)
  5. 为什么: 一个界面的功能很复杂
  6. 作用: 复用编码, 简化项目编码, 提高运行效率
    模块化:当应用中的 js 都以模块来编写的, 那这个应用就是一个模块化的应用。
    组件化:当应用中的功能都是多组件的方式来编写的, 那这个应用就是一个组件化的应用,。

2.1非单文件组件

一个文件包含有n个组件。
1.基本使用
vue中使用组件的三大步骤:
一、定义组件(创建组件)
二、注册组件
三、使用组件(写组件标签)

一、如何定义一个组件?
       使用vue.extend(options)创建,其中options和new Vue(options)时传入的那个options几乎一样,但也有点区别:
       区别如下:
            1.el不要写。为什么?————最终所有的组件都要经过一个vm的管理,由vm中的el决定服务器那个容器。
            2.data必须写成函数。为什么?————避免组件复用时,数据存在引用关系。
        备注:使用template可以配置组件结构。

二、如何注册组件?
        1.全局注册:靠new Vue的时候传入components选项
        2.全局注册:靠Vue,component(`组件名`,组件)
三、编写组件标签:
        如:<xuexiao></xuexiao>

2.注意点
几个注意点:
1. .关于组件名:
一个单词组件成:
第一种写法(首字母小写):school
第二种写法(首字母大写):school
多个单词组成:
第一种写法(kebab-case命名):my-school
第二种写法(CamelCase命名):Myschool(需要Vue脚手架支持)
备注:
(1).组件名尽可能回避html中已有元素名称,例如:h2、H2都不行。
(2).可以使用name配置项指定组件在开发工具中呈现的名字。
2.关于组件标签:
第一种写法:<schook></schook> 第二种写法:<school/> 备注:不用使用脚手架,<school/>会导致后续组件不能渲染。
3.一个简历方式:
cont school = vue.extend(options) 可简写为:const school = options

3.组件的嵌套
使用component进行嵌套

4.VueComponent介绍(组件原理)

关于VueComponent:

1.school组件本质是一个名为关于VueComponent的构造函数,且不是程序员定义的,是vue.extend生成的。

2.我们只需要写或,Vue解析时会带我们创建school组件实例对象。

即Vue帮我们执行的:new VueComponent(optiond).

3.特别注意:每次调用Vue.extend,返回的都是一个个全新的VueComponent!!!

4.关于this指向:

(1).组件配置中:

data函数、methods中的函数、watch中的函数、computed中的函数 它们的this均是【VueComponent实例对象】。

(2).new Vue()配置中:

data函数、methods中的函数、watch中的函数、computed中的函数 它们的this均是【Vue实例对象】

5.VueComponent的实例对象,以后简称vc(也可称之为:组件实例对象)。

Vue的实例对象,以后简称vm。

elementUI步骤条二级_vue.js_32

2.2单文件组件

一个文件中只包含有1个组件
创建流程:1.创建组件(.vue文件)
2.创建App组件对其进行管理(.vue文件)
3.创建vue实例对象,实现组件。(js文件)
4.创建页面实现vue实例对象(html文件)

  1. 创建组件(.vue文件)
  2. 创建App组件对其进行管理(.vue文件)
  3. .创建vue实例对象,实现组件。(js文件)
  4. .创建页面实现vue实例对象(html文件)

第三章脚手架

3.1初始化脚手架

常用命令:
Vue create xxx(项目名) 创建vue项目
CTRL+~ 打开vue终端
Ctrl+c 暂停/结束vue项目
Npm run serve启动项目
vue inspect > output.js打开脚手架所有webpack相关的配置(只能看,不能改,改也不起作用)
npm run build 打包项目

3.1.1说明

1.Vue脚手架是Vue官方提供的标准化开发工具(开发平台)
2.最新版本是4.x

3.1.2具体步骤

1.如果下载缓慢请配置npm淘宝镜像那 npm config set registry http://registry.npm.taobao.org
2.全局安装@vue/cli npm install -g @vue/cli
3.切换到创建项目的目录,使用命令创建项目vue create xxx
4.选择使用vue版本
5.启动项目npm run serve
6.打包项目npm run build
7.暂停项目 CTRL+c
vue脚手架隐藏了所有webpack相关的配置,若想查看具体的webpack配置请执行:
vue inspect > output.js

3.1.3脚手架结构

脚手架文件结构

├── node_modules 
   ├── public
   │   ├── favicon.ico: 页签图标
   │   └── index.html: 主页面
   ├── src
   │   ├── assets: 存放静态资源
   │   │   └── logo.png
   │   │── component: 存放组件
   │   │   └── HelloWorld.vue
   │   │── App.vue: 汇总所有组件
   │   │── main.js: 入口文件
   ├── .gitignore: git版本管制忽略的配置
   ├── babel.config.js: babel的配置文件
   ├── package.json: 应用包配置文件 
   ├── README.md: 应用描述文件
   ├── package-lock.json:包版本控制文件
3.1.4render函数
import Vue from 'vue'
import App from './App.vue'

Vue.config.productionTip = false

new Vue({
  el:'#app',
  // render函数功能:将App组件放入容器中
  // 简写形式
  render: h => h(App),
  // 完整形式
  // render(createElement){
  //   return createElement(App)
  // }
})
3.1.5关于不同版本的Vue
  1. vue.js与vue.runtime.xxx.js的区别:
  1. vue.js是完整版的Vue,包含:核心功能 + 模板解析器。
  2. vue.runtime.xxx.js是运行版的Vue,只包含:核心功能;没有模板解析器。
  1. 因为vue.runtime.xxx.js没有模板解析器,所以不能使用template这个配置项,需要使用render函数接收到的createElement函数去指定具体内容。
3.1.6vue.config.js配置文件
  1. 使用vue inspect > output.js可以查看到Vue脚手架的默认配置。
  2. 使用vue.config.js可以对脚手架进行个性化定制,详情见:https://cli.vuejs.org/zh
3.1.7Ref属性
  1. 被用来给元素或子组件注册引用信息(id的替代者)
  2. 应用在html标签上获取的是真实DOM元素,应用在组件标签上是组件实例对象(vc)
  3. 使用方式:
  1. 打标识:<h1 ref="xxx">.....</h1><School ref="xxx"></School>
  2. 获取:this.$refs.xxx
3.1.8props配置项
  1. 功能:让组件接收外部传过来的数据
  2. 传递数据:<Demo name="xxx"/>
  3. 接收数据:
  1. 第一种方式(只接收):props:['name']
  2. 第二种方式(限制类型):props:{name:String}
  1. 第三种方式(限制类型、限制必要性、指定默认值)
props:{
        	name:{
        	type:String, //类型
        	required:true, //必要性
        	default:'老王' //默认值
        	}
        }
备注:props是只读的,Vue底层会监测你对props的修改,如果进行了修改,就会发出警告,若业务需求确实需要修改,那么请复制props的内容到data中一份,然后去修改data中的数据。

使用过程:1.像组件传参

2.接收参数

3.修改参数:
如何修改传入参数?
直接掉props里的参数进行修改?不可直接修改props中的参数,就算修改也是无效的.
那该如何修改?
因为props优先级高于data,所以vue会先编译props的参数,并将其存储到vue实例对象中(可以在data中this.出传入的参数)。当两个参数名一样时会优先展示props的参数,并报错。

3.1.9mixin(混入)
  1. 功能:可以把多个组件共用的配置提取成一个混入对象
  2. 使用方式:
    第一步定义混合:

{
data(){…},
methods:{…}

}

第二步使用混入:
	全局混入:```Vue.mixin(xxx)```
	局部混入:```mixins:['xxx']

全局混入:

局部混入:

备注:
1.组件和混入对象有同名选项时,这些选项将以恰当方式进行“合并,在发生冲突时以组件优先。

var mixin = {
		data: function () {
			return {
  		message: 'hello',
            foo: 'abc'
   	}
  	}
}

	new Vue({
  	mixins: [mixin],
	  	data () {
    	return {
	      		message: 'goodbye',
            	bar: 'def'
	    	}
	    },
	  	created () {
	    	console.log(this.$data)
	    	// => { message: "goodbye", foo: "abc", bar: "def" }
	  	}
	})

2.同名生命周期钩子将合并为一个数组,因此都将调用。另外混入对象的钩子将在组件自身钩子之前调用

var mixin = {
  	created () {
    	console.log('混入对象的钩子被调用')
  	}
}

new Vue({
  	mixins: [mixin],
  	created () {
    	console.log('组件钩子被调用')
  	}
})

// => "混入对象的钩子被调用"
// => "组件钩子被调用"
3.1.10插件
  1. 功能:用于增强Vue
  2. 本质:包含install方法的一个对象,install的第一个参数是Vue,第二个以后的参数是插件使用者传递的数据。
  3. 定义插件:
    对象.install = function (Vue, options) {
    // 1. 添加全局过滤器
    Vue.filter(…)
    // 2. 添加全局指令
    Vue.directive(…)
    // 3. 配置全局混入(合)
    Vue.mixin(…)
    // 4. 添加实例方法
    Vue.prototype.elementUI步骤条二级_vue.js_33myProperty = xxxx
    }
  4. 使用插件:Vue.use()
3.1.11scoped样式

命令:
npm i less-loader@7 添加less类型

  1. 作用:让样式在局部生效,防止冲突。
  2. 写法:<style scoped>

3.2总结todolist_tes案例

1.组件化编译流程:
(1).拆分静态组件:组件要按照功能点拆分,命名不要与html元素冲突
(2).实现动态组件:考虑好数据存放位置数据是一个组件再用,还是一些组件再用:
1).一个组件在用:放在组件自身即可。
2).一些组件在用:放在他们共同的父组件上【官网称呼:状态提升】
(3).实现交互:从绑定事件开始。
2.props适用于:
(1).父组件  子组件 通信
(2).子组件  父组件 通讯 (要求父组件先给子组件一个函数)
3.使用v-model时要切记:v-model绑定的值不能时props传过来的值,因为props是不可修改的!
4.props传过来的若是对象类型的值,修改对象中的属性时vue不会报错,但不推举这样做。

3.3本地存储 自定义事件

3.3.1webStorage(js本地存储)

存储内容大小一般支持5MB左右(不同浏览器可能还不一样)
浏览器端通过Window.sessionStorage和Window.localStorage属性来实现本地存储机制
相关API
xxxStorage.setItem(‘key’,’value’)该方法接受一个键和值作为参数,会把键值对添加到存储中,如果键名存在,则更新其对应的值
xxxStorsge.getItem(‘key’)该方法接受一个键名作为参数,返回简明对应的值
xxxStorage.removeItem(‘key’)该方法接受一个简明作为参数,并把该键名从存储中删除
备注
sessionStorage存储的内容会随着浏览器窗口关闭而消失
LocalStrage存储的内容,需要手动清除才会消失
xxxStorage.getItem(xxx)如果xxx对应的value获取不到,那么getItem()的返回值是null
JSON.parse(null)的结果依然是null
localStorage:

<h2>localStorage</h2>
<button onclick="saveDate()">点我保存数据</button><br/>
<button onclick="readDate()">点我读数据</button><br/>
<button onclick="deleteDate()">点我删除数据</button><br/>
<button onclick="deleteAllDate()">点我清空数据</button><br/>

<script>
  let person = {name:"JOJO",age:20}

  function saveDate(){
    localStorage.setItem('msg','localStorage')
    localStorage.setItem('person',JSON.stringify(person))
  }
  function readDate(){
    console.log(localStorage.getItem('msg'))
    const person = localStorage.getItem('person')
    console.log(JSON.parse(person))
  }
  function deleteDate(){
    localStorage.removeItem('msg')
    localStorage.removeItem('person')
  }
  function deleteAllDate(){
    localStorage.clear()
  }

</script>

sessionStorage:

<h2>sessionStorage</h2>
<button onclick="saveDate()">点我保存数据</button><br/>
<button onclick="readDate()">点我读数据</button><br/>
<button onclick="deleteDate()">点我删除数据</button><br/>
<button onclick="deleteAllDate()">点我清空数据</button><br/>

<script>

  let person = {name:"JOJO",age:20}

  function saveDate(){
    sessionStorage.setItem('msg','sessionStorage')
    sessionStorage.setItem('person',JSON.stringify(person))
  }
  function readDate(){
    console.log(sessionStorage.getItem('msg'))
    const person = sessionStorage.getItem('person')
    console.log(JSON.parse(person))
  }
  function deleteDate(){
    sessionStorage.removeItem('msg')
    sessionStorage.removeItem('person')
  }
  function deleteAllDate(){
    sessionStorage.clear()
  }
</script>

3.4组件的自定义事件

  1. 一种组件间通信的方式,适用于:子组件父组件
  2. 使用场景:A是父组件,B是子组件,B想给A传数据,那么就要在A中给B绑定自定义事件(事件的回调)
  3. 绑定自定义事件:
  4. 第一种方式,在父组件中<demo @atguigu=”test”>或

Student组件

  1. 第二种方式:在父组件中:

当前组件

  1. 若是想让自己定义事件只能触发一次,可以使用once修饰符,或$once方法

4.触发自定义事件:this.$emit(‘atguigu’,数据)

5.解绑自定义事件:this.elementUI步骤条二级_Vue_34off([‘atguigu’,‘demo’]) //解绑多个自定义事件
this.$off() //解绑所有的自定义事件
6组件上也可以绑定原生DOM事件,需要使用native修饰符。

7.注意:通过this.elementUI步骤条二级_elementUI步骤条二级_35on(‘atguigu’,回调)绑定自定义事件时,回调要么配置在methods中,否则this指向会出问题

3.5全局事件总线(GlobalEventBus),消息订阅预发布(pubsub)

3.5.1全局事件总线(GlobalEventBus)

一种可以在任意组件间通信的方式,本质上就是一个对象,它必须满足一下条件。
1.一种组件通讯的方式,适用于任意组件间通信。
2.定义全局事件总线:

3.使用事件总线:
1.接收数据:A组件接收数据,则在A组件中给$bus绑定自定义事件,事件的回调留在A组件自身

2.提供数据:this.$bus.$emit(‘xxxx’,数据)

4.最好在beforeDestroy钩子中,用$off去解绑当前组件所用到的事件

3.5.2消息订阅发布(pubsub)【不常用】
  1. 一种组件间通信的方式,适用于任意组件间通信。
  2. 使用步骤:
  3. 安装pubsub:npm I pubsub-js
  4. 引入:import pubsub from ‘pubsub-js’
  5. 接收数据:A组件想接收数据,则在A组中订阅消息,订阅的回调留在A组件自身。
  6. 提供数据:pubsub.Publish(‘xxx’,数据)
  7. 最好在beforeDestroy钩子中,用pubsub.unsubscribe(pid)去取消订阅
    nextTick
  8. 语法:this.$nextTick(回调函数)
  9. 作用:在下一次DOM更新结束后执行其指定的回调
  10. 什么时候用:当改变数据后,要基于更新后的新DON进行某些操作时,要在nextTick所指定的回调函数中执行

3.6Vue封装的过度与动画

  1. 作用:在插入,更新或移除DOM元素时,在合适的时候给元素添加样式类名。
  2. 图示:
  3. elementUI步骤条二级_数据_36

  4. 写法:
  5. 准备好样式:
    元素进入的样式:
    1.v-enter:进入的起点
    2.v-enter-active:进入过程中
    3.v-enter-to:进入终点

元素离开的样式:
1.v-leave:离开的起点
2.v-leave-active:离开的过程中
3.v-leave-to:离开的终点

2.使用包裹要过度的元素,并配置name属性:

3.备注:若有多个元素需要过度,则需要使用:< transition -group>,且每个元素都要搞定key值

3.7Vue中的Ajax配置代理slot插槽

3.7.1Vue脚手架代理

方法一
在vue.config.js中添加如下配置:

说明:

  1. 优点:配置简单请求资源时直接发给前端(8080)即可
  2. 缺点:不能配置多个代理,不能灵活的控制请求是否走代理。
  3. 工作方式:若按照上述配置代理,当请求了前端不存在的资源时,那么该请求会转发给服务器(优先匹配前端资源)
    方法二
    编写vue.config.js配置具体代理规则:

说明;

  1. 优点:可以配置多个代理,且可以;灵活控制请求是否走代理。
  2. 缺点:配置略微繁琐,请求资源时必须加前缀。
    3.8插槽
    插槽:让父组件可以向子组件指定位置插入htnl结构,也是一种组件间通信的方式,
    适用于 父组件子组件
  3. 分类:默认插槽、具名插槽、作用域插槽
  4. 使用方式
  5. 默认插槽
  6. 具名插槽
  7. 作用域插槽
    1.理解:数据在组件的自身,但根据数据生成的结构需要组件的使用者来决定。(games数据在Category组件中,但使数据所遍历出来的结构由App组件决定)

第四章理解vuex

1.vuex是什么

1.概念:专门在vue中实现集中式状态(数据)管理的一个vue插件,对vue应用中多个组件的共享状态进行集中式的管理(读/写),也是一种组件间通信的方式,且适用于任意组件通信。

elementUI步骤条二级_Vue_37


elementUI步骤条二级_vue.js_38

2.什么时候使用vuex

1.多个组件依赖与同一状态。
2.来自不同组件的行为需要变更同一状态

3.工作原理图

elementUI步骤条二级_逆序_39

4.使用vuex

1.下载安装vuex npm I vuex
2.创建src/store/index.js该文件用于创建vuex中最为和核心的store
import Vue from ‘vue’
import Vuex from ‘vuex’ // 引入Vuex

Vue.use(Vuex) // 应用Vuex插件

const actions = {} // 准备actions——用于响应组件中的动作
const mutations = {} // 准备mutations——用于操作数据(state)
const state = {} // 准备state——用于存储数据

// 创建并暴露store
export default new Vuex.Store({
actions,
mutations,
state,
})
3.在src/main.js中创建vm时传入store配置项
import Vue from ‘vue’
import App from ‘./App.vue’
import store from ‘./store’ // 引入store

Vue.config.productionTip = false

new Vue({
el: ‘#app’,
render: h => h(App),
store, // 配置项添加store
beforeCreate() {
Vue.prototype.$bus = this
}
})

5.使用vuex编写

Vuex的基本使用

  1. 初始化数据state,配置actions、mutations,操作文件store.js
  2. 组件中读取vuex中的数据$store.state数据
  3. 组件中修改vuex中的数据elementUI步骤条二级_vue.js_40store.commit(‘mutation中的方法名’,数据)
    若没有网络请求或其他逻辑,组件中也可以越过actions,即不写dispatch,直接编写commit

于下张截图为一张

1.可以通过elementUI步骤条二级_数据_41store.commit()调用方法传入参数(但会跳过dispatch直接使用commit,无法获取或使用后台数据)

6.Getters配置项

  1. 概念:当state中的数据需要经过加工后在使用时,可以使用getters加工,相当于全局计算属性
  2. 在store.js中追加getters配置
  3. 组件中读取数据$store.getters.bigSunm

7.四个map方法的使用

  1. mapState:用于帮助映射state中的数据为计算属性
  2. mapGetters方法:用于帮助映射getters中的数据为计算属性
  3. mapActions方法:用于帮助生成与actions对话的方法,即包括$stor.dispatch(xxx)的函
  4. mapMutations方法:用于帮助生成与mutations对话的方法,即包含$store.commit(xxx)的函数

注意:mapAction与mapMutations使用时,若需要传递参数需要:在模板中绑定事件时传递好参数,否则参数是事件对象

8.模块化+命名空间

1.目的:让代码更好维护,让多种数据分类更加明确
2.修改store.js
为了解决不同模块命名冲突的问题,将不同模块的namespaced:true,之后在不同页面中引入getter actions mutations 时,需要加上所属的模块名
const countAbout = {
namespaced: true, // 开启命名空间
state: {x:1},
mutations: { … },
actions: { … },
getters: {
bigSum(state){ return state.sum * 10 }
}
}

const personAbout = {
namespaced: true, // 开启命名空间
state: { … },
mutations: { … },
actions: { … }
}

const store = new Vuex.Store({
modules: {
countAbout,
personAbout
}
})
3.开启命名空间后,组件中读取state数据
// 方式一:自己直接读取
this.elementUI步骤条二级_逆序_42store.getters[‘personAbout/firstPersonName’]
//方式二:借助mapGetters读取:
…mapGetters(‘countAbout’,[‘bigSum’])
5开启命名空间后,组件中调用dispatch
//方式一:自己直接dispatch
this.elementUI步骤条二级_Vue_43store.commit(‘personAbout/ADD_PERSON’,person)
//方式二:借助mapMutations:
…mapMutations(‘countAbout’,{increment:‘JIA’,decrement:‘JIAN’}),

第五章路由器

5.1相关理解

5.1.1vue-router理解

Vue的一个插件库,专门用来实现SPA应用

5.1.2对SPA应用的理解

1.单页面web应用(single page web application , SPA)。
2.整个应用中有一个完整的页面。
3.点击页面中的导航链接不会刷新页面,只会做页面的局部更新。
4.数据需要通过Ajax请求获取

5.1.3路由的理解

1.什么是路由?
(1).一个路由就是一组映射关系(key-value)
(2).key为路径,value可能是function或componen
2.路由分类
(1).后端路由
<1>.理解:value是function用于处理客户端提交的请求
<2>.工作过程:服务器接收到一个请求时,根据亲贵路径找到匹配的函数开处理请求,返回响应数据
(2).前端路由
<1>.理解:value是component,用于展示页面内容
<2>.工作过程:当浏览器的路径改变时,对应的组件就会显示

5.2路由的基本使用

1.安装vue-router,命令npm I vue-router
2.应用插件Vue.use(VueRouter)
3.创建src/router/index.js文件,编写router配置项

import VueRouter from ‘vue-router’ // 引入VueRouter
import About from ‘…/components/About’ // 路由组件
import Home from ‘…/components/Home’ // 路由组件

// 创建router实例对象,去管理一组一组的路由规则
const router = new VueRouter({
routes:[
{
path:‘/about’,
component:About
},
{
path:‘/home’,
component:Home
}
]
})

//暴露router
export default router
4.实现切换
浏览器会被替换为a标签
Active-class
About
5.指定展示位</ router-view >.

5.3几个注意事项

1.路由组件通常存放在pages文件夹,一般组件通常放在components文件夹。
2.通过切换,“隐藏”了的路由组件,默认是被销毁掉的,需要的时候再去挂载
3.每个组件都有自己的elementUI步骤条二级_逆序_44router属性获取到

// 该文件专门用于创建整个应用的路由器
import VueRouter from "vue-router";
import Home from '../pages/Home'
import About from '../pages/About'

export default new VueRouter({
    routes:[
        {
            path:'/about',
            component:About
        },
        {
            path:'/home',
            component:Home
        }
    ]
})

<template>
    <div class="col-xs-offset-2 col-xs-8">
        <div class="page-header"><h2>Vue Router Demo</h2></div>
    </div>
</template>

<script>
    export default {
        name:'Banner'
    }
</script>

<template>
  <div>
    <div class="row">
      <Banner/>
    </div>
    <div class="row">
      <div class="col-xs-2 col-xs-offset-2">
        <div class="list-group">
<!-- 原始html中我们使用a标签实现页面跳转 -->
      <!-- <a class="list-group-item active" href="./about.html">About</a>
       <a class="list-group-item" href="./home.html">Home</a> -->
      <!-- Vue中借助router-link标签实现路由的切换 -->
      <router-link class="list-group-item" active-class="active" to="/about">
        About</router-link>
      <router-link class="list-group-item" active-class="active" to="/home">
        Home</router-link>
			</div>
		</div>
		<div class="col-xs-6">
			<div class="panel">
				<div class="panel-body">
					<!-- 指定组件的呈现位置 -->
					<router-view></router-view>
				</div>
			</div>
		</div>
	</div>
</div>

5.4多级路由

1.配置路由规则,使用children配置项

routes:[
	{
		path:'/about',
		component:About,
	},
	{
		path:'/home',
		component:Home,
		children:[ 					// 通过children配置子级路由
			{
				path:'news', 		// 此处一定不要带斜杠,写成 /news
				component:News
			},
			{
				path:'message',	// 此处一定不要写成 /message
				component:Message
			}
		]
	}
]

2.跳转(to内要写完整路径)
News

5.5路由的query参数

1.传递参数

//跳转并携带query参数,to的字符串写法 -
<router-link :to="`/home/message/detail?id=${m.id}&title=${m.title}`">跳转</router-link>
<router-link 
	:to="{
		path:'/home/message/detail',
		query:{
		   id: m.id,
           title: m.title
		}
	}"

2.接收参数
$route.query.id
$route.query.title

5.6命名路由

1.作用:可以简化路由的跳转
2.如何使用
1.给路由命名

{
path:‘/demo’,
component:Demo,
children:[
{
path:‘test’,
component:Test,
children:[
{
name:‘hello’ // 给路由命名
path:‘welcome’,
component:Hello,
}
]
}
]
}
2.简化跳转

<!--简化前,需要写完整的路径 -->
<router-link to="/demo/test/welcome">跳转</router-link>

<!--简化后,直接通过名字跳转 -->
<router-link :to="{name:'hello'}">跳转</router-link>

<!--简化写法配合传递参数 -->
<router-link 
	:to="{
		name:'hello',
		query:{
		    id:666,
        title:'你好'
		}
	}"
>跳转</router-link>

5.7路由的params参数

1.配置路由,声明接收params参数

{
	path:'/home',
	component:Home,
	children:[
		{
			path:'news',
			component:News
		},
		{
			component:Message,
			children:[
				{
					name:'xiangqing',
					path:'detail/:id/:title', // 🔴使用占位符声明接收params参数
					component:Detail
				}
			]
		}
	]
}

2.传递参数
特别注意:路由携带params参数时,若使用to的对象写法,则不能使用path配置项,必须使用name配置!

<!-- 跳转并携带params参数,to的字符串写法 -->
<router-link :to="/home/message/detail/666/你好">跳转</router-link>
				
<!-- 跳转并携带params参数,to的对象写法 -->

```java
<router-link 
	:to="{
		name:'xiangqing',
		params:{
		   id:666,
       title:'你好'
		}
	}"
	>跳转</router-link>

3.接收参数

跳转

<router-link 
	:to="{
		name:'xiangqing',
		params:{
		   id:666,
       title:'你好'
		}
	}"

5.8路由props配置

Props作用:让路由组件更方便的收到参数

{
	name:'xiangqing',
	path:'detail/:id',
	component:Detail,

	//第一种写法:props值为对象,该对象中所有的key-value的组合最终都会通过props传给Detail组件
	// props:{a:900}

	//第二种写法:props值为布尔值,为true时,则把路由收到的所有params参数通过props传给Detail组件
	// props:true
	
	//第三种写法:props值为函数,该函数返回的对象中每一组key-value都会通过props传给Detail组件
	props($route){
		return {
			id: $route.query.id,
			title: $route.query.title
		}
	}
}

5.9路由跳转的replace方法

1.作用:控制路由跳转时操作浏览器历史记录的模式
2.浏览器的历史记录有两种写入方式:push和replace
Push是追加历史记录
Replace是替换当前记录,路由跳转时候默认为push方式
3.开启replace模式

<router-link :replace=”true” …>News</router-link>
  简写:<router-link replace …>News</router-link>

总结:浏览记录本质是一个栈,默认push,点开新页面就会在栈顶追加一个地址,后退,栈顶指针向下移动,改为replace就是不追加,而将栈顶地址替换

<template>
  <div>
    <h2>Home组件内容</h2>
    <div>
      <ul class="nav nav-tabs">
        <li>
          <router-link replace class="list-group-item" active-class="active" 
                       to="/home/news">News</router-link>
    		</li>
        <li>
          <router-link replace class="list-group-item" active-class="active" 
                       to="/home/message">Message</router-link>
    		</li>
    </ul>
    <router-view></router-view>
    </div>
  </div>
</template>

<script>
  export default {
    name:'Home'
  }
</script>

5.10编程式路由导航

作用:不借助实现路由跳转,让路径跳转更加灵活

this.$router.push({})     内传对象与<router-link>中的to相同
this.$router.replace({})   
this.$router.forward()    前进
this.$router.back()       后退
this.$router.go(n)        可前进也可后退,n为正数前进n,为负数后退
this.$router.push({
	name:'xiangqing',
  params:{
    id:xxx,
    title:xxx
  }
})

this.$router.replace({
	name:'xiangqing',
  params:{
    id:xxx,
    title:xxx
  }
})

5.11缓存路由组件

作用:让不展示的路由组件保持挂载,不被销毁

<keep-alive include=”News”><router-view></roter-view></keep-alive>
<keep-alive include=”[‘News’,’Message’]”><router-view></roter-view></keep-alive>
// 缓存一个路由组件
<keep-alive include="News"> // include中写想要缓存的组件名,不写表示全部缓存
    <router-view></router-view>
</keep-alive>

// 缓存多个路由组件
<keep-alive :include="['News','Message']"> 
    <router-view></router-view>
</keep-alive>

5.12Vue Router activated deactivated 路由守卫

Activated和deactivated是路由组件所独有的两个钩子,用于捕获路由组件的激活状态
具体使用:

  1. activated路由组件被激活时触发
  2. deactivated路由组件失活时触发
<template>
    <ul>
        <li :style="{opacity}">欢迎学习vue</li>
        <li>news001 <input type="text"></li>
        <li>news002 <input type="text"></li>
        <li>news003 <input type="text"></li>
    </ul>
</template>

<script>
    export default {
        name:'News',
        data(){
           return{
                opacity:1
           }
        },
        activated(){
console.log('News组件被激活了')
       this.timer = setInterval(() => {
this.opacity -= 0.01
if(this.opacity <= 0) this.opacity = 1
            },16)
       },
        deactivated(){
            console.log('News组件失活了')
            clearInterval(this.timer)
        }
    }
</script>

5.13路由守卫

作用:对路由进行权限控制
分类:全局守卫、独享守卫、组件内守卫

  1. 全局守卫
    Meat路由源信息
// 全局前置守卫:初始化时、每次路由切换前执行
router.beforeEach((to,from,next) => {
	console.log('beforeEach',to,from)
	if(to.meta.isAuth){ // 判断当前路由是否需要进行权限控制
		if(localStorage.getItem('school') === 'atguigu'){ // 权限控制的具体规则
			next()	// 放行
		}else{
			alert('暂无权限查看')
		}
	}else{
		next()	// 放行
	}
})

// 全局后置守卫:初始化时、每次路由切换后执行
router.afterEach((to,from) => {
	console.log('afterEach',to,from)
	if(to.meta.title){ 
		document.title = to.meta.title //修改网页的title
	}else{
		document.title = 'vue_test'
	}
})

2.	独享守卫

beforeEnter(to,from,next){
	console.log('beforeEnter',to,from)
    if(localStorage.getItem('school') === 'atguigu'){
        next()
    }else{
        alert('暂无权限查看')
    }
}

3.	组件内守卫

beforeEnter(to,from,next){
	console.log('beforeEnter',to,from)
    if(localStorage.getItem('school') === 'atguigu'){
        next()
    }else{
        alert('暂无权限查看')
    }
}
示例1:全局守卫
//该文件专门用于创建整个应用的路由器
import VueRouter from "vue-router";
//引入组件
import Home from '../pages/Home'
import About from '../pages/About'
import News from '../pages/News'
import Message from '../pages/Message'
import Detail from '../pages/Detail'


//创建一个路由器
const router = new VueRouter({
    routes:[
        {
            name:'guanyv',
            path:'/about',
            component:About,
            meta:{title:'关于'}
        },
        {
            name:'zhuye',
            path:'/home',
            component:Home,
            meta:{title:'主页'},
            children:[
                {
                    name:'xinwen',
                    path:'news',
                    component:News,
                    meta:{isAuth:true,title:'新闻'}
                },
                {
                    name:'xiaoxi',
                    path:'message',
                    component:Message,
                    meta:{isAuth:true,title:'消息'},
                    children:[
                        {
                            name:'xiangqing',
                            path:'detail',
                            component:Detail,
                            meta:{isAuth:true,title:'详情'},
                            props($route){
                                return {
                                    id:$route.query.id,
                                    title:$route.query.title,
                                }
														}
                        }
                    ]
                }
            ]
        }
    ]
})

// 🔴全局前置路由守卫————初始化的时候、每次路由切换之前被调用
router.beforeEach((to,from,next) => {
    console.log('前置路由守卫',to,from)
    if(to.meta.isAuth){
        if(localStorage.getItem('school')==='atguigu'){
            next()
        }else{
            alert('学校名不对,无权限查看!')
        }
    }else{
        next()
    }
})

// 🔴全局后置路由守卫————初始化的时候被调用、每次路由切换之后被调用
router.afterEach((to,from)=>{
	console.log('后置路由守卫',to,from)
	document.title = to.meta.title || '硅谷系统'
})

// 导出路由器
export default router
示例2:独享守卫
//该文件专门用于创建整个应用的路由器
import VueRouter from "vue-router";
//引入组件
import Home from '../pages/Home'
import About from '../pages/About'
import News from '../pages/News'
import Message from '../pages/Message'
import Detail from '../pages/Detail'


//创建一个路由器
const router = new VueRouter({
    routes:[
        {
            name:'guanyv',
            path:'/about',
            component:About,
            meta:{title:'关于'}
        },
        {
            name:'zhuye',
            path:'/home',
            component:Home,
            meta:{title:'主页'},
            children:[
                {
                    name:'xinwen',
                    path:'news',
                    component:News,
                    meta:{title:'新闻'},
                    // 🔴独享守卫,特定路由切换之后被调用
                    beforeEnter(to,from,next){
                        console.log('独享路由守卫',to,from)
                        if(localStorage.getItem('school') === 'atguigu'){
                            next()
                        }else{
                            alert('暂无权限查看')
                        }
                    }
                },
                {
                    name:'xiaoxi',
                    path:'message',
                    component:Message,
                    meta:{title:'消息'},
                    children:[
                        {
                            name:'xiangqing',
                            path:'detail',
                            component:Detail,
                            meta:{title:'详情'},
                            props($route){
                                return {
                                    id:$route.query.id,
                                    title:$route.query.title,
                                }
                            }
                        }
                    ]
                }
            ]
        }
    ]
})

//全局后置路由守卫————初始化的时候被调用、每次路由切换之后被调用
router.afterEach((to,from)=>{
	console.log('后置路由守卫',to,from)
	document.title = to.meta.title || '硅谷系统'
})

//导出路由器
export default router

示例3:组件内守卫

<template>
    <h2>我是About组件的内容</h2>
</template>

<script>
    export default {
        name:'About',
        // 通过路由规则,离开该组件时被调用
        beforeRouteEnter (to, from, next) {
            console.log('About--beforeRouteEnter',to,from)
            if(localStorage.getItem('school')==='atguigu'){
                next()
            }else{
                alert('学校名不对,无权限查看!')
            }
        },
        // 通过路由规则,离开该组件时被调用
        beforeRouteLeave (to, from, next) {
            console.log('About--beforeRouteLeave',to,from)
            next()
        }
    }
</script>

5.14路由的两种工作模式

1.对于一个url来说,什么是hash值? 及其后面的所有都是hash值
2.hash值不会包含在http请求中。即:hash值不会带给服务器
3.hash模式
1.地址中永远带着#号,不美观
2.若以后将地址通过第三方手机app分享,若app校验严格,则地址会被标记为不合法
3.兼容性较好
4.history模式
1.地址干净,美观
2.兼容性和hash模式相比略差
3.应用部署上线时需要后端人员支持,解决刷新页面服务端404的问题

const router =  new VueRouter({
	mode:'history',
	routes:[...]
})

export default router

解决项目打包用于区分是前端路由还是后端路由的插件(打包后使用)
nginx connect-history-api-fallback

第六章vue UI组件库

6.1 移动端常用 UI 组件库

  1. Vant https://youzan.github.io/vant
  2. Cube UI https://didi.github.io/cube-ui
  3. Mint UI http://mint-ui.github.io

6.2 PC 端常用 UI 组件库

  1. Element UI https://element.eleme.cn
  2. IView UI https://www.iviewui.co

6.3element-ui基本使用

1.安装element-ui:npm I element-ui -S(s可以不加安装默认为最新版本)
2.main.js编写代码

import Vue from 'vue'
import App from './App.vue'
import ElementUI from 'element-ui';							// 引入ElementUI组件库
import 'element-ui/lib/theme-chalk/index.css';	// 引入ElementUI全部样式

Vue.config.productionTip = false

Vue.use(ElementUI)	// 使用ElementUI

new Vue({
    el:"#app",
    render: h => h(App),
})

6.4element-ui按需引入

1.安装babel-plugin-component npm I babel-plugincomponent -D
2.修改babel-config-js

module.exports = {
  presets: [
    '@vue/cli-plugin-babel/preset',
    ["@babel/preset-env", { "modules": false }]
  ],
  plugins: [
    [
      "component",
      {        
        "libraryName": "element-ui",
        "styleLibraryName": "theme-chalk"
      }
    ]
  ]
}

3.main.js

import Vue from 'vue'
import App from './App.vue'
import { Button,Row } from 'element-ui'	// 按需引入

Vue.config.productionTip = false

Vue.component(Button.name, Button);
Vue.component(Row.name, Row);
/* 或写为
 * Vue.use(Button)
 * Vue.use(Row)
 */

new Vue({
    el:"#app",
    render: h => h(App),
})``