Vue2

  • 什么是vue

用于构建用户界面的渐进式js框架

​ 渐进式:vue可以自底向上逐层的应用(简单应用只需要一个轻量小巧的核心库,面对复杂应用可以引入各式各样的Vue插件)

  • Vue的特点

    1. 采用组件化的模式,提高代码的复用率、且更好维护(生成了一个全新的文件.vue,包括了每个部件的js,html,css,使得每个部分有更好的封装)
    2. 申明式编码,让编码人员无需直接操作DOM,提高开发效率(区别于一般的命令式编码)指令封装到了各个命令之中
    3. 使用虚拟DOM,遇到改变值的时候比较快捷
  • 学习vue之前需要掌握的js知识

    1. ES6语法规范
    2. ES6模块化
    3. 包管理器
    4. 原型、原型链
    5. 数组常用方法
    6. axios
    7. promise
  • 官方文档

    1. 学习->教程

      学习->API(相当于字典,编码时不会时进行查看)

      学习->风格指南 可以写出更加好的结构和代码

      学习->示例

      学习->cookbook(一些小技巧)

    2. 生态系统->工具

         	  ->核心插件
      
    3. 资源列表->Awesome Vue(Vue的大量周边库)

      ​ ->浏览和Vue相关的包

一、Vue2

1、vue基础

(1)安装vue

<1>使用

引入一段js文件

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EebNnGxg-1650258889023)(C:\Users\HP\AppData\Roaming\Typora\typora-user-images\image-20220312204447630.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zgwkaloQ-1650258889027)(C:\Users\HP\AppData\Roaming\Typora\typora-user-images\image-20220312204457374.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0Euu1fsO-1650258889029)(C:\Users\HP\AppData\Roaming\Typora\typora-user-images\image-20220312204431373.png)]

安装开发工具:略

<2>全局配置

Vue.config 是一个对象包含Vue的全局配置

最好在设置完全局配置之后再进行Vue对象的创建

<3>Vue对象的创建

Vue是一个构造函数

使用new的方法创建函数对象

const x =new Vue({配置对象})

十分重要必须使用这个之后的一切都建立在这个之上

配置对象:

  1. el

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-En761kau-1650258889030)(C:\Users\HP\AppData\Roaming\Typora\typora-user-images\image-20220313103115790.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ke0J2daC-1650258889031)(C:\Users\HP\AppData\Roaming\Typora\typora-user-images\image-20220313103227642.png)]

注意:id~#

​ class~.

与css之中的选择器对应方法一样

  1. data

    使得数据可变

    插入语法

    存储数据,供指定的容器使用,值暂时可以写为一个对象,之后要写为函数

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6LCIQOBv-1650258889032)(C:\Users\HP\AppData\Roaming\Typora\typora-user-images\image-20220313104205000.png)]

  • 加入Vue之后,整体的容器代码依然是符合HTML规范的

  • root容器之中的代码被称为Vue模板

知识点补充:按住shift在刷新是强制刷新,有些时候需要使用

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-66Htlue6-1650258889033)(C:\Users\HP\AppData\Roaming\Typora\typora-user-images\image-20220313105547934.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fpXPW2mZ-1650258889035)(C:\Users\HP\AppData\Roaming\Typora\typora-user-images\image-20220313105606242.png)]

一个实例最多只能对应一个容器

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-THTezL1g-1650258889036)(C:\Users\HP\AppData\Roaming\Typora\typora-user-images\image-20220313110028655.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-aFsCoE2Y-1650258889037)(C:\Users\HP\AppData\Roaming\Typora\typora-user-images\image-20220313110342654.png)]

第一个实例已经接管了容器

第二个执行了,但是没有用

总结:

  1. 容器与实例的关系只能是一对一

  2. 双花括号里可以写的东西:必须是js表达式

    补充:js表达式与代码(语句)的区别

    表达式:一个表达式会产生一个值,可以放在任何需要值的地方

    ​ eg:变量a,a+b,demo(1),x=y?‘a’:‘b’

    js代码(语句)

    控制流程的走向和走几次

    ​ eg:if(){},for(){}

<4>Vue开发者工具

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xfotbr5p-1650258889038)(C:\Users\HP\AppData\Roaming\Typora\typora-user-images\image-20220313150948725.png)]

(2)模板语法

<1>插值语法

上面所用的在某个地方插入可变的对象的语法

<2>指令语法

使得网页的跳转地址是可变的

  1. v-bind

    作用:给标签之中的属性绑定对应的值

     eg.href与url进行绑定,使得url被当做一个js表达式进行运算,从而使得<a>标签指向的网页进行变化
    

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-pDQSpsGc-1650258889044)(C:\Users\HP\AppData\Roaming\Typora\typora-user-images\image-20220313154051885.png)]

注:

  • v-bind:可以简写为“:”
  • 每个标签绑定一个对应的属性值
<3>二者的区别
  1. 插值语法:用于解析标签体内容
  2. 指令语法用于解析标签(包括:标签属性、标签体内容、绑定事件……)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wPXRWYlq-1650258889048)(C:\Users\HP\AppData\Roaming\Typora\typora-user-images\image-20220313155836442.png)]

如图所示可以实现分级调用

<4>数据绑定
  1. 单向数据绑定:v-bind

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-F5XZr2VZ-1650258889049)(C:\Users\HP\AppData\Roaming\Typora\typora-user-images\image-20220314163517727.png)]

改变data的值,前台会变

但是改变前台的值,data不会变

  1. 双向绑定:v-model

    改变前台,data数据同时改变

    改变data之中的值,前台的数据也会改变

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-az3EUUwq-1650258889050)(C:\Users\HP\AppData\Roaming\Typora\typora-user-images\image-20220314164954582.png)]

注意:

  • 不是所有元素类型都支持v-model

v-model只能用于表单类元素,或者叫做输入类元素之中(有value值的元素之中)

  • v-model:value="……"可以简写为v-model=“……”
  • 如果绑定的checkbox v-model如果是一个bool值就可以决定选中的状态

(3)el与data的两种写法

<1>el

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gLeDpHjp-1650258889051)(C:\Users\HP\AppData\Roaming\Typora\typora-user-images\image-20220314171427339.png)]

使用图中的函数可以代替el将实例与容器进行绑定

mount---------挂载

<2>data

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZqEkxugF-1650258889053)(C:\Users\HP\AppData\Roaming\Typora\typora-user-images\image-20220314172230589.png)]

注意:

  • 在学习到组件之后一定要使用函数式
  • 这个函数只能是普通函数不可以是箭头函数(扩展:由Vue管理道的函数一定不可以是箭头函数一旦使用了Vue函数,this就是不是Vue实例而是windows了)

(4)MVVM模型

Vue在一定的程度上参考了这个模型

M:模型 对应data之中所写的数据

V:视图 模板

VM:视图模型 Vue实例对象

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8BhV8g91-1650258889054)(C:\Users\HP\AppData\Roaming\Typora\typora-user-images\image-20220314202547774.png)]

注:

  1. data之中所有的属性都出现在了vm身上
  2. vm身上所有的属性都可以在Vue模板之中使用

(5)复习Object.defineProperty语法

Object.defineProperty(对象,属性,{属性值与各种函数})

这个函数用于个指定对象添加指定函数

枚举:遍历

不可枚举:不可以参加枚举

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-awxBXMg3-1650258889055)(C:\Users\HP\AppData\Roaming\Typora\typora-user-images\image-20220314212115156.png)]

直接用如图方法给对象添加上一个新的属性,这个属性是不可枚举型且不可修改且不可以删除的

只有如下图所示才可以把这个新的属性变为可枚举型、可删除,可修改的

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4uSHPxXO-1650258889055)(C:\Users\HP\AppData\Roaming\Typora\typora-user-images\image-20220314213133552.png)]

configurable--------------------可配置的

一个高级用法

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BB98dfg4-1650258889056)(C:\Users\HP\AppData\Roaming\Typora\typora-user-images\image-20220314214952520.png)]

效果如下:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RMClSCHb-1650258889057)(C:\Users\HP\AppData\Roaming\Typora\typora-user-images\image-20220314215030199.png)]

每次读取就执行一次函数

可以略去函数名简写为:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AKNGicQ1-1650258889058)(C:\Users\HP\AppData\Roaming\Typora\typora-user-images\image-20220314215251494.png)]

另一个重要函数:setter

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Jtl5G2YI-1650258889058)(C:\Users\HP\AppData\Roaming\Typora\typora-user-images\image-20220315201116093.png)]

(6)数据代理

通过一个对象代理另一个对象中属性的操作(读\写)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tJaQa0AX-1650258889060)(C:\Users\HP\AppData\Roaming\Typora\typora-user-images\image-20220315202605484.png)]

如此通过obj2也可以操作obj中的x

(7)Vue之中的数据代理

所以Vme之中的修改读取数据,就是按照(6)之中的方法对data之中的每一个属性都进行了代理,可以更加方便的操作data之中的数据

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Kftl15fJ-1650258889060)(C:\Users\HP\AppData\Roaming\Typora\typora-user-images\image-20220315204504494.png)]

注意:

  • data被传到_data ,可以使用 对象名._data.属性名 来调用属性

(8)事件处理

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hB5wIe2a-1650258889061)(C:\Users\HP\AppData\Roaming\Typora\typora-user-images\image-20220315215105047.png)]

alert-------------------------------警告,提示、

v-on:click的简写为@click

<button @click="showInfo">点我提示信息</button>

(注:如果函数功能简单可以直接写在showinfo的位置)

效果如下图所示

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AYvidNs3-1650258889062)(C:\Users\HP\AppData\Roaming\Typora\typora-user-images\image-20220315215200485.png)]

点击事件时进行传参的方法

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7e9Q48X7-1650258889063)(C:\Users\HP\AppData\Roaming\Typora\typora-user-images\image-20220315220437987.png)]

(9)事件修饰符

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nzGAs6pZ-1650258889064)(C:\Users\HP\AppData\Roaming\Typora\typora-user-images\image-20220316213509090.png)]

prevent就是事件修饰符(比如上图就不会进行跳转)

Vue中的常见事件修饰符:

  1. prevent:阻止默认事件
  2. stop:阻止事件冒泡
  3. once:事件只触发一次
  4. capture:使用事件的捕获模式(在捕获阶段就执行函数)
  5. self:只有event.target是当前操作的元素时才出发事件(event.target指向点击事件所点的按钮),所以一定程度上可以阻止冒泡
  6. passive:事件的默认行为立即执行,无需等待事件的回调执行完毕(优化用,移动端常用)

注:

  • 当接收到一个事件时分为事件捕获和事件冒泡两个阶段,先进行事件捕获,再进行事件冒泡

    事件捕获有父级到子级,事件冒泡反之

  • 事件冒泡,即当一个元素接收到事件的时候 会把他接收到的事件传给自己的父级,一直到window

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NKdtbtDD-1650258889065)(C:\Users\HP\AppData\Roaming\Typora\typora-user-images\image-20220316214541997.png)]

​ 如上图所示由于事件冒泡,点击事件会从button传到div所以函数会执行两次

  • 事件的执行顺序,默认执行绑定的函数,得到回调之后才执行默认事件(有些时候绑定函数太难执行,会造成卡顿就是因为这个)
  • 修饰符也是可以连用的 @click.prevent.stop(先阻止默认事件,再阻止冒泡,注意顺序)

(10)键盘事件

  1. keydown:按下去就触发

  2. keyup:按下去,放开之后才触发(常用)

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Ad9keYyk-1650258889065)(C:\Users\HP\AppData\Roaming\Typora\typora-user-images\image-20220316223003956.png)]

enter就是回车键的别名,即当按下回车键时就调用函数

  1. 常见别名:

    • 回车------------enter

    • 删除------------delete(包括退格和删除)

    • 退出------------esc

    • 空格------------space

    • 换行------------tab(tab键不适合用keyup因为它自己就有转开焦点的作用,所以如果使用keyup在生效之前就已经切换走了)

    • 上----------------up

    • 下----------------down

    • 左--------------left

    • 右--------------right

  2. 想要用没有别名的按键

​ 则可以使用event.key得到对应的按键的名称,然后将单词改为小写再进行按键的绑定

( 注:有些按键的名称是由两个单词组成的驼峰型,绑定时要改为“单词1-单词2”)

  1. 系统修饰键(用法特殊):ctrl、alt、shift、meta(也叫win键)
    • 配合keyup使用:按下修饰键的同时,再按下其他键,随后释放其他键,事件才会被触发(可以使用keyup.ctrl.y 指定只有按住y再松开才可以,其他的都不行)
    • 配合keydown使用:正常触发事件
  2. 也可以使用keyCode去指定具体的按键(将要废除不推荐)
  3. Vue.config.keyCodes.自定义键名=键码,可以去定制按键别名(其实也不推荐)

(11)计算属性与监视

插值语法也可以插入methods里的函数

补充:

  1. {{函数名}}---------------------------把函数的内容直接插入
  2. {{函数名()}}--------------------------插入函数的返回值

属性:data里的数据

计算属性:通过属性计算出一个全新的属性,写在computed里,配置方式类似data

​ 即所需的属性不存在,需要对已有的属性进行计算得出

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-h7KRZrq4-1650258889066)(C:\Users\HP\AppData\Roaming\Typora\typora-user-images\image-20220317205739718.png)]

缓存:

执行过一次之后,会有一个缓存,之后的相同调用都是直接提取缓存而不是重新调用函数4

get的执行时机:

  1. 初次读取Fullname时
  2. 所依赖的数据发生了改变的时候

注意

  • 调用时直接像调用data之中的属性一样调用即可“{{Fullname}}”不是“{{Fullname.get()}}”

  • 有get就有与之对应的set(非必要可以不用添加,更多的情况是只读取出来显示,而不必修改),set在修改值的时候被调用,在这里对所需的属性进行改变才可以改变界面上的值

<1>计算属性的简写

当只读不改的时候才可以使用这个简写的方式

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MTd5Y2CI-1650258889067)(C:\Users\HP\AppData\Roaming\Typora\typora-user-images\image-20220318200944642.png)]

相当于直接使用这个函数做get

注意:

  1. 在模板之中可以直接调用vue对象之中的数据,也只可以找到vue对象上的,不可以找到别的地方的函数(比如:window上的就找不到)
  2. 计算属性可以使用其他计算属性进行计算
<2>监视属性

watch属性

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-oygCHlHk-1650258889069)(C:\Users\HP\AppData\Roaming\Typora\typora-user-images\image-20220318202956999.png)]

当所监视的属性值发生更改的时候,执行这个函数,并且传入修改前和修改后的两个值

watch的配置项:

  1. immediate:默认为false改为true之后,打开页面时就会默认执行一次handler

    写法:

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2mL6NV1B-1650258889070)(C:\Users\HP\AppData\Roaming\Typora\typora-user-images\image-20220318203524934.png)]

  2. 深度监测:

    属性deep默认为false如果改为true就可以监视多级结构之中的所有属性的变化

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bavdRtHN-1650258889071)(C:\Users\HP\AppData\Roaming\Typora\typora-user-images\image-20220318212819054.png)]

watch的简写形式:

当没有使用配置项的时候才可以使用简写形式

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WoS8Rjzc-1650258889072)(C:\Users\HP\AppData\Roaming\Typora\typora-user-images\image-20220318213714872.png)]

注:

  • computed之中的计算出的属性也可以进行监测

  • 第二种监视的方式(比较灵活):
    在对象创建完毕之后写在对象之外

    Vue对象.$watch('要监视的属性名',{
    				//下面这部分代码和之前的写法一样
                   immediate:true,
                    handler(newValue,oldValue){
                        console.log(newValue,oldValue)
                    }
    })
    
  • 监视属性必须存在才可以监视(但是不会报错)

  • 监视多级属性中某个属性的变化:
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xLS3aU1t-1650258889072)(C:\Users\HP\AppData\Roaming\Typora\typora-user-images\image-20220318212144125.png)]

注意这里必须加‘’还原默认写法

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jRd3vZCq-1650258889073)(C:\Users\HP\AppData\Roaming\Typora\typora-user-images\image-20220318212620591.png)]

  • Vue自身可以检测到每一层的改变,但是watch只有配置了deep才可以

  • watch可以使用定时器来完成异步任务,computed不行

  • 所有被Vue管理的函数最好写成普通函数,使得函数的this指向Vue实例

  • 所有不被Vue所管理的函数(定时器函数,ajax函数,promise回调函数)最好写成箭头函数

    这样这些函数的指向才是Vue对象

(12)绑定样式

<1>绑定class样式
  • 字符串写法,适用于:样式的类名不确定,需要动态指定

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Qe4WgYaM-1650258889074)(C:\Users\HP\AppData\Roaming\Typora\typora-user-images\image-20220319101016690.png)]

​ 实现三种心情随机生成

  • 数组写法,适用于样式的个数不确定,名字也不确定

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9Z2am2eq-1650258889075)(C:\Users\HP\AppData\Roaming\Typora\typora-user-images\image-20220319102254087.png)]

就可以用

vm.arr.shift()移除数组第一个样式

vm.arr.push(‘样式名’)添加一个样式

  • 绑定class的样式写法:适用于绑定样式的个数确定,名字也确定,但是要动态觉定用不用

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZqvnlNLC-1650258889076)(C:\Users\HP\AppData\Roaming\Typora\typora-user-images\image-20220319103306214.png)]

由true和false来确定是否使用此样式

  • 绑定style的写法:

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LWg0zGxU-1650258889105)(C:\Users\HP\AppData\Roaming\Typora\typora-user-images\image-20220320211134606.png)]

    注:fontsize为data里设置的值

    或者

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-iD9kRslJ-1650258889107)(C:\Users\HP\AppData\Roaming\Typora\typora-user-images\image-20220320211443981.png)]

    同时想要使用多个样式,可以直接写数组

(13)条件渲染

  1. v-show
v-show="True或者False"

当为真的时候展示,当为假的时候隐藏,也可为data之中的属性,也可以是一个结果为bool值的函数,由此来进行动态的展示与消失

注:结构依然存在,只是页面上不显示

  1. v-if

    用法与v-show相同

    注:页面上不存在,且结构也不存在了

    • 如果变化频率较高,最好使用v-show
  2. v-else-if

    和v-if配合使,一组一组的进行判断,与正常语法之中的相同

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nnD8UD6B-1650258889110)(C:\Users\HP\AppData\Roaming\Typora\typora-user-images\image-20220320213424487.png)]

  3. v-else

    与正常的else相同(后面不用跟条件)

  • 注意:这几个条件之间不能间隔开(之间插入了不带这种类型标签的语句)
  • v-show也不可以与后面的这些进行匹配
  • 当有多个标签都需要使用相同的判断条件时,可以使用template标签来对这些标签进行包裹,然后 直接绑定template,区别于使用div标签进行包裹,可以不破坏HTML 的结构,防止某些CSS代码不能正确指定对象,但是只能使用v-if,不能使用v-show

(14)列表渲染(重要)

  1. v-for

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rIsD3F4L-1650258889111)(C:\Users\HP\AppData\Roaming\Typora\typora-user-images\image-20220320221234157.png)]

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-F5bR4SAu-1650258889112)(C:\Users\HP\AppData\Roaming\Typora\typora-user-images\image-20220320221302630.png)]

    可以通过for命令生成数组长度的列表

  2. key标签

    • 写法1:[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1FSmggve-1650258889112)(C:\Users\HP\AppData\Roaming\Typora\typora-user-images\image-20220320221606336.png)]

    • 写法2:

      [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-c2XiXkNK-1650258889113)(C:\Users\HP\AppData\Roaming\Typora\typora-user-images\image-20220320222432769.png)]

      其实有两个形参,p就是其中的数据,index为索引值,可以直接使用index为key的值(index)默认从零开始遍历整数

      注意:

      1. in可以使用of进行替换功能完全一样
      2. key标签非常的重要一定要写
    1. 遍历对象

      除了遍历数组还可以对对象进行遍历

      [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nbnvFjV8-1650258889114)(C:\Users\HP\AppData\Roaming\Typora\typora-user-images\image-20220320230025016.png)]

    2. 遍历字符串

      [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7aCwv96w-1650258889114)(C:\Users\HP\AppData\Roaming\Typora\typora-user-images\image-20220320230247238.png)]

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fKPOSuKB-1650258889115)(C:\Users\HP\AppData\Roaming\Typora\typora-user-images\image-20220320230300671.png)]

    字符和索引值

    1. 遍历指定次数

      [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-azd3WCKu-1650258889116)(C:\Users\HP\AppData\Roaming\Typora\typora-user-images\image-20220320230531229.png)]

      [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PLBAHuo3-1650258889116)(C:\Users\HP\AppData\Roaming\Typora\typora-user-images\image-20220320230632946.png)]

    值是正常从1开始计数,索引从0开始数

    1. key的原理

      为节点进行标识,相当于身份证号

      为了提高效率

      虚拟DOM对比算法:
      当key值相同的时候,就对里面的内容进行对比,如果内容相同,则直接复用之前的真实DOM,如果内容不同则进行重新由虚拟DOM进行更新

      key值没有寻找到相同的时候直接生成新的

      导致:使用index直接做key值时如果进行逆序添加,逆序删除等会进行破坏顺序的操作时,index会重新生成,导致顺序错乱,如果有输入类型的(虚拟DOM层完全相同),会导致数据错乱

      所以使用id(数据唯一标识)来使得每个元素绑定指定的key可以较好的使用对比算法,既可以提高复用效果,又可以防止数据错乱

      注:没写key的时候,Vue默认把index当key

    2. 列表过滤(一般交由后端处理)

    3. 列表排序(一般交由后端处理)

(15)Vue的底层监视方法

  1. 加工data

    加入响应式:reactivegetter,reactivesetter(其实更加完善,复杂)

  2. vm._data=data

  3. Vue.set

    用于给Vue对象上添加属性

    Vue.set(vm.想要给哪一个对象添加属性,添加的属性名,添加的属性值)

    也可用于替换(写已有的属性名,加上需要替换的属性值)

    同样功能

    vm.$set(vm.想要给哪一个对象添加属性,添加的属性名,添加的属性值)

    注:

    • 用其他方式进行添加都不会给新属性添加Vue所需要的getter和setter
    • 不可以直接在vm,或者vm._data上直接加,必须还有一层
  4. 数组之中的项没有对应的getter和setter值(数组项之中的对象有,即加了一层才有),所以Vue无法监测到数组项的整体的改变

    arr=[{对象1},{对象2},{对象3}]

    arr[0],arr[1],arr[2]没有,对象1,对象2,对象3有

    只有通过对数组进行操作的几个函数才可以被数组监视到,进行改变,重解析模板

    其实这几个函数(push,pop……)已经和原型对象之上的函数不一样了(添加了一些东西,进行了包裹)

  5. 注意:filter---------过滤 也不会被监视,要使用时进行过滤之后直接替换即可

  6. 数据劫持:给写的data加上了getter和setter的操作,不直接给页面

2、收集表单数据

JSON.stringify(data里数据名)------------------------------------把数据转化为JSON数组

v-model的字符修饰

v-model.number--------------------将输入的变为数字格式

v-model.lazy---------------------------失去焦点的一瞬间才进行收集

v-model.trim---------------------------无视所有的空格

v-model收集的是value值,用户输入的就是value值

v-model收集的是value值,用户输入的就是value值

  1. 未配置value值的时候收集的就是checked(勾选or未勾选,是bool值)
  2. 配置了input的value值
    • v-model的初始值如果是非数组,那么收集的就是checked(勾选or未勾选,是bool值)
    • v-model的初始值如果是数组,那么收集的就是value组成的数组

3、(过滤器)(vue3已删除)

  1. 显示格式化的时间戳

    • 引入第三方库

      bootCDN下载dayjs(复制链接打开后直接保存下来)

      然后引入库,最后在计算属性中,或者写成方法使用下列函数

      day(时间戳).format(‘YYYY-MM-DD HH:MM:SS’)

    • 过滤器实现

      过滤器的实现也需要配置项(和data,methods是一个层级的)

      [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vztTPes4-1650258889117)(C:\Users\HP\AppData\Roaming\Typora\typora-user-images\image-20220323211547685.png)]

      把time传给对应得函数得到返回值之后,在把一个整体都使用返回值进行替代

      注意:

      • 如果给timeFormater()传参会有一个默认的Time传参,再加上自己给的另一个参数

      • 过滤器可以进行串联

      [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-46LyRW0s-1650258889118)(C:\Users\HP\AppData\Roaming\Typora\typora-user-images\image-20220323212454258.png)]

      • time传给timeFormater,timeFormater再传给myslice最后返回

      • 可以配合v-bind进行使用(v-model不支持)v-bind:属性=“xxx|过滤器”

      • 注意这里的过滤器都是局部的,在别的组件(别的Vue对象)之中就不可以进行调用了)

      • 全局过滤器

        [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-T6Lut4Jy-1650258889118)(C:\Users\HP\AppData\Roaming\Typora\typora-user-images\image-20220323212952278.png)]

        注意这里是filter,只能一个一个的写

4、内置指令

  1. v-text

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-IEFcZ37x-1650258889119)(C:\Users\HP\AppData\Roaming\Typora\typora-user-images\image-20220323213649450.png)]

    效果相同,但是不如插值语法灵活,会替换掉节点之中的所有内容,把所有内容当做文本,不支持结果的解析

  2. v-html

    用法与v-text相同,只不过支持结果的解析(如果包含html标签会执行)

    内容补充:

    cookie

    第一次请求,需输入用户名与密码进行登录,登陆成功后不仅返回界面,同时会返回一些cookie,被浏览器存储了。

    第二次请求,携带着对应的cookie(身份的标识),校验之后,返回数据,有些可能还会带着新的cookie。

    cookie是每个浏览器各自使用的,不可以跨浏览器进行读取

    使用cookie可以直接伪造身份(安装插件:cookie editor可以批量导入,导出cookie)

    如果使用了这个插入了且加入document.cookie便可以获得别人浏览器上的cookie(设置httponly可以防止此种情况的发生)

    最好不要使用这个:

    1. 永远不要相信用户的输入
    2. 容易导致XSS攻击
  3. v-cloak

    js阻塞:如果,我没有执行完毕,其他的都不可以执行

    这个属性,当Vue加载成功的时候移除这个属性

    当Vue不工作,即网络不通畅的时候,防止未经解析的模板跑到界面上(先隐藏,Vue调用成功之后在显示)

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hPpzpT72-1650258889119)(C:\Users\HP\AppData\Roaming\Typora\typora-user-images\image-20220324102326029.png)]

  4. v-once

    v-once所在的节点在初次动态渲染之后就视为静态渲染了(不随data改变而改变了)

  5. v-pre

    跳过其节点所在的编译过程,即Vue不再去解析这个节点,直接进行呈现

    可以用它跳过一些不需要编译的语法,加快编译速度

5、自定义指令

自己定义操作名和操作

第一种定义的方法:写成函数

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-omzw5Wyk-1650258889120)(C:\Users\HP\AppData\Roaming\Typora\typora-user-images\image-20220324104712536.png)]

自己定义了v-big

所有的函数都可以收到element和binding

element是实例即真实的dome元素,binding是绑定的对象(n)里面有value

执行的时机:

  1. 指令与元素成功绑定时
  2. 指令所在的模块重新解析时

第二种定义方法:对象形式

最完整的形式,可以包含多个指定函数,Vue会在特殊的时机帮你调用这几个函数(注意名称不能写错)

  1. bind(element,binding){}

    指令与元素成功绑定时调用

  2. inserted(element,binding){}

    指令所在元素被插入界面时调用

  3. update(element,binding){}

    指令所在模板被重新解析时调用

注意事项

  • 要使用多个单词来为函数命名的时候:

    格式为:v-big-name

    而不是:v-bigName (会报错)

    调用时应该使用完整的写法:‘v-big-name’(){}

  • 这里写出来的时局部的自定义指令,如果想要定义全局指令,和全局过滤器类似

    Vue.directive(指令名,配置对象或函数)

6、生命周期

生命周期:在Vue的一个周期内某个指定的时间点进行指定的事

(1)生命周期回调函数(生命周期钩子、什么周期函数)

生命周期函数的名称是固定的非常重要

4对钩子

  1. beforecreate

    数据代理和数据监测创建之前

  2. created

    完成了数据监测和数据代理(可以监视到data和methods了)

  3. beforeMount

    页面呈现未经Vue编译的DOM结构

    对DOM的所有操作都不奏效

  4. mounted(与data平级):挂载

    页面呈现经过Vue编译的DOM

    这时候对DOM的操作有效,但是应该尽量避免(否则Vue没有意义了)

    至此初始化过程结束,一般在这里执行开启定时器、发送网络请求、订阅消息、绑定自定义事件等初始化操作

    在Vue完成模板的解析,并且把初始的真实DOM元素(之后改变了也不再调用了,之后的改变不叫挂载,叫更新)放入页面后(即挂载完成)调用

    注:mounted的this指向vm或者组件实例对象

  5. beforeUpdate

    更新之前,立刻调用(页面和数据尚未保持同步)

  6. updated

    更新之后,进行调用(页面与数据都是最新的)

  7. beforeDestroy

    销毁vue对象之前调用(即调用了vm.$destroy()之后立即进行调用,很少亲自调用)清理与其他实例的链接解绑所有自定义事件监听器(原生事件不会解绑:比如说点击事件)

    注意:

    • 销毁了vm之后,DOM依然存在,只是没有vm帮助管理了
    • 此时vm的所有东西仍处于可以使用的状态:一般在此阶段进行关闭定时器、取消订阅消息、解绑自定义事件等收尾操作(但是这里不会再触发数据更新了
  8. destroyed

  9. 还有3个钩子需要在讲路由的时候才可以看到

7、template

可以通过这个配置项来对一个空的div进行配置**``使用这个符号进行包裹**(使用模板字符串进行包裹可以随意的进行换行,否则只能一行写完),使得div显示模板(多个标签必须包裹在一个根元素(比如div)之中,否则会报错,注:不能用template做根元素)

二、组件化编程

1、为什么要用组件化编程

传统方式:

  • 依赖关系混乱,不好维护
  • 代码复用率不高

组件方式:

每个区域都包含有自己的CSS,HTML,JS,一个vm可以下属多个组件,每个组件也可以有自己的下属组件

实现应用之中局部功代码和资源的集合

注:模块化:即把一个大的js文件拆为几个小的js文件

2、非单文件组件(开发时几乎不用)

一个文件中包含n个组件

a.html

使用组件需要三步:

  1. 创建

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-y8qrBZ5K-1650258889121)(C:\Users\HP\AppData\Roaming\Typora\typora-user-images\image-20220327163840410.png)]

    注意:

    1. 组件定义
    2. data一定要写成函数式()因为每次调用都会生成一组新的变量,否则只有一组的话在一个地方被修改,则所有调用的地方都会修改

    带上模板

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BgZiDLlE-1650258889121)(C:\Users\HP\AppData\Roaming\Typora\typora-user-images\image-20220327213357271.png)]

  2. 注册

    局部注册(叫常用)

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-b6ivK4xP-1650258889122)(C:\Users\HP\AppData\Roaming\Typora\typora-user-images\image-20220327213134405.png)]

    components

    定义时的名字:组件名(可自取)

    全局注册

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YXY0PUp4-1650258889122)(C:\Users\HP\AppData\Roaming\Typora\typora-user-images\image-20220327214135076.png)]

    component

  3. 使用

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-O8FVsnst-1650258889123)(C:\Users\HP\AppData\Roaming\Typora\typora-user-images\image-20220327214839433.png)]

  4. 注意:

    • 关于组件名:

      1. 一个单词:

        首字母小写

        首字母大写

      2. 多个单词组成

        短横杠链接 my-school

        首字母都大写:MySchool(需要脚手架支持)

      3. 回避与HTML已有的相同标签(大小写都不行)

    • name

      创建时可以添加一个name标签项,这样Vue开发者工具里的显示就不是你在注册时所赋予的名字而是这里name的名字,但是在页面之中进行调用的时候,依然要使用注册时所赋予的名字(防止组件错乱)

    • 在脚手架环境下,调用时可以写为闭合单标签

      [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ko5O60ZA-1650258889123)(C:\Users\HP\AppData\Roaming\Typora\typora-user-images\image-20220327220211536.png)]

    • 简写模式

      const student=Vue.extend({option})
      const s={option}
      
  5. 组件的嵌套

    父组件

    子组件

    在父组件之中使用components对子组件进行注册

    子组件应该在父组件之前进行创建

    注册给谁,数据就只有谁能调用,就去谁的结构里面写

  6. app组件,一般使用app组件管理所有的组件,vm只管理app

  7. VueComponent

    • 组件本质上是一个名字为VueComponent的构造函数,且不是程序员定义的,是Vue.extend生成的

    • 我们只需要按照前面的方法就可以让Vue在解析的时候帮助我们创造实例对象

    • 特别注意每次调用Vue.extend,返回的都是一个全新的VueComponent(每new一次就会生成一个新的,不同的实例对象)

    • 关于this的指向

      1. 组件配置中:

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

      2. new Vue(option)配置中:

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

      二者其实类似可以进行类比(数据代理,数据监视)

      VueComponent实例对象,简称vc

      Vue实例对象,简称vm

  8. 一个重要的内置关系

     VC.prototype.__proto__===Vue.prototype
    注:
         prototype显示原型对象(只有函数才有)
         __proto__隐式原型对象
    

    当查找一个数据没有找到时会沿着原型链进行寻找

    目的让VC可以访问到Vue原型上的属性与方法

3、单文件组件

一个文件中只包含1个组件

a.vue(创建了一个新的文件名)经过处理和加工变为.js才可以被浏览器识别(使用脚手架,即一个搭建好的webpack,进行搭建)

条理清晰,便于管理

  1. 命名规则(与组件命名相同):

    1. 一个单词:

      首字母小写

      首字母大写

    2. 多个单词组成

      短横杠链接 my-school

      首字母都大写:MySchool(需要脚手架支持)

  2. 书写格式

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LPyfuejE-1650258889124)(C:\Users\HP\AppData\Roaming\Typora\typora-user-images\image-20220330211805297.png)]

只有这三个标签

安装插件后<v 就可以生成默认模板

一定要在script里面写上暴露:

  1. 默认暴露(建议使用,引入时较为简单)

    写法:

    在组件结束后写上

    export default vc

    或者在开头直接写上

    export default Vue.extend({

    })

    或者简写为

    export default{

    name:’’,

    }

  2. App组件引入其他组件

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xZraqHnx-1650258889125)(C:\Users\HP\AppData\Roaming\Typora\typora-user-images\image-20220331091022059.png)]

    并对其他组件进行注册

  3. 使用main.js(入口文件)引入App组件

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9rRFoZzS-1650258889126)(C:\Users\HP\AppData\Roaming\Typora\typora-user-images\image-20220331091846123.png)]

    并对App组件进行注册

  4. 在html之中引入main.js和Vue(在body的底部进行引入,先引入Vue再引入main.js)

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-B1WVgdPF-1650258889127)(C:\Users\HP\AppData\Roaming\Typora\typora-user-images\image-20220331092537039.png)]

三、脚手架(Vue CLI)

CLI----------------------command line interface命令行接口工具

Vue脚手架是Vue的官方标准化开发工具

最新版本4.x

(1)分析脚手架

全局

  1. 安装 @vue/cli(仅第一次使用时需要)

    备注:最好配置淘宝镜像安装

    npm config set registry https://registry.npm.taobao.org
    

    在进行安装

    npm install -g @vue/cli
    

    安装完毕后退出cmd再重新打开

  2. 切换到你要创建项目的目录,然后使用命令创建项目

    cd Desktop(在桌面上创建)

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0nZvtj5G-1650258889128)(C:\Users\HP\AppData\Roaming\Typora\typora-user-images\image-20220331095709177.png)]

    执行vue create

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bTJZo3FB-1650258889129)(C:\Users\HP\AppData\Roaming\Typora\typora-user-images\image-20220331100115943.png)]

    实际上帮你创建了一个包含hello world的案例和脚手架,使用自己的项目对hello world进行替换即可

    选择Vue的版本

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CFN2umm1-1650258889129)(C:\Users\HP\AppData\Roaming\Typora\typora-user-images\image-20220331102111852.png)]

    最后一项是自定义的意思

    babel:ES6转ES5

    eslint:语法检查

    选择好对应的版本之后等待安装即可

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7dEHB1xM-1650258889135)(C:\Users\HP\AppData\Roaming\Typora\typora-user-images\image-20220331102912605.png)]

    创建完成

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hGUB3CMv-1650258889139)(C:\Users\HP\AppData\Roaming\Typora\typora-user-images\image-20220331102931520.png)]

    按提示执行如图所示的命令

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vGbp3mmA-1650258889140)(C:\Users\HP\AppData\Roaming\Typora\typora-user-images\image-20220331103211684.png)]

    给了一个两个端口,一个自己使用,另一个同局域网使用

    复制地址,到浏览器之中打开

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-M4pNC8Fs-1650258889143)(C:\Users\HP\AppData\Roaming\Typora\typora-user-images\image-20220331103436722.png)]

    进入到vue所给的例子

    注意:使用快捷键ctrl+c可以停止进程(按两遍)

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-q3yKPfpa-1650258889145)(C:\Users\HP\AppData\Roaming\Typora\typora-user-images\image-20220331223828678.png)]

     App running at:
      - Local:   http://localhost:8080/
      - Network: http://192.168.0.105:8080/
    
  3. 文件结构讲解

    • 主页面

      [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2DIdfhEp-1650258889146)(C:\Users\HP\AppData\Roaming\Typora\typora-user-images\image-20220331225418223.png)]

    • src

      [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9Ye635JW-1650258889148)(C:\Users\HP\AppData\Roaming\Typora\typora-user-images\image-20220331225716492.png)]

      1. main.js-----------------运行nmp run serve之后执行的文件

        [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rPZp4hOQ-1650258889149)(C:\Users\HP\AppData\Roaming\Typora\typora-user-images\image-20220331230746560.png)]

      2. assets文件夹

        在前端工作之中常常被用于存储静态资源(logo图,png……)

      3. components文件夹

        存放处App组件之外的所有组件

        注:在vscode之中打开终端(cmd)的方法按住Ctrl+~(esc下方的按键)即可

      4. App.vue

    • public文件夹

      1. favicon.ico

        网站的页签标签

      2. index.tml

        网站主页

  4. render配置项(因为引入的是不完整的vue,没有模板解析器,所以需要使用rander来解析模板)

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-R7AbVeSH-1650258889150)(C:\Users\HP\AppData\Roaming\Typora\typora-user-images\image-20220402105213379.png)]

    这里的a是一个函数叫createElement

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-69xrE8T0-1650258889150)(C:\Users\HP\AppData\Roaming\Typora\typora-user-images\image-20220402105455792.png)]

    比如a(‘h1’,‘你好啊’)会展现出

    <h1>你好啊</h1>
    

    的效果

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ieIKx9bF-1650258889151)(C:\Users\HP\AppData\Roaming\Typora\typora-user-images\image-20220402105929789.png)]

    改写成箭头函数之后的简写形式

  5. vue的引入

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rm6PLlzy-1650258889152)(C:\Users\HP\AppData\Roaming\Typora\typora-user-images\image-20220402110049016.png)]

    为什么要有精简版的vue(vue.runtime.xxx.js)

    完整的vue=核心+模板解析器

    可是在使用webpack进行打包之后,就不在需要模板解析器了

    所以使用精简版的可以减少代码的含量

    (组件之中的template有专门的的解析,不用当心)

  6. 修改脚手架的默认配置

    注意:Vue脚手架隐藏了所有webpack的相关配置,若想要查看具体的webpack配置需要在控制台之中执行

    vue inspect > output.js
    

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kNYZ4vFh-1650258889153)(C:\Users\HP\AppData\Roaming\Typora\typora-user-images\image-20220402165439208.png)]

    即将vue隐藏的信息一output.js的形式输出到当前所在的文件夹内

    直接打开由于是一个对象但是不完整所以会报错,加上const a =就不会报错了(这里只能查看,不可以修改)

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-krVStdXt-1650258889154)(C:\Users\HP\AppData\Roaming\Typora\typora-user-images\image-20220402165734209.png)]

    • 不能随便修改的默认配置

      1. public文件夹
      2. src不能改
      3. main.js不能改
    • 如果想要修改

      可以修改的属性都已经在 Vue官网->Vue CLI->配置参考中进行了注明

      [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-i6aXy802-1650258889154)(C:\Users\HP\AppData\Roaming\Typora\typora-user-images\image-20220402170554768.png)]

      新建一个vue.config.js文件夹在与package.json同级的地方,之后在文件之中结合配置参考中的代码来进行修改(现用现查,不需要背)

      [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Vi2ORXpH-1650258889155)(C:\Users\HP\AppData\Roaming\Typora\typora-user-images\image-20220402171129297.png)]

      修改之后一定要重新定义

      注:要么就不写用默认的,如果写了,就算空白,也不会去调用默认的了,而是报错

    • 关闭语法检查,

      在配置参考之中找到lintOnSave

      [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MjJyYV82-1650258889156)(C:\Users\HP\AppData\Roaming\Typora\typora-user-images\image-20220402172044786.png)]

      注:配置参考的所有项都是平级的都要写在函数之中

      [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HzpvMTb0-1650258889157)(C:\Users\HP\AppData\Roaming\Typora\typora-user-images\image-20220402172405132.png)]

      关闭了语法检查之后才可以跑起来,否则定义了没有用到的函数会导致报错,进而导致脚手架无法启动

(2)ref属性

  1. 给某个标签打标识,(相当于id)

    vc.$refs.ref名(获取vc的真实dom)

  2. 给子组件名打ref(这里用id)

    vc.$refs.ref名得到组件实例对象(重要)

(3)vc配置项props

组件的复用,动态的从外面传入新的数据

  1. 方法一:简单申明接收

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bjFYo1tK-1650258889158)(C:\Users\HP\AppData\Roaming\Typora\typora-user-images\image-20220402191517261.png)]

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xa1YmFUr-1650258889158)(C:\Users\HP\AppData\Roaming\Typora\typora-user-images\image-20220402191544934.png)]

    在App组件之中给School组件传入一个值,要用props进行接收(传多个值的时候,顺序不一定要求对应)

  2. 方法二:类型限制接收

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-haXxusuM-1650258889159)(C:\Users\HP\AppData\Roaming\Typora\typora-user-images\image-20220402210621945.png)]

    限制接收的对象的类型

    注:

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Q5X4Qq76-1650258889160)(C:\Users\HP\AppData\Roaming\Typora\typora-user-images\image-20220402210657149.png)]

    这里age前加了:进行了数据绑定,""内的内容视为一个代码操作,所以最后传下去的时数字,

    如果不加的话传下去的就是字符串了(非常重要,传一个对象的时候也要加)

  3. 方法三:最完整版的接收

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TPMH5V5g-1650258889160)(C:\Users\HP\AppData\Roaming\Typora\typora-user-images\image-20220402211215999.png)]

    配置所需的类型的同时,配置是否必须,或配置一个默认值(后两者一般不一起写,没有意义)

    注意:

    1. prop-----------------------属性

    2. 不可以申明不存在的数据

    3. props中的值优先被放到vc上(和data之中的数据同名的时候看props上的)

    4. 传入的属性值可以改,但是最好不要改,可能会出现问题

      如果要修改的话:

      在data之中定义一个新的数据使它=this.传入的数据

      然后对新定义的数据进行修改即可

    5. 什么都可以传,数组、函数这些都可以传

(4)vc配置项mixin

混入:两个组件共享一个相同的配置

创建一个新的js文件在其中书写一个配置项并将其暴露

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bKMIZLrT-1650258889161)(C:\Users\HP\AppData\Roaming\Typora\typora-user-images\image-20220402214033932.png)]

在组件中引入这个配置项

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MDVTictU-1650258889162)(C:\Users\HP\AppData\Roaming\Typora\typora-user-images\image-20220402214341453.png)]

使用数组引用

所有的配置项都可以进行混合(包括data)

就是复用配置

注:

  1. 已有的配置项进行混合不是替换,会在原有的基础上进行添加,

  2. data中的数据,methods中的方法如果发生冲突的时候,以源码为主

  3. 但是生命周期钩子冲突的时候,都进行执行,且源码的执行靠后

  4. 全局引入 Vue.mixin(混合项)

    写在main.js之中

    这样进行引入之后,所有的vm,vc上都会有混合项

(5)插件

可以增强vue

本质上是一个必须包含install的对象

一般写在plugins.js文件之中

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-w77DY2hC-1650258889163)(C:\Users\HP\AppData\Roaming\Typora\typora-user-images\image-20220403104319238.png)]

然后在main.js之中进行应用

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4Z9u8cpc-1650258889163)(C:\Users\HP\AppData\Roaming\Typora\typora-user-images\image-20220403104614898.png)]

注:install()函数的第一个参数是Vue第二个参数第二个以后的参数是使用者传递的数据

可以在里面添加全局过滤器、全局指令、全局混入、添加实例方法,然后在,main.js之中进行调用,所有的对象就都可以对它进行使用

(6)样式的写法

问题:vue最后会把所有组件的样式都汇总到一起,如果出现了相同的样式名,后引入的样式会把先引入的样式进行覆盖

解决 在style标签上添加一个scoped属性

表示,这个样式只作用于这个组件(注意App组件最好不要加这个,不然不会对所有组件进行管理)

补充:如果要使用less来写样式,可以在style之中的lang标签改为less然后安装less-loader

npm i less-loader@7

注意安装的版本要与webpack对应(@7即安装7的最新版本)

scope-------------------作用域,范围

ajax

(7)组件化的编码流程(通用)

  1. 实现静态组件:抽取组件,使用组件实现静态页面效果

  2. 展示动态数据:

    • 数据的类型和名称

      类型:数组或者对象

      数组包对象很常用

      [{id:’’,data:’’},{}]

    • 数据保存在哪一个组件

      注意:兄弟组件之间不好传数据

      现在只能使用父子之间的传递

      所以一个组件在用的数据:放到在用的组件

      一些组件在用,放到父组件之中(状态提升)

      使用props进行通信

      父传子使用props就行

      子传父:

      父亲创建一个函数,且使用props传给儿子,儿子在合适的时机进行调用(把值传入函数),函数定义在父亲里,就可以实现向父亲的数组中传入数据

      父组件

      methods{
      receive(x){
      this.todo.unshift(x)
      }
      }
      
      

      子组件:

      add(e){
      const todoObj={id:name(),title:e.traget.value,done:false}
      this.recive(todoObj)
      }
      

      注:

      1. 键盘事件绑定好add函数后通过e.traget.value可以拿到输入框之中的值(e是自己

        命名的)

      2. 数据在哪里,操作就在哪里

      3. 数据只可以逐层传递,父亲给儿子,不可以给孙子

      4. v-model绑定的值不可以是props的值,因为props是不可以修改的

(8)浏览器本地存储

向本地缓存一些数据

  1. localStorage

    • 执行以下代码就可以存储

      localStorage.setItem(‘键名’,‘键值’)

      存储的键名和键值都要是字符串,

    • 执行以下代码进行读取

      localStorage.getItem(‘键名’)

    • 执行以下代码进行删除

      localStorage.removeItem(‘键名’)

    • 执行以下代码进行清空

      localStorage.clear()

    数据全部在本地就算关闭浏览器也依然存在

    手动清除才可以

  2. sessionStorage

    • 执行以下代码就可以存储

      sessionStorage.setItem(‘键名’,‘键值’)

      存储的键名和键值都要是字符串,

    • 执行以下代码进行读取

      sessionStorage.getItem(‘键名’)

    • 执行以下代码进行删除

      sessionStorage.removeItem(‘键名’)

    • 执行以下代码进行清空

      sessionStorage.clear()

    与localStorage的API都相同

    但是浏览器一关闭就清空了

    session----------------------会话

以上两者统称webStorage

存储大小一般5MB左右

配合监视属性(watch)进行数据的存储

与读取

(9)组件的自定义事件

内置事件:click、keyup……

自定义事件:只可以给组件使用

  1. 是一种组件间的通信方式,适用于子组件给父组件数据

  2. 使用场景:A:父组件,B:子组件,B想给A传数据,那么就要在A中给B绑定自定义事件(事件的回调在A中

  3. 原则:给谁绑定的事件,就在谁那里触发

  4. 绑定自定义事件:

    • 方式一:

      在父组件中:

      <demo @自定义事件名="回调函数名">
      或者
      <demo v-on:自定义事件名="回调函数名">
      

      回调函数写在methods之中,可以接受触发之后传回的值

    • 方式二:

      在父组件之中:

      <demo ref="xxx"/>
      ……
      mounted(){
      this.$refs.xxx.$on('自定义事件名',this.回调函数)
      }
      
    • 若想让自定义事件只触发一次,可以使用once修饰符,或$once方法

  5. 触发自定义事件:this.$emit(‘自定义事件名’,给回调函数传的参数)

  6. 解绑自定义事件:this.$off(‘自定义事件名’)

  7. 组件上也可以绑定原生DOM事件(click……),但是需要添加native修饰符

  8. 注意:通过

  9. this.

    r

    e

    f

    s

    .

    x

    x

    x

    .

    refs.xxx.

    refs.xxx.on(‘自定义事件名’,回调)绑定自定义事件的时候,要么只写回调函数名(this.回调函数名),把函数本体写在methods中,要么直接在这里写回调函数,但是要写为箭头函数

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JfHojzoS-1650258889164)(C:\Users\HP\AppData\Roaming\Typora\typora-user-images\image-20220404095927160.png)]

图中的选项卡可以查看自定义事件的触发

emit-------------------爆发

native------------------原生的,本来的

(10)全局事件总线(非常重要)GlobalEventBus

可以实现任意组件之间的通信,开发的时候非常常用

其实是一个把现有的知识进行组合之后的经验,不是一个新的API

要求:

  1. 可以被所有组件看见------------------------------------------在Vue的原型对象上(见单文件组件第8点,一个重要的内置关系)
  2. 可以调用:

    o

    n

    on、

    onoff、$emit----------------------------这些关系都在vue的原型对象上

综上:

标准的写法(写在main.js的vue对象之中)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ywm8T5PA-1650258889165)(C:\Users\HP\AppData\Roaming\Typora\typora-user-images\image-20220404105719104.png)]

使用生命周期钩子进行创建,在Vue的原型对象上添加一个$bus,以实现上面的需求

注意:

不再用这个绑定了事件的vc时要在beforeDestroy(){}中对这个事件进行销毁,否则这个事件名会一直跟着vm保持占用

谁接收数据就在谁的地方给发送数据的绑定一个事件

在发送数据的地方进行触发

在挂载的时候进行绑定

应用场景:

  1. 同级传递
  2. 跨多级传递

(11)消息的订阅与发布

也可以实现全局数据的传递

需第三方库,推荐:pubsub-js(所有的框架都可以使用)

  1. 安装

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rd4d8AFY-1650258889166)(C:\Users\HP\AppData\Roaming\Typora\typora-user-images\image-20220404111835956.png)]

  2. 引入

    import pubsub from 'pubsub-js'
    
  3. 订阅消息

    mounted() {
       this.订阅id= pubsub.subscribe('消息名',(消息名,数据)=>{
        执行回调
        })
    }
    
  4. 发布消息

    mounted() {
        pubsub.publish('消息名',数据)
    }
    
  5. 解除订阅

    每次订阅都是通过订阅id进行订阅的,解绑的时候也需要使用订阅id

      beforeDestroy(){
      pubsub.unsubscribe(this.订阅id)
      }
    

其实全局事件总线更好

(12)$nextTick

语法:vc.nextTick(回调函数)

作用:在下一次DOM更新结束后执行指定的回调函数

什么时候使用:但数据变更之后需要基于更新后的DOM元素进行一些操作的时候,就要使用这个API

(13)过度与动画

写法:

  1. 准备好样式

    • 元素进入的样式
      1. v-enter:进入的起点
      2. v-enter-active:进入的过程
      3. v-enter-to:进入的终点
    • 元素的离开的样式:
      1. v-leave:离开的起点
      2. v-leave-active:离开的过程
      3. v-leave-to:离开的终点
  2. 使用transition包裹要过度的元素,并且配置name属性

    <transition name="hello">
    		<h1 v-show="isShow">你好</h1>
    </transition>
    
  3. 注意

    • 如果有多个元素都需要过度或者动画要使用transition-group 进行包裹,并且每一个元素都要有指定的key值
    • appear可以加在transition标签上(直接写)让动画一开始就可以调用

animate库的使用

  1. 打开网站选择对应动画

    https://animate.style/

  2. 先进行安装

    npm install animate.css
    
  3. 进行引入

     import ‘animate.css’ 
    
  4. 然后看这里

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-pkyFPbrJ-1650258889166)(C:\Users\HP\AppData\Roaming\Typora\typora-user-images\image-20220404171645925.png)]

    在想要添加的标签后添加这一句

    到这里配置完毕

  5. 给标签添加标签项

    enter-active-class=“xxx” //进入效果

    leave-active-class=“xxx” //离开效果

    xxx的获取方法

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DojM8E6e-1650258889167)(C:\Users\HP\AppData\Roaming\Typora\typora-user-images\image-20220404172052697.png)]

    在网站上选择相应的样式后进行复制

四、Vue中的Ajax

(1)常用的发送AJAX请求的方法

  1. xhr(元祖,不常用)

    new XMLHHttpRequest()

    xhr.open()

    xhr.send()

  2. jQuery (对xhr进行封装)

    $.get

    $.post

  3. axios(对xhr进行封装)

    vue进行使用比较好

  4. fetch(与xhr是平级的关系)

    进行了两次封装,且兼容性不好

  5. vue-resource(对xhr进行封装)

    vue中插件库

    早期vue常用

(2)使用axios发送请求

  1. 下载axios

    npm i axios
    
  2. 在App组件之中引入axios

    import axios from 'axios'
    
  3. 绑定函数并调用

    getData(){
    axios.get('服务器地址/所请求的数据名').then(
    response=>{
        response.data//请求到的数据
    },//成功则执行这个
    error=>{
        error.message//失败的原因
    }//失败则执行这个
    )
    }
    
  4. 跨域

    数据传递时有同源要求

    即协议名、主机名、端口号必须一样

    如果有一个或者多个不一样的话就会有跨域的问题出现

    会发出请求,服务器也会进行返回数据,但是浏览器不会把数给你

    • 解决方法:

      1. cros

        后端进行解决(配置特殊的响应头,实际意义上的解决)

      2. jsonp

        借助script标签在引入src时不受同源影响

        巧妙但是很少用(前后端都改,而且只可以解决get请求的跨越问题)

      3. 配置代理服务器

        代理服务器与浏览器当前的地址是相同的

        浏览器向代理服务器要数据

        代理服务器向目标服务器要数据

        目标服务器向代理服务器返回数据

        代理服务器再将数据返回给浏览器

        (注:ajax只是前端技术,服务器之间传数据,不用ajax,不要求同源)

        • 代理服务器的开启方法

          1. Nginx(学习成本较高)

          2. 使用Vue进行直接开启

            在vueconfig.js中进行添加

            配置方法一:

            [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-h7agbKI3-1650258889168)(C:\Users\HP\AppData\Roaming\Typora\typora-user-images\image-20220404204323138.png)]

            [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WmJRuCIF-1650258889168)(C:\Users\HP\AppData\Roaming\Typora\typora-user-images\image-20220404204606479.png)]

             devServer: {
                proxy: 'http://localhost:4000'
              }
            

            之后重新启动就可以开启代理服务器了

            请求数据时所使用的的地址变为:

            当前服务器地址/所请求的数据

            缺点:

            public文件夹中的数据就相当于当前代理服务器中的数据,如果请求了这个文件夹含有的数据,则代理服务器不会向目标服务器进行请求,而是把文件夹中的数据进行返回

            只能配置一个代理(一个目标服务器)

            配置方式二:(解决方式一的问题)

            [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xE6Lr8Su-1650258889169)(C:\Users\HP\AppData\Roaming\Typora\typora-user-images\image-20220404205605527.png)]

             devServer: {
                proxy: {
                  '/请求前缀1': {
                    target: '目标服务器地址',
                    pathRewrite:{'/请求前缀':''}   
                    //非常重要,把地址中的请求前缀去掉,否则会找目标服务器去要带着请求前缀的地址下的请求对象
                    ws: true,
                    //用于支持websocket
                    changeOrigin: true
                    //跨域伪造,为true则实话实说,讲出自己的真实地址,为false则把自己的地址伪造成目标服务器的地址,即用于控制host字段
                  },
                    //对另一个服务器进行请求
                  '/请求前缀2': {
                    target: '另一个目标服务器地址'
                  }
                }
              }
            

            请求的写法:

            axios.get('服务器地址:端口号/请求前缀/请求对象')
            

            加前缀走代理,不加前缀则不走代理(优先匹配前端资源)

            注:

            请求的时候如果要使用到js的语法则可以像下面这样写

            axios.get(`地址${想要当做js解析的部分}`)//注意这里的两个点是模板字符串的点
            
  5. vue-resource的使用

    在引入vue的地方进行引入

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-E08pRChb-1650258889169)(C:\Users\HP\AppData\Roaming\Typora\typora-user-images\image-20220404222425099.png)]

    对插件进行使用

    用法与axios完全相同,

    只需要把axios变为this.$http即可

    但是这个库维护的较少了(官方已经不维护了),所以还是推荐使用axios

(3)插槽

让父组件可以向子组件的指定位置放一些东西

  1. 默认插槽

    父组件之中:
    <子组件名>
        <div>要传递的结构</div>
    </子组件名>
    
    子组件之中:
    <template>
        <div>
            定义插槽
        <slot>如果没有进行传递则显示这里的内容</slot>
        </div>
    </template>
    
  2. 具名插槽

    父组件之中:
    <子组件名>
        <template slot="自定义的名字1">
        	<div>要传递的结构</div>
        </template>
         <template v-slot:自定义的名字2>
        	<div>要传递的结构</div>
        </template>
    </子组件名>
    
    子组件之中:
    <template>
        <div>
            定义插槽
        <slot name="自定义的名字1">如果没有进行传递则显示这里的内容</slot>
        <slot name="自定义的名字2">如果没有进行传递则显示这里的内容</slot>
        </div>
    </template>
    
  3. 作用域插槽

使用场景:数据存在组件的自身,但是数据的显示结构需要组件的使用者(父组件)进行决定

父组件之中:
<子组件名>
    <template scope="最好与子组件传过来的数据名保持相同">
    	<div>要显示的结构1</div>
    </template>
</子组件名>

<子组件名>
    <template slot-scope="最好与子组件传过来的数据名保持相同">
    	<div>要显示的结构2</div>
    </template>/子组件名>
<子组件名>
    
    
    
    
子组件之中:
<template>
    <div>
        定义插槽
    <slot :数据名:"数据名">如果没有进行传递则显示这里的内容</slot>
    </div>
</template>
    <script>
    数据
    </script>

这样在父组件的结构之中也可以通过数据名来点出所需要的数据

几个插槽直接可以互相配合

五、vuex(重要)

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

使用时机:

一个数据的读取和返回如果涉及到组件太多,那么全局事件总线需要绑定的就太多了,这时候就选择把数据存在vuex通过两个API进行读取和修改(即多个组件依赖于同一状态,不同组件的行为需要变更同一状态)

vuex的工作原理

(1)vuex的引入:

  1. 安装vuex

    注:vue2只能用vuex的3版本,vue3只能用vuex的4版本

    npm i vuex@3
    
  2. 引入vuex

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4FpCLe1Z-1650258889170)(C:\Users\HP\AppData\Roaming\Typora\typora-user-images\image-20220405113659353.png)]

(注:这里不用第二个框中的代码了,在第三步进行使用)

  1. 在src目录下新建一个store文件夹,在里面新建一个index.js

    按如下方法配置store

    //该文件用于创建store
    
    //引入Vue核心库
    import Vue from 'vue'
    //引入Vuex
    import Vuex from 'vuex'
    //引用Vuex
    Vue.use(Vuex)
    
    const actions = {
        //响应组件中加的动作
    	jia(context,value){
    		// console.log('actions中的jia被调用了',miniStore,value)
    		context.commit('JIA',value)
    	},
    }
    
    const mutations = {
        //执行加
    	JIA(state,value){
    		// console.log('mutations中的JIA被调用了',state,value)
    		state.sum += value
    	}
    }
    
    //初始化数据
    const state = {
       sum:0
    }
    
    //创建并暴露store
    export default new Vuex.Store({
    	actions,
    	mutations,
    	state,
    })
    

    在new vue的时候引入store配置项,这样所有的vm,vc都可以看到

  2. 在main.js中再次引入store

    import store from './store/index'
    

    并且在vm实例中进行配置:写一个配置项叫store就可以

    注:脚手架的引入方式,不论你的import在哪都会先进行引入之后在执行其他的代码

(2)veux的使用

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EC0w8G8q-1650258889171)(C:\Users\HP\AppData\Roaming\Typora\typora-user-images\image-20220405162710748.png)]

注:

  • 上图的操作名在使用的时候都是全小写的
  • vc实例在不需要操作的时候可以直接通过commit调用到mutations
  • mutations中的方法名一般都是全大写便于区分
  • actions中的commit中也包含有dispatch属性,即几个actions之间可以进行互相调用,增加复用性
  • commit身上也有state属性,其实可以直接拿到数据进行操作,但是不建议(这样写工具就失效了)
  1. 引入了vuex后,所有的vm与vc身上都有了$store属性,通过这个属性和上图对应的方法可以进行调用

  2. this.$store.dispatch()

    与actions对话,调用actions之中与

(3)vuex的开发者工具

其实也集成在了vue的开发者工具中了

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qFzyLiv7-1650258889171)(C:\Users\HP\AppData\Roaming\Typora\typora-user-images\image-20220405162502140.png)]

就是第二个选项卡

上方选择区:记录mutations中的操作

下方展示区:进行具体展示

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bNJ9zDjD-1650258889172)(C:\Users\HP\AppData\Roaming\Typora\typora-user-images\image-20220405163815583.png)]

注意:取消操作会取消所有以此次操作结果为基础进行的所有操作

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RXSjnLMY-1650258889173)(C:\Users\HP\AppData\Roaming\Typora\typora-user-images\image-20220405164319029.png)]

注:

  1. 组件中读取vuex中的数据:$store.state.sum(模板中可以不加this.但是脚本中必须加)

  2. 组件中修改vuex中的数据:$store.dispatch('action中的方法名',数据)$store.commit('mutations中的方法名',数据)

    备注:若没有网络请求或其他业务逻辑,组件中也可以越过actions,即不写dispatch,直接编写commit

mutations-----------------------------突变,变化,转变

commit--------------------------------上下文

(4)getters配置项

  1. 概念:当state中的数据需要经过加工后再使用时,可以使用getters加工。

  2. store.js中追加getters配置

    ......
    
    const getters = {
    	bigSum(state){
    		return state.sum * 10
    	}
    }
    
    //创建并暴露store
    export default new Vuex.Store({
    	......
    	getters
    })
    
  3. 组件中读取数据:$store.getters.bigSum

类比:

state=======>data

getters======>computed

(5)map的使用

帮助我们自动生成一些重复的代码,简化写法

  1. 在所需要使用的vue文件中进行引入

    import {mapState,mapGetters,mapMutations,mapActions} from 'vuex'
    
  2. 四种写法

    • mapState 从state之中读取数据为计算属性供给vc使用

      computed: {
          //借助mapState生成计算属性:sum、school、subject(对象写法)
           ...mapState({sum:'sum',school:'school',subject:'subject'}),
               
          //借助mapState生成计算属性:sum、school、subject(数组写法)
          ...mapState(['sum','school','subject']),
      },
      
    • mapGetters 从getter中读取数据为计算属性供给vc使用

      computed: {
          //借助mapGetters生成计算属性:bigSum(对象写法)
          ...mapGetters({bigSum:'bigSum'}),
      
          //借助mapGetters生成计算属性:bigSum(数组写法)
          ...mapGetters(['bigSum'])
      },
      
    • mapActions用于帮助我们生成与actions对话的方法,即:包含$store.dispatch(xxx)的函数

      methods:{
          //靠mapActions生成:incrementOdd、incrementWait(对象形式)
          ...mapActions({incrementOdd:'jiaOdd',incrementWait:'jiaWait'})
      
          //靠mapActions生成:incrementOdd、incrementWait(数组形式)
          ...mapActions(['jiaOdd','jiaWait'])
      }
      
    • mapMutations用于帮助我们生成与mutations对话的方法,即:包含$store.commit(xxx)的函数

      methods:{
          //靠mapActions生成:increment、decrement(对象形式)
          ...mapMutations({increment:'JIA',decrement:'JIAN'}),
          
          //靠mapMutations生成:JIA、JIAN(数组形式)注:这里的函数名要与mutations中的函数名保持一致
          ...mapMutations(['JIA','JIAN']),
      }
      

    注:

    ...对象, 
    

    可以把对象展开成键值对

    如果不展开,则会因为对象不可以包裹另一个对象而报错

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

(6)模块化编码(进阶)

目的:让代码更好维护,让多种数据分类更加明确。

  1. 修改store.js

    //第一种分类
    const countAbout = {
      namespaced:true,//开启命名空间,这个分类名才可以被map认识
      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
      }
    })
    
  2. 开启命名空间后,组件中读取state数据:

    //方式一:自己直接读取
    this.$store.state.personAbout.list
    //方式二:借助mapState读取:
    ...mapState('countAbout',['sum','school','subject']),
    
  3. 开启命名空间后,组件中读取getters数据:

    //方式一:自己直接读取
    this.$store.getters['personAbout/firstPersonName']
    //方式二:借助mapGetters读取:
    ...mapGetters('countAbout',['bigSum'])
    
  4. 开启命名空间后,组件中调用dispatch

    //方式一:自己直接dispatch
    this.$store.dispatch('personAbout/addPersonWang',person)
    //方式二:借助mapActions:
    ...mapActions('countAbout',{incrementOdd:'jiaOdd',incrementWait:'jiaWait'})
    
  5. 开启命名空间后,组件中调用commit

    //方式一:自己直接commit
    this.$store.commit('personAbout/ADD_PERSON',person)
    //方式二:借助mapMutations:
    ...mapMutations('countAbout',{increment:'JIA',decrement:'JIAN'}),
    

注:使用map的形式比较统一,使用自己手写的方式比较麻烦(getter和与其他形式上有所不同)

模块化:

进行上述操作之后,可以把每个组件分别存储到store文件夹下的新建文件,最后在统一引入到index.js

然后进行暴露

六、路由(非常重要)

  1. 一个路由(route)就是一组映射关系(key - value),多个路由需要路由器(router)进行管理。
  2. 多个路由需要同一个路由器(router)管理

目的实现单页面(spa)应用:页面不刷新但是地址和内容会变,进行局部更新,数据需要通过ajax请求

实现方法:前端路由:更改路径之后,router会自动监测并匹配对应的组件进行显示

​ 后端路由:更改路径后,调用对应的数据去响应前端请求

(1)环境配置

vue-router是vue的一个库专门用于实现spa应用

  1. 安装这个库

    npm i vue-router@3
    

    最新版本vue2不能使用

  2. 引入这个库(main.js中)

    Vue.use(VueRouter)
    
  3. 创建vm的时候可以得到一个新的项:router

(2)基本使用

  1. 创建一个router文件夹,内置一个index文件(该文件专门用于创建router)

  2. 在该文件下引入router

  3. 文件中的写法:

    //引入VueRouter
    import VueRouter from 'vue-router'
    //引入对应的组件
    import About from '../components/About'
    import Home from '../components/Home'
    
    //创建router实例对象,去管理一组一组的路由规则
        //暴露router
    export default new VueRouter({
        //配置路由规则
    	routes:[
    		{
    			path:'/about',//监视对应路径
    			component:About//随着对应路径出现的组件
    		},
    		{
    			path:'/home',
    			component:Home
    		}
    	]
    })
    
    
    
    
  4. 在main.js之中引入路由器

    import router from './router/index'
        
     //vm对象之中配置
        router:router 
    
  5. 使用<router-link></router-link>标签来替换<a></a>>标签进行跳转

    <router-link active-class="active" to="/about">About</router-link>
    

    收到事件时,把地址后面的改为/加上“/about”

    active-class:把当前选中的高亮

  6. 指定组件展示位置

    <router-view></router-view>
    

    注意:

    • 组件的区别:
      路由组件-----------靠路由规则进行匹配展示的组件 放在pages文件加中

      一般组件-----------自己写结构,注册的组件 放到components文件夹中

    • 整个应用都只有一个路由器(

      r

      o

      u

      t

      e

      r

      router),但是有多个路由规则(

      routerroute)每个组件都有一个存储着自己的路由信息

    • 不用的路由组件被销毁了

(4)嵌套路由

导航项,下还有导航项

使用children项配置子路由

子路由要写成数组,因为可能有多个子路由

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

注意前端要写完整路径

<router-link to="/home/news">News</router-link>

(5)路由传参

给路由组件传递参数

<!-- 跳转并携带query参数,to的字符串写法 -->
不常使用
<router-link :to="`/home/message/detail?id=${vc.id}&title=${vc.title}`">跳转</router-link>
				
<!-- 跳转并携带query参数,to的对象写法 -->
<router-link 
	:to="{
		path:'/home/message/detail',           //跳转地址
		query:{                                //传递数据
		   id:666,
            title:'你好'
		}
	}"
>跳转</router-link>

接收参数

$route.query.id
$route.query.title

(6)路由命名

简化跳转时的写法

  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>
    

(7)params参数

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

    {
    	path:'/home',
    	component:Home,
    	children:[
    		{
    			path:'news',
    			component:News
    		},
    		{
    			component:Message,
    			children:[
    				{
    					name:'xiangqing',
    					path:'detail/:id/:title', //使用占位符声明接收params参数,告诉从detail之后就是路由的传参了
    					component:Detail
    				}
    			]
    		}
    	]
    }
    
  2. 传递参数

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

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

  3. 接收参数:

    $route.params.id
    $route.params.title//占位符的名称
    

params与query在实际开发之中都常用

query------------------疑问询问

params----------------参数、参数个数

(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
            //在传入组件之中使用props['id','title'],之后就可以直接写id和title属性了
		}
	}
}

(9)<router-link>的replace属性

历史记录的默认操作模式:堆栈的push模式

还有一种操作就是replace:用新的对当前的进行替换,历史记录始终只有一条,所以不可以前进后退(登录界面可以考虑使用这个,避免重复提交表单)

replace模式的开放方式:

<router-link replace .......>News</router-link>

(10)编程式,路由导航

不使用router-link进行路由导航

需求:

因为router-link最终会被解析为a标签,如果原来是别的标签进行跳转则会破坏结构

多少秒后自动跳转

  1. 具体编码:

    //$router的两个API
    //封装成一个函数,放到methods里面,在外面进行调用即可
    
    
    this.$router.push({
    	name:'xiangqing',
    		params:{
    			id:xxx,
    			title:xxx
    		}//可以携带参数
    })
    
    this.$router.replace({
    	name:'xiangqing',
    		params:{
    			id:xxx,
    			title:xxx
    		}
    })
    
    //另外三个API
    this.$router.forward() //前进
    this.$router.back() //后退
    this.$router.go() //可前进也可后退,传入一个正数,则前进正数所对应的的步数,传入一个负数则反之
    

(11)缓存式路由

对路由的完善

应用场景:切换组件之后,仍然保存数据(现实场景之中很实用)

<keep-alive include="News"> //include指定要保存对象的组件名
    <router-view></router-view>
</keep-alive>

//同时指定多个的方法
<keep-alive :include="['News','massege']"> //include指定要保存对象的组件名(加:之后写成数组)
    <router-view></router-view>
</keep-alive>

指定的组件在切换的时候保持挂载不会被销毁

注意:

  • 要缓存的名字要写的是组件名
  • 要包裹在所在组件展示的 <router-view></router-view>之外

(12)两个新的生命周期钩子

路由组件独有

  1. activated路由组件被激活时触发。
  2. deactivated路由组件失活时触发。

使用方法与正常的相同

(13)路由守卫

  1. 作用:对路由进行权限控制(当满足某些条件下才可以点开)

  2. 分类:全局守卫、独享守卫、组件内守卫

  3. 使用前先用一个const接住创建的对象,然后并不在对象前直接暴露,而是在配置完路由守卫之后,在 export default 对象名

  4. 两个API

    • beforeEach:初始化时和每次路由切换之前调用的函数

      三个收到的对象:

      to------去哪

      to.path----------可以获得想要跳转的页面的路径,可以用于路径判断

      from-------来自哪里(目前所处的位置)

      next()-------放行

    • afterEach:

  5. 配置项meta

    路由元信息,可以在这里面放置几组bool值来统一配置路由守卫的判断信息,也可以放置一些title名

    常常起名为:isAuth

  6. 全局守卫:

    //注:router是自己取的对象名
    //全局前置守卫:初始化时执行、每次路由切换前执行
    router.beforeEach((to,from,next)=>{
       
    	console.log('beforeEach',to,from)
    	if(to.meta.isAuth){ //判断当前路由是否需要进行权限控制,未定义就是false
    		if(localStorage.getItem('school') === 'atguigu'){ //权限控制的具体规则
    			next() //放行
    		}else{
    			alert('暂无权限查看')
    			// next({name:'guanyu'})
    		}
    	}else{
    		next() //放行
    	}
    })
    
    //全局后置守卫:初始化时执行、每次路由切换后执行,没有next
    //常常用于改变页签(title)
    router.afterEach((to,from)=>{
    	console.log('afterEach',to,from)
    	if(to.meta.title){ 
    		document.title = to.meta.title //修改网页的title(从跳转到的meta上获取)
    	}else{
    		document.title = 'vue_test'
    	}
    })
    
  7. 独享守卫:

    写在路由之中,只对所在的路由负责

    独享路由守卫只有前置没有后置

    beforeEnter(to,from,next){
    	console.log('beforeEnter',to,from)
    	if(to.meta.isAuth){ //判断当前路由是否需要进行权限控制
    		if(localStorage.getItem('school') === 'atguigu'){
    			next()
    		}else{
    			alert('暂无权限查看')
    			// next({name:'guanyu'})
    		}
    	}else{
    		next()
    	}
    }
    
  8. 组件内守卫:

    写在组件内,仔细揣摩触发的时机,不要简单的理解为前后

    //进入守卫:通过路由规则,进入该组件之前被调用,一定要写next()放行
    beforeRouteEnter (to, from, next) {
    },
    //离开守卫:通过路由规则,离开当前组件之前被调用
    beforeRouteLeave (to, from, next) {
    }
    

(14)路由的两种工作模式

  1. 关于hash

    • 对于一个url来说,什么是hash值?—— #及其后面的内容就是hash值。

    • hash值不会包含在 HTTP 请求中,即:hash值不会带给服务器。

  2. hash模式:

    1. 地址中永远带着#号,不美观 。
    2. 若以后将地址通过第三方手机app分享,若app校验严格,则地址会被标记为不合法。
    3. 兼容性较好,
  3. history模式:

    1. 地址干净,美观 。
    2. 兼容性和hash模式相比略差,进行网络请求的时候(比如在一个页面进行刷新),会把所有的地址值都当做地址去请求而导致404,而hash模式不会出现这种情况
    3. 应用部署上线时需要后端人员支持解决刷新页面服务端404的问题。npm上有对应的connect-history-api-fallback中间件可以专门解决node上的这个问题,neginx也可以解决
  4. 更改的方式

    给路由器添加配置项 mode

    new VueRouter({
        mode:'history'//history模式
         mode:'hash'//默认的模式
    })
    
  5. 项目上线问题

    不能直接上线,要经过一次打包生成最纯粹的.html.css.js文件

    执行build命令即可

    npm run build
    

    生成的文件叫做dist

    生成的页面要放到服务器上进行部署才可以

    不能直接打开

dist--------------------打包压缩

七、Vue UI组件库

  1. 移动端常见UI库

    • Vant https://youzan.github.io/vant
    • Cube UI https://didi.github.io/cube-ui
    • Mint UI http://mint-ui.github.io
    • NUT UI
  2. PC端常用组件库

    • Element UI https://element.eleme.cn
    • IView UI https://www.iviewui.com
  3. Element UI

    按照官网组件中的办法进行全部引入

    1. 安装
    2. 引入组件库
    3. 引入全部样式
    4. 应用

    这样引入非常的大,因为所有都进行了注册

    进行按需引入

    快速上手->按需引入->GitHub->babel-plugin-component

    安装开发依赖

npm install babel-plugin-component -D

找到babel.config.js不要删去原来的,而是在原来的基础上进行追加

{
  "presets": [["@babel/preset-env", { "modules": false }]],
      //注意:这里的配置与官网上不一致
  "plugins": [
    [
      "component",
      {
        "libraryName": "element-ui",
        "styleLibraryName": "theme-chalk"
      }
    ]
  ]
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3xKYUpn0-1650258889175)(C:\Users\HP\AppData\Roaming\Typora\typora-user-images\image-20220409224244382.png)]

引入其他组件也是相同的办法

样式会自动加上,不用引入了

四、用到的js语法

  1. event.traget---------------------------------可以指向触发点击事件的按钮的属性

  2. event.keycode------------------------------得到某个按键对应的按键编号

  3. const arr=value.split(’-’)-------------------把value按照’-'拆分成几个数组,arr[0]是第一数组,以此类推

  4.  setTimeout(()=>{
       				代码片段
                        },1000)
    

​ 延迟1s之后执行代码

  1. 箭头函数没有自己的this,会向外一层找this

  2. math.random()-------------------------------随机生成一个0到1内的随机数(包括0但是不包括1)

  3. math.floor()------------------------------------对所给的数进行向下取整

    结合6可以生成一个范围内的随机数

    math.floor(math.random()*3)        //生成0到2内的一个随机整数
    
    • 有关数组操作的函数
  4. 数组名.unshift(元素名)-----------------------------在数组之前加入一个元素、

  5. 数组名.push(元素名)--------------------------------

  6. 数组名.pop(元素名)

  7. 数组名.shift(元素名)

  8. 数组名.splice(元素名)

  9. 数组名.sort(元素名)

  10. 数组名.reverse(元素名)

  11. JSON.stringify(数据)------------------------------------把数据转化为JSON数组

  12. debugger--------------------------------------------------在这里设置一个断点(开了控制面板才有用)

  13. clearInterval()----------------------------------------------停止循环

  14. 暴露的三种方法:

    • 默认暴露

      暴露方法:

      export default 暴露对象

      引入方法:

      import 暴露对象 from ’文件地址‘

    • 分别暴露

      暴露方法:

      export 暴露对象

      引入方法:

      import {暴露对象} from ‘文件地址’

  15. nanoid生成全球唯一的一串编码常用来做id

    安装这个库

    npm i nanoid

    使用分别暴露的引入方式进行引入

    import {nanoid} from ‘nanoid’

    使用

    id:nanoid()即可

  16. 数组名.foeEach((单项名)=>{

    })

    对数组进行遍历,每经过一个数,执行一遍{}中的内容

  17. 数组名.filter((单项名)=>{

    returen todo.id !== id

    })

    把id不等于传入的id的项进行返回

    只有返回值为真的时候才会返回当前项

  18. reduce 专门用于条件统计

    数组.reduce((pre,current)=>{

    return pre+ (current.doen?1:0)

    },0)

    第一次调用的时候pre是指定的0

    第二次调用的时候pre是上一次调用的返回值,依次类推

    数组有多长就调用几次

    最后一次的调用的返回值作为函数的返回值

    current为当前的数组项

    所以上述代码实现的是判断数组之中值为1的项

  19. JSON.stringify()

    将对象转化为字符串(可以是数组包对象)

  20. JSON.parse()

    将字符串变为对象(可以是数组包对象)

  21. {…对象1,…对象2}

    用对象2替换对象1中同名属性的属性值,如果没有的则保持

  22. clearInterval(计时器名)----------------------关闭计时器

五、用到的css语法

overflow:auto---------------------------------添加一个滚动条

scroll---------------------------------------------滚动事件(滚动条发生滚动)

wheel--------------------------------------------滚动事件(鼠标的滚轮发生改变)

click---------------------------------------------点击事件

style=“opacity”------------------------------透明度

六、用到的HTML语法

在输入框中显示默认的text

<hr/>分隔线

事件:

  1. 点击事件:click
  2. 改变事件:change
  3. 失去焦点:blur

alert(‘文本’):弹窗提示文本

confirm(‘文本’):弹窗提示文本,确定返回真,返回返回假

七、注意

  • 注意区分虚拟DOM与真实DOM,两者不在一层

  • 第三方成型的资源一般都不放到.vue文件之中,而是新建一个assets文件夹,在里面在分门别类的放置

    如果没有使用到第三方则在App.vue之中进行引入, 如果用到了则在inde.html之中使用link标签引入

  • 数据驱动页面的展示

  • 空数组,未定义是false

  • flex页面布局
    .config.js不要删去原来的,而是在原来的基础上进行追加

{
  "presets": [["@babel/preset-env", { "modules": false }]],
      //注意:这里的配置与官网上不一致
  "plugins": [
    [
      "component",
      {
        "libraryName": "element-ui",
        "styleLibraryName": "theme-chalk"
      }
    ]
  ]
}

[外链图片转存中…(img-3xKYUpn0-1650258889175)]

引入其他组件也是相同的办法

样式会自动加上,不用引入了

四、用到的js语法

  1. event.traget---------------------------------可以指向触发点击事件的按钮的属性

  2. event.keycode------------------------------得到某个按键对应的按键编号

  3. const arr=value.split(’-’)-------------------把value按照’-'拆分成几个数组,arr[0]是第一数组,以此类推

  4.  setTimeout(()=>{
       				代码片段
                        },1000)
    

​ 延迟1s之后执行代码

  1. 箭头函数没有自己的this,会向外一层找this

  2. math.random()-------------------------------随机生成一个0到1内的随机数(包括0但是不包括1)

  3. math.floor()------------------------------------对所给的数进行向下取整

    结合6可以生成一个范围内的随机数

    math.floor(math.random()*3)        //生成0到2内的一个随机整数
    
    • 有关数组操作的函数
  4. 数组名.unshift(元素名)-----------------------------在数组之前加入一个元素、

  5. 数组名.push(元素名)--------------------------------

  6. 数组名.pop(元素名)

  7. 数组名.shift(元素名)

  8. 数组名.splice(元素名)

  9. 数组名.sort(元素名)

  10. 数组名.reverse(元素名)

  11. JSON.stringify(数据)------------------------------------把数据转化为JSON数组

  12. debugger--------------------------------------------------在这里设置一个断点(开了控制面板才有用)

  13. clearInterval()----------------------------------------------停止循环

  14. 暴露的三种方法:

    • 默认暴露

      暴露方法:

      export default 暴露对象

      引入方法:

      import 暴露对象 from ’文件地址‘

    • 分别暴露

      暴露方法:

      export 暴露对象

      引入方法:

      import {暴露对象} from ‘文件地址’

  15. nanoid生成全球唯一的一串编码常用来做id

    安装这个库

    npm i nanoid

    使用分别暴露的引入方式进行引入

    import {nanoid} from ‘nanoid’

    使用

    id:nanoid()即可

  16. 数组名.foeEach((单项名)=>{

    })

    对数组进行遍历,每经过一个数,执行一遍{}中的内容

  17. 数组名.filter((单项名)=>{

    returen todo.id !== id

    })

    把id不等于传入的id的项进行返回

    只有返回值为真的时候才会返回当前项

  18. reduce 专门用于条件统计

    数组.reduce((pre,current)=>{

    return pre+ (current.doen?1:0)

    },0)

    第一次调用的时候pre是指定的0

    第二次调用的时候pre是上一次调用的返回值,依次类推

    数组有多长就调用几次

    最后一次的调用的返回值作为函数的返回值

    current为当前的数组项

    所以上述代码实现的是判断数组之中值为1的项

  19. JSON.stringify()

    将对象转化为字符串(可以是数组包对象)

  20. JSON.parse()

    将字符串变为对象(可以是数组包对象)

  21. {…对象1,…对象2}

    用对象2替换对象1中同名属性的属性值,如果没有的则保持

  22. clearInterval(计时器名)----------------------关闭计时器

五、用到的css语法

overflow:auto---------------------------------添加一个滚动条

scroll---------------------------------------------滚动事件(滚动条发生滚动)

wheel--------------------------------------------滚动事件(鼠标的滚轮发生改变)

click---------------------------------------------点击事件

style=“opacity”------------------------------透明度

六、用到的HTML语法

在输入框中显示默认的text

<hr/>分隔线

事件:

  1. 点击事件:click
  2. 改变事件:change
  3. 失去焦点:blur

alert(‘文本’):弹窗提示文本

confirm(‘文本’):弹窗提示文本,确定返回真,返回返回假

七、注意

  • 注意区分虚拟DOM与真实DOM,两者不在一层

  • 第三方成型的资源一般都不放到.vue文件之中,而是新建一个assets文件夹,在里面在分门别类的放置

    如果没有使用到第三方则在App.vue之中进行引入, 如果用到了则在inde.html之中使用link标签引入

  • 数据驱动页面的展示

  • 空数组,未定义是false

  • flex页面布局