• 第02篇_Vue框架

    第01章_Vue基础

    第一节vue简介

    1. vue是什么?

    Vue (读音 /vjuː/,类似于 view) 是一套用于构建用户界面渐进式JavaScript框架。其借鉴了Angular和React的设计思想,采用组件化模式和声明式编码,提高代码复用率和开发效率,且无需直接操作DOM。

    Vue的作者为美籍华人尤雨溪,目前主流的版本为2016年10月发布的vue2.x,最新版本为2020年发布的Vue3.x。

     

    2. MVVM模式

    MVVM(Model-View-ViewModel)是传统MVC(Model-View-Controller)模式的改进版,将其中的View 的状态和行为抽象化,将视图 UI 和业务逻辑分开。Vue的设计也借鉴了这种思想,并实现了数据的双向绑定。

    image-20220319115932990

     

     

    3. 入门案例

    Vue可以直接在HTML页面中引入使用,也可以使用下一章将讲解的Vue-Cli构建复杂的单页面应用,直接引入的方式如下:

    下面准备Vue所使用的容器,一般为一个普通的div标签。容器内部使用插值表达式从Vue实例中获取数据(后文将会详细讲解)。

    最后创建Vue实例,并与容器进行绑定。

    完整的代码示例如下:

    使用浏览器打开页面看一下吧!

    image-20220319111436037

     

     

    第二节 Vue实例与模板语法

    1. Vue实例

    Vue实例是整个Vue应用的核心,一般来说,一个应用只有一个Vue实例,并且与容器一一对应。此外,Vue实例必须与容器绑定后,Vue才会开始工作,而不是仅引入vue.js。实例与容器绑定的方式如下:

    Vue中的数据通过data属性配置,data属性有对象形式函数形式两种写法:

    注意:关于Vue中的函数是否写为箭头函数的原则

    1. 由Vue管理的函数,不要写箭头函数,一旦写了箭头函数,this就不再是Vue实例了。如钩子函数等。

    2. 不是由Vue管理的函数,一般写成箭头函数,向外查找this。如钩子函数中的定时器回调、ajax的回调、Promise的回调函数等。

     

    2. Vue模板语法

    Vue的模板语法有两大类,第一类为插值语法,使用{{xxx}}形式,第二类为指令语法,使用v-xxx开头。

    1. 插值语法:

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

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

    2. 指令语法:

      • 功能:用于解析标签(包括:标签属性、标签体内容、绑定事件.....)。

      • 举例:v-bind:href="xxx" 或 简写为 :href="xxx",xxx同样要写js表达式,且可以直接读取到data中的所有属性。

    扩展:JS表达式

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

      a a+b demo(1) x === y ? 'a' : 'b'

    2. js代码(语句):一般用作流程控制。

      if(){} for(){} continue return

     

     

    第三节 数据绑定

    1. 单向绑定与双向绑定

    Vue有两种数据绑定的方式,第一种为单向绑定(v-bind),第二种为双向绑定(v-model)。

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

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

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

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

     

    2. 扩展:关于数据代理

    为什么插值语法能直接从this(vm实例)读取配置data中的属性?

    答:因为vue对管理的数据使用Object.defineProperty进行了数据代理

    1. 何为数据代理?通过一个对象代理对另一个对象中属性的操作(读/写)。

    2. Vue中的数据代理:通过vm对象来代理data对象中属性的操作(读/写),从而更加方便的操作data中的数据。

    3. Vue数据代理的基本原理:通过Object.defineProperty()把data对象中所有属性添加到vm上,为每一个添加到vm上的属性,都指定一个getter/setter,在getter/setter内部去操作(读/写)data中对应的属性。

    4. 关于Object.defineProperty():

      可以看到,代理对象中,本身的y属性不变,但新增的x属性,增加了get和set方法!

      image-20220319121852397

       

     

    第四节 事件处理

    1. 事件的基本使用

    在Vue中,使用v-on:xxx="事件回调"@Xxx="事件回调" 的形式绑定事件,其中xxx是事件名,事件的回调一般为配置在methods对象中的函数,当然,也可以是简短的JS代码。

    注意:

    1. methods中配置的函数都是vue所管理的函数,一般不配置为箭头函数,否则this就不是vm/vc了。

    2. @click="demo" 和 @click="demo($event)" 效果一致,但后者可以继续传参。

     

    2. 事件修饰符

    事件修饰符主要用于控制事件触发的相关行为,使用.号连接在事件之后,可以连续使用。常用的事件修饰符如下:

    事件修饰符行为
    prevent阻止默认事件
    stop阻止事件冒泡
    once事件只触发一次
    capture使用事件的捕获模式
    self只有event.target是当前操作的元素时才触发事件
    passive事件的默认行为立即执行,无需等待事件回调执行完毕

     

    3. 键盘事件

    键盘按下和抬起会分别触发@keydown@keyup事件,可以使用修饰符声明指定的按键才触发,如按下回车触发的事件配置为@keydown.enter="回调”。其它一些常用的按键如下:

    按键中文名别名键码
    回车enter13
    删除(退格)delete 
    退出esc 
    空格space 
    换行tab 
    上/下/左/右up/down/left/right 

    如需使用无内置别名的按键,可以直接拿键码来配置(但不推荐),或者使用Vue.config.keyCodes.自定义键名 = 键码的形式提前绑定自定义别名,但注意要转为kebab-case(短横线命名)的形式。

    一些特殊的修饰键(ctrl/alt/shift/meta)可配合@keyup事件配置为组合键,按下修饰键的同时,再按下其他键,随后释放其他键,事件才被触发,如Ctrl+C、Ctrl+Alt+M等。注意,这些特殊的修饰键依然可以配合@keydown事件在按下时直接触发。

     

    第五节 计算属性与监视

    1. 计算属性-函数简写形式

    计算属性是指通过其它属性经过一系列计算而得来的属性,与methods相比,内部有缓存机制,效率更高,调试方便。其配置在computed下,值为一个对象,以键值对的形式存储多个计算属性。如果只需要对计算属性进行读操作,并且不需要配置其它属性,那么可以直接简写成函数形式,其内容与get方法一致。

    注意:计算属性在什么时候被调用?

    1. 初次读取时会执行一次。

    2. 当依赖的数据发生改变时会被再次调用。

     

    2. 计算属性-对象配置形式

    如果需要对计算属性进行修改或配置其它属性时,则需要使用对象的形式写完整版的计算属性配置。

    提示:

    1. 计算属性也会被Vue使用Objcet.defineproperty进行数据代理,因此也能直接在vm身上看见。

     

    3. 监视属性-函数简写形式

    监视属性指对一个属性进行监视,当被监视的属性发生变化时, 回调函数自动调用, 进行相关操作。监视属性有两种写法,可以在创建Vue实例时传入watch配置,也可以在之后通过vm.$watch配置。

     

    注意:computed和watch之间的区别:

    1. computed能完成的功能,watch都可以完成。

    2. watch能完成的功能,computed不一定能完成,例如:watch可以进行异步操作。

     

    4. 监视属性-对象配置形式

    如果需要对监视的属性进行深度监视或进行其它配置时(如在初始化时执行一次),可以采用监视属性的对象配置形式。

     

     

    第六节 动态绑定样式

    CSS样式一般通过classstyle属性引入,在vue中动态绑定样式的写法如下:

     

    1. class样式绑定

    class样式绑定的写法为:class="xxx" ,其中xxx可以是字符串对象数组

     

    2. style样式绑定

    style样式绑定的写法为:style="xxx" ,其中xxx可以是样式对象样式对象数组

     

     

    第七节 条件渲染与列表渲染

    1. 条件渲染

    Vue中的条件渲染有两种方式,第一种为v-if指令,将不展示的DOM元素直接移除,适用于切换频率较低的场景。第二种为v-show指令,将不展示的DOM元素通过display:none样式隐藏,适用于切换频率较高的场景。

    1. v-if:

      • v-if="表达式"

      • v-else-if="表达式"

      • v-else="表达式"

    2. v-show:

      • v-show="表达式"

    注意:

    1. v-if可以和:v-else-if、v-else一起使用,但要求结构不能被“打断”。

    2. 使用v-if的时,元素可能无法获取到,而使用v-show一定可以获取到。

    3. v-if可以与template的配合使用,将多个标签同时包裹,且不会破坏DOM结构。

     

     

    2. 列表渲染

    Vue中使用v-for指令可重复渲染某个标签,形成动态列表。语法格式为v-for="(item, index) in xxx" :key="yyy"。xxx可以是数组对象字符串等可遍历的元素,也可以是一个数值,用于指定遍历的次数;yyy默认为列表的索引index,下节将会详细讲解。

     

    3. key的使用

    Vue中进行列表渲染时,一般会指定一个key值,key是虚拟DOM对象的标识,当数据发生变化时,Vue会根据“新数据”生成“新的虚拟DOM”,随后Vue进行“新虚拟DOM”与“旧虚拟DOM”的差异比较,比较规则如下:

    一般来说,如果仅对数据进行列表展示,而不涉及对数据的逆序添加逆序删除等破坏顺序操作,则可以直接使用列表的索引index作为key。否则,最好使用每条数据的唯一标识作为key,比如id、手机号、身份证号、学号等唯一值。

    注意:用index作为key可能会引发的问题

    若对数据进行逆序添加、逆序删除等破坏顺序操作,会产生没有必要的真实DOM更新,虽然界面显示没问题,但效率低,不推荐。如果结构中还包含输入类的DOM(如input框),则还会产生异常的DOM更新 ,造成界面错乱。

    下面是分别使用index作为key和使用id作为key的DOM解析流程对比,可放大图片进行查看。

    index作为key id作为key

     

    4. 列表过滤与排序

    列表过滤与排序一般使用计算属性实现,直接展示处理后的列表数据。当然,计算属性可以实现的使用watch也可以做到。

     

    5. 关于数组元素替换

    数组的元素不能使用下标进行替换,如arr[0]={id:001,name:’马冬梅’}。这样虽然更改了Vue实例中的数据,但Vue无法检测到,界面不会正常刷新。我们可以使用下列指定API来操作,Vue会进行拦截处理。

    API作用
    push()/unshift()向数组的末尾/开头添加一个或多个元素,并返回新的长度
    pop()/shift()删除并返回数组的最后一个/第一个元素
    sort()对数组的元素进行排序。
    reverse()颠倒数组中元素的顺序。
    splice()从已有的数组中返回选定的元素

     

    6. 扩展:关于数据监测

    在创建Vue实例时,Vue会对data配置中的数据使用Object.defineProperty进行数据代理,监测后续数据的改变。特别的,对于数组类型的数据,通过代理数组操作API的方式来实现,因此数组元素需要通过上述指定API来进行操作。

    如果需要在Vue实例创建后添加可以被Vue监测的响应式数据,可以通过Vue.set(target,propertyName/index,value)vm.$set(target,propertyName/index,value)的方式。

    注意:

    1. Vue.set() 和 vm.$set() 不能给vm 或 vm的根数据对象(_data)添加属性!

     

     

    第八节 收集表单数据

    Vue提供了v-model双向绑定的方式来收集表单数据。

    1. 普通文本框(<input type="text"/>):收集用户输入的value值。与之类似的还有密码框(type="password")、数值框(type="number")、选择框(select)、文本域(textarea)等。

    2. 单选框(<input type="radio"/>):收集用户所选项的value值,需要提前给标签配置value属性。

    3. 复选框(<input type="checkbox"/>):

      • 如果标签配置了value属性,则可将选中项的value值收集为数组,但要求v-model绑定变量的初始值为数组。

      • 此外,还可以收集布尔类型的checked属性。

    此外,v-model还有一些修饰符

    修饰符作用
    number将字符串转为有效的数字
    trim首尾空格过滤
    lazy失去焦点再收集数据,一般用于文本域等。

     

    第九节 过滤器

    过滤器对要显示的数据进行特定格式化后再显示,适用于一些简单逻辑的处理。使用步骤如下:

    1. 注册过滤器:

      • 局部注册:new Vue{filters:{}} ,仅在当前Vue实例可用。

      • 全局注册: Vue.filter(name,callback) ,所有Vue实例可用。

    2. 使用过滤器:

      • 插值语法中使用:{{ xxx | 过滤器名}}

      • 指令语法中使用: v-bind:属性 = "xxx | 过滤器名"

    此外,过滤器支持接收额外的参数,并且可以同时使用多个过滤器。

     

     

    第十节 内置指令与自定义指令

    1. Vue中的内置指令

    指令作用
    v-bind单向绑定解析表达式,可简写为v-bind:xxx可简写为 :xxx。
    v-model双向数据绑定。v-model:value=‘xxx’可简写为v-model=‘xxx’。
    v-for遍历数组/对象/字符串,或遍历指定次数。
    v-on绑定事件监听,v-on=‘xxx’可简写为@Xxxx。
    v-if/v-else-if/v-else条件渲染(动态控制节点是否存存在)
    v-show条件渲染(动态控制节点是否存展示)
    v-text替换所在节点的标签内容。
    v-html替换所在节点的标签内容,并执行HTML解析(注意防止xss攻击)。
    v-cloak与CSS([v-cloak]{display:none;})配合解决插值闪烁问题,在模板解析完成后会自动删除。
    v-once配置的标签仅会被渲染一次,用于优化性能。
    v-pre配置的标签会被跳过解析,Vue不进行管理,加快编译速度。

     

    2. 自定义指令-函数简写形式

    Vue支持自定义指令来实现一些功能,如果你只需要在指令与元素成功绑定时指令所在的模板被重新解析时触发指令,则可以使用指令的函数简写形式,与过滤器类似,也支持局部注册或全局注册。

    1. 局部注册:new Vue({directives{指令名:回调函数}})

    2. 全局注册:Vue.directive(指令名,回调函数)

    如下案例,实现了一个自定义指令v-big-number,功能和v-text功能类似,但会把绑定的数值放大10倍。

    注意:

    1. 指令定义时不加v-,但使用时要加v-。

    2. 指令名如果是多个单词,要使用kebab-case命名方式,不要用camelCase命名。

     

    3. 自定义指令-对象配置形式

    如果需要在指令与元素成功绑定时指令所在元素被插入页面时以及指令所在的模板被重新解析时触发指令并执行不同业务逻辑,可以采用完整版的对象配置形式。对象配置形式也可以进行局部注册或全局注册。

    1. 局部注册:new Vue({directives:{指令名:配置对象}})

    2. 全局注册:Vue.directive(指令名,配置对象)

    配置对象为三个回调函数bindinsertedupdate,分别代表指令的三个执行时机。

    如下案例,定义一个v-fbind指令,和v-bind功能类似,但可以让其所绑定的input元素默认获取焦点。

     

     

    第十一节 vue实例生命周期

    Vue实例生命周期,又名生命周期回调函数、生命周期钩子等,是Vue在关键时刻帮我们调用的一些特殊名称的函数,该类函数的名称不可更改,但函数的具体内容是程序员根据需求编写的。下面是Vue实例生命周期图:

    image-20220320220444820

    最常用的生命周期函数有mountedbeforeDestroy

     

    注意:

    1. 生命周期函数中的this指向是vm 或 组件实例对象。

    2. Vue实例销毁后借助Vue开发者工具看不到任何信息,销毁后自定义事件会失效,但原生DOM事件依然有效。

    3. 一般不会在beforeDestroy操作数据,因为即便操作数据,也不会再触发更新流程了。

     

     

    第十二节 Vue组件化编程

    1. 非单文件组件

    组件化是Vue最大的特性之一,Vue中使用组件的三大步骤:

    1. 定义组件

      • 使用const 变量名 = Vue.extend(options)创建,可简写为const 变量名 = options。其中options和创建Vue实例时传入的那个options几乎一样。但:

        • el不要写(最终所有的组件都要经过一个vm的管理,由vm中的el决定服务哪个容器)。

        • data必须写成函数(避免组件被复用时,数据存在引用关系)。

    2. 注册组件

      • 局部注册:创建Vue或定义组件时传入components选项。

      • 全局注册:通过Vue.component('组件名',组件)进行全局注册。

    3. 使用组件

      • 在合适的位置编写组件标签,如<school></school>(注意:如未使用vue-cli脚手架,请勿使用自闭和标签的形式)。

    此外,可以通过template属性将模板配置在组件内部,还可以使用name属性指定开发者工具中显示的组件名。

    关于组件名:

    1. 组件名可以是首字母小写首字母大写的单个单词(如school、School),也可以是以kebab-case命名或CamelCase命名的多个单词(如my-school、MySchool),但后者(MySchool)需要Vue-Cli脚手架的支持。

    2. 组件名尽可能回避HTML中已有的元素名称,例如:h2、H2都不行。

    3. 可以使用name配置项指定组件在开发者工具中呈现的名字。

    关于VueComponent:

    1. 组件的本质是一个VueComponent构造函数,且不是程序员定义的,是Vue.extend生成的。

    2. 我们只需要写定义好的组件标签,Vue解析时会帮我们创建组件的实例对象,即Vue帮我们执行new VueComponent(options)。

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

    4. 一个重要的内置关系:VueComponent.prototype.__proto__ === Vue.prototype,让组件实例对象(vc)可以访问到 Vue原型上的属性、方法。

      image-20220320231236654

     

    2. 组件嵌套

    Vue组件可以进行嵌套,即组件中还可以使用其它的组件。

    打开开发者工具,可以看到如下的组件架构:

     

    3. 单文件组件

    单文件组件即每个文件只写一个组件,利于维护和管理,实际开发一般为此种形式。如下一个HTML页面(index.html),准备了一个容器。

    在新建一个js文件(main.js)用于创建Vue实例,并在模板中使用App组件。

    App组件(App.vue)是所有组件的父组件,在此组件中使用其它的业务组件。

    下面是业务组件School(School.vue)。

    下面是业务组件Student(Student.vue)。

    注意:在打开index.html时会报Uncaught SyntaxError: Cannot use import statement outside a module错误,原因是浏览器不支持ES6语法,上述代码需要借助后续讲解的Vue-Cli才能运行。

     

     

     

     

    第02章_Vue脚手架

    第一节 初始化脚手架

    Vue 脚手架(@vue/cli)是 Vue 官方提供的标准化开发工具(开发平台),官网地址为: https://cli.vuejs.org/zh/

     

    1. 安装脚手架

    使用NPM安装脚手架@vue/cli的相关命令如下:

    注意:Vue CLI 4.x 需要 Node.js v8.9 或更高版本 (推荐 v10 以上)。

     

    2. 创建项目

    使用脚手架创建项目的相关命令如下,该命令会新建一个文件夹,并进行项目的初始化。

     

    3. 启动项目

    进入项目根目录,使用如下命令启动项目:

     

    4. 目录结构说明

     

     

    vue.js与vue.runtime.xxx.js的区别:

    • 前者是完整版的Vue,包含核心功能 + 模板解析器。

    • 后者是运行版的Vue,只包含核心功能,没有模板解析器。

    因为vue.runtime.xxx.js没有模板解析器,所以不能使用template这个配置项,需要使用render函数接收到的createElement函数去指定具体内容。

     

     

     

    5. 修改默认配置

    1. 导出并查看默认配置:vue inspect > output.js

    2. 修改默认配置:

     

     

    第二节 ref属性与scoped属性

    1. ref属性

    ref属性用于注册引用信息,可应用于原始HTML标签组件标签,作为id的替代者使用。使用步骤如下:

    1. 声明引用:<h1 ref="xxx">.....</h1><School ref="xxx"></School>

    2. 获取:this.$refs.xxx。HTML标签的引用获取的是真实DOM元素,组件的引用获取的是组件实例对象(vc)

     

    2. scoped属性

    scoped用于限制样式的作用范围,使其只在当前组件生效,防止样式冲突。必要时直接在组件的<style>标签添加该样式即可,格式为:<style scoped>

     

     

     

    第三节 props声明(父子组件通信)

    props用于声明组件可接收的外部参数,一般用于父->子通信。声明的方式有三种:

    1. 第一种方式(只接收):props:['name']

    2. 第二种方式(限制类型):props:{name:String}

    3. 第三种方式(限制类型、限制必要性、指定默认值):

    子组件声明可接收的外部参数后,父组件在使用子组件时,可以传递对应的参数,用法为:<Demo name="xxx"/>

    注意:

    1. 子组件中的props应该是只读的,如果进行了修改,Vue会监测到并发出警告信息(浅层次的监测)。如果业务确实需要修改,请先复制一份到data中,去修改data中的那份数据。

    2. 父组件中如果需要传递动态参数,请使用v-bind进行绑定,可简写为<Demo :name="xxx"/>

     

     

     

     

    第四节 混合与插件

    1. 混合

    混合(mixin)是指将外部配置对象与当前组件的配置整合,一般用于抽取公共配置。使用方式如下:

    1. 定义外部配置对象。

    2. 混合外部配置到组件:

      • 全局混合:Vue.mixin(xxx)

      • 局部混合:mixins:['xxx']

     

     

     

     

     

    2. 插件

    Vue插件主要用于扩展Vue的功能,其本质是一个带install方法的对象。在install方法中,可以进行一些Vue的增强,如添加全局过滤器、全局指令、全局混合以及实例方法等。定义格式如下:

     

     

     

     

    第五节 自定义事件(子父组件通信)

    自定义事件一般用于子->父间通信。使用步骤如下:

    1. 子组件在合适的时机触发事件:this.$emit('event01',数据)

    2. 父组件在使用子组件时绑定事件回调,有两种方式:

      • 配置方式:<Demo v-on:event01="test"/>或简写为<Demo @event01="test"/>

      • 代码方式:事先设置子组件的ref属性,然后在父组件中(一般在mounted钩子中)通过$on绑定事件回调。

    3. 父组件可在需要的时候解绑自定义事件:

      • 解绑单个自定义事件:this.$off('event01')

      • 解绑多个自定义事件:this.$off(['event01','event02'])

      • 解绑所有自定义事件:this.$off()

    注意:

    1. 通过this.$refs.xxx.$on('atguigu',事件回调)方式绑定时,该回调需写成箭头函数或者为配置在methods中的普通函数,否则this的指向不会是vc实例。

    2. 绑定事件回调时,若想让自定义事件只能触发一次,可以使用once修饰符,或$once方法。

    3. 组件上也可以绑定原生DOM事件,需要使用native修饰符。

     

     

    提示: 子->父通信也可以通过props声明来实现!!!

    1. 父组件在使用子组件时传递一个回调函数,用于处理父组件的一些数据。

    2. 子组件声明props,接收父组件传递过来的回调函数,在合适的时机执行该回调函数。

     

     

    第六节 全局事件总线(任意组件通信)

    全局事件总线($bus)由自定义事件衍生而来,一般用于任意组件间通信。使用步骤如下:

    1. 安装全局事件总线:一般选择Vue组件作为通信的中间组件,因为它全局唯一且所有组件均可访问。

    2. 使用总线发送数据:this.$bus.$emit('xxxx',数据),使用通信组件(vm)的$emit方法触发特定事件,并附带业务数据。

    3. 从总线获取数据:在总线上绑定所关注事件的回调,当关注的事件触发时,自动调用回调函数处理收到的数据。

    注意:一般来说,最好在beforeDestroy钩子中,用$off去解绑当前组件所用到的事件。

     

     

     

    提示:有关事件触发、绑定及解绑的相关操作请参考上一节:自定义事件!!!

     

     

     

     

    第七节 消息订阅与发布(任意组件通信)

    消息订阅与发布是通过第三方库实现的任意组件间通信,在其它类型的框架中也可使用。使用步骤如下:

    1. 安装:npm i pubsub-js

    2. 引入: import pubsub from 'pubsub-js'

    3. 发布:pubsub.publish('xxx',数据)

    4. 订阅:this.pid = pubsub.subscribe('xxx',this.demo)

    注意:一般来说,最好是在beforeDestroy钩子中,用pubsub.unsubscribe(pid)取消订阅

     

     

     

    第八节 过度与动画

    Vue通过一些标签和属性在DOM插入、更新或移除时,动态增删一些样式,以达到动画效果。

     

    1. 单个标签的过度与动画

     

    2. 多个标签的过度与动画

     

    3. 第三方过度与动画

    1. 安装:npm install animate.css --save

    2. 引入:import 'animate.css'

    3. 使用:通过name、enter-active-class、leave-active-class等属性指定动画样式。

     

    第九节 插槽(slot)

    插槽用于父组件向子组件插入动态HTML结构,也是一种父子间组件间通信的方式。使用步骤如下:

    1. 子组件定义插槽:

    2. 父组件往插槽塞入HTML结构:

    注意:

    1. 如果子组件只有一个插槽,则可以省略name属性(插槽名称),同时父组件也无需指定slot属性。

    2. 可以使用template标签同时包裹多个标签塞入,并且不会破坏解析后的HTML结构。

    3. slot="slot01"也可写为v-slot:slot01

     

    1. 基本使用

     

     

    2. 带数据的插槽

    带数据的插槽指将子组件内部的数据通过插槽传递给父组件,父组件使用该数据来生成特定的HTML结构并塞入插槽。

     

     

     

     

    扩展1: 浏览器存储(webStorage)

    浏览器存储(webStorage)用于在客户端保存少量的网页数据(约5MB),根据数据的类型可分为会话存储(SessionStorage)本地存储(LocalStorage)

    常用的API如下:

    提示:在实际开发中,一般将数据转为JSON存入,转换方式如下:

    • Object -> Json:JSON.stringify(obj)。如果obj为null,则转换结果为'null'。

    • Json -> Object:JSON.parse(jsonStr)。如果jsonStr为null,则解析结果为null。

     

     

    扩展2:Ajax请求(axios)

    1. 安装:npm install axios

    2. 引入:import axios from 'axios'

    3. 使用:

    更多资料请参考官方文档:http://www.axios-js.com/

     

    扩展3:nextTick钩子

    如果某些函数需要在DOM更新结束后再执行,则可以使用nextTick注册回调函数。语法格式为:this.$nextTick(回调函数)

    提示:自定义指令的inserted(element,binding){}配置也有类似的效果!

     

    扩展4:脚手架代理配置

    脚手架代理服务器一般是前端人员为了解决跨域问题而配置(更好的方式是后端配置响应头或使用Nginx作代理)。创建或修改根目录下的vue.config.js文件,配置如下:

     

    访问方式如下:

     

     

     

    第03章_Vue插件

    第一节 Vuex插件

    1. Vue插件简介

    Vuex插件是一个用于实现集中式状态(数据)管理的Vue插件,对vue应用中多个组件的共享状态(数据)进行集中式的管理(读/写),也是一种组件间通信的方式,且适用于任意组件间通信。Github地址为:https://github.com/vuejs/vuex

    image-20220324223302759

     

    2. 搭建Vuex环境

    1. 安装vuex:npm install vuexnpm install vuex@3

      注意:如果出现Uncaught TypeError: Object(...) is not a function at resetStoreState (vuex.esm-browser.js?5502:1或类似错误,可能是Vue 2.x和Vuex 4.x版本不匹配导致。先卸载npm uninstall vuex,再继续安装匹配的旧版本npm install vuex@3

    2. 创建src/store/index.js文件,写入如下store配置。

    3. main.js中创建vm时传入store配置项(注意:已在上方配置中使用了插件)。

     

    3. Vuex的基本使用

    1. 修改store.js文件,初始化state数据,以及配置actionsmutations中的操作函数。

    2. 组件中读取vuex中的数据:$store.state.sum

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

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

     

    4. getters的使用

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

    2. store.js中追加getters配置

    3. 组件中读取数据:$store.getters.bigSum

     

    5. 四个map方法的使用

    1. mapState方法:用于帮助我们映射state中的数据为计算属性。

    2. mapGetters方法:用于帮助我们映射getters中的数据为计算属性。

    3. mapActions方法:用于帮助我们生成与actions对话的方法,即:包含$store.dispatch(xxx)的函数。

    4. mapMutations方法:用于帮助我们生成与mutations对话的方法,即:包含$store.commit(xxx)的函数。

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

     

    6. 模块化+命名空间

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

    2. 修改store.js将原来的大配置进行拆分:

    3. 开启命名空间后,组件中读取state数据:

    4. 开启命名空间后,组件中读取getters数据:

    5. 开启命名空间后,组件中调用dispatch

    6. 开启命名空间后,组件中调用commit

     

     

    第二节 VueRouter插件

    1. VueRouter插件简介

    VueRouter插件是一个用于实现单页面应用(SPA)的Vue插件,主要由路由器(router)路由(route)配置组成。

     

    2. 搭建VueRouter环境

    1. 安装vue-router:npm i vue-router

      注意: 如果出现Uncaught TypeError: Object(...) is not a function at resetStoreState (vuex.esm-browser.js?5502:1或类似错误,可能是Vue 2.x和Vue-Router的版本不匹配,先卸载npm uninstall vue-router后安装旧版本npm install vue-router@3.5.2即可。

    2. 创建src/router/index.js文件,写入如下路由器(router)配置。

    3. main.js中创建vm时引入和使用VueRouter插件,并传入路由器配置。

       

    3. VueRouter的基本使用

    1. 切换地址栏路径:使用<router-link>标签替换原<a>标签,当该标签被点击时,会根据to属性的值修改地址栏路径,路由器检测到路径改变后,切换为指定的路由组件(提示:可通过active-class属性配置激活样式)。

    2. 指定组件展示位置:使用<router-view>标签指定路由组件展示在哪个位置。

    注意:

    1. 一般组件通常存放在components文件夹,而路由组件通常存放在pages文件夹。

    2. 通过切换,“隐藏”了的路由组件,默认是被销毁掉的,需要的时候再去挂载。

    3. 每个组件都有自己的$route属性,里面存储着自己的路由信息。

    4. 整个应用只有一个router,可以通过组件的$router属性获取到。

     

    4. 多级路由

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

    2. 切换地址栏路径(注意:要写完整路径):

     

    5. 路由的query参数

    1. 点击切换时传递query参数。

    2. 接收参数:通过路由组件自身特有的$route属性获取query参数。

     

    6. 路由名称

    路由名称即给某个路由规则起一个方便使用的名称,可以简化路由的跳转。

    1. 给路由规则命名:通过name属性指定路由规则的名称。

    2. 简化跳转:

     

    7. 路由的params参数

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

    2. 传递参数

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

    3. 接收参数:通过路由组件自身特有的$route属性获取query参数。

     

    8. 路由的props配置

    路由的props配置让路由组件更方便的收到参数。

     

    9. <router-link>标签的replace属性

    1. 作用:控制路由跳转时操作浏览器历史记录的模式。

    2. 浏览器的历史记录有两种写入方式:分别为push(默认)replace

      • push:追加历史记录。

      • replace:替换当前记录。

    3. 如何开启replace模式:<router-link replace .......>News</router-link>

     

    10. 编程式路由导航

    1. 作用:不借助<router-link>实现路由跳转,让路由跳转更加灵活。

    2. 具体编码:

     

    11. 路由组件保活

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

    2. 具体编码:在<router-view>标签外部包裹一层<keep-alive include="组件列表">标签。其中include属性指需要保活的路由组件列表,多个组件间通过逗号分隔。

     

    12.两个新的生命周期钩子

    1. 作用:路由组件所独有的两个钩子,用于捕获路由组件的激活状态。

    2. 具体名字:

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

      2. deactivated路由组件失活时触发。

       

    13. 路由守卫

    1. 作用:对路由进行权限控制。

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

    3. 全局守卫:

    4. 独享守卫:

    5. 组件内守卫:

     

    14. 路由器的两种工作模式

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

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

    3. hash模式(默认):

      • 地址中永远带着#号,不美观 。

      • 若以后将地址通过第三方手机app分享,若app校验严格,则地址会被标记为不合法。

      • 兼容性较好。

    4. history模式:

      • 地址干净,美观 。

      • 兼容性和hash模式相比略差。

      • 应用部署上线时需要后端人员支持,解决刷新页面服务端404的问题。

    5. 切换:

     

     

    第三节 Element-UI插件

    https://element.eleme.cn/#/zh-CN

     

    扩展:Vue应用打包发布

    npm serve build -> dist

     

    第04章_Vue3新技术

    第一节 Vue3简介

    1. 从Vue2到Vue3

    2020年9月18日,Vue.js发布了Vue的3.0版本,代号海贼王(one piece),地址为https://github.com/vuejs/vue-next/releases/tag/v3.0.0

    新版本主要进行了下面一些升级:

     

    2. 入门案例

    首先使用vue-cli初始化一个Vue3项目,过程与Vue2类似。

    注意:请通过vue --version查看@vue/cli版本,确保在4.5.0以上,否则通过npm install -g @vue/cli进行升级。

     

    然后进入项目根目录,使用如下命令启动项目:

    注意:启动前关闭eslint的语法检查,编辑vue.config.js文件如下:

     

    3. 目录结构说明

     

     

     

     

     

    第二节 响应式数据

    1. setup

    steup是Vue3.0中新增的配置项,值为一个函数,是其它Composition API(组合API)表演的舞台。

    setup函数相关注意点:

    1. setup函数在beforeCreate之前执行一次,this是undefined

    2. 不可以访问Vue2.x方式所配置属性和方法等,但反之可行(最好的办法是不要混合使用)。

    3. 如果声明为异步函数(async),则必须和Suspense及异步组件配合使用(见4.3小节)。

    4. 除了可以返回一个对象外,也可返回一个渲染函数,用于自定义渲染内容(了解)。

     

    setup函数有两个参数propscontext

    注意:Vue3中的子组件触发的事件需要通过emits:['event01']声明,否则会报警告。

     

     

     

    2. ref/shallowRef

    ref函数用于将原始数据包装为refImpl的对象,方便实现响应式,包装的语法格式为:const refValue = ref(rawValue)

    提示:如果在包装对象类型的原始数据时,不想创建Proxy对象,可以使用shallowRef替代,这样只有在整个对象进行替换时,才会触发响应式,刷新模板。

     

    3. reactive/shallowReactive

    reactive函数用于创建对象类型数据代理对象(Proxy),语法格式为:const 代理对象= reactive(源对象)。该代理对象是"深层次"代理的,能监控所有层次数据的增删改查操作,包括Vue2.x不支持的增加属性、删除属性、直接用下标操作数组(如arr[0] = 1)等操作。

    提示:如果只处理对象最外层属性的响应式(浅响应式),可以使用shallowReactive替代,一般用于第三方类库返回的数据。

     

    4. readonly/shallowReadonly

    readonly用于标记一个响应式数据是只读的(深只读),一般用于第三方类库返回的响应式数据,我们一般不在自己的程序中修改它。

    提示:如果你想"只读"仅对第一层属性生效,可以使用shallowReadonly替代(浅只读)。

     

     

    5. toRef/toRefs/toRaw/makeRaw

    本小节四个Composition API 用于实现原始数据和响应式数据之间的相互转换:

     

     

     

     

    6. isRef/isReactive/isProxy/isReadonly

     

    7. customRef

    customRef用于创建一个自定义的 ref,并对其依赖项跟踪和更新触发进行显式控制。如下一个防抖案例:

     

     

    第三节 计算属性与监视

    1. computed

    Vue3中的计算属性通过computed函数来定义,方式与Vue2中的computed配置项配置完全一致。

     

    2. watch

    Vue3中的属性监视通过watch函数来定义,格式为:watch(监视列表,回调函数(新值列表,旧值列表){},属性配置对象),根据监视的目标类型,具有不同的表现:

    此外,Vue2中讲解的immediate和deep属性依然有效(reactive类型强制开启deep),作为函数的第三个参数传入。

    提示:如果需要监视多个属性,可通过数组形式传入多个属性名,回调函数中则会分别收到新值和旧值所组成的列表。

     

    3. watchEffect

    watchEffect由watch衍生而来,根据回调函数中使用的属性,可自动推断需要监视的属性,和Vue2中的计算属性非常相似。

     

     

    第四节 新的组件

    1. Fragment

     

    2. Teleport

    Teleport是一种能够将我们的组件html结构移动到指定位置的技术,一般用于弹窗等操作。

     

     

     

     

     

     

    3. Suspense

    Suspense组件用于等待异步组件时渲染一些额外内容,让应用有更好的用户体验。使用步骤如下:

     

     

     

     

    第五节 其它补充

    1. 后代组件通信(provide/inject)

    Vue3中提供一对APIprovideinject,用于父组件和后代组件间通信。

     

     

     

     

    2. Vue3生命周期

    下面是Vue2和Vue3生命周期对比图,主要有如下一些差别:

    vue2.x的生命周期lifecycle_2
    vue3.0的生命周期lifecycle_2

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

    关于生命周期钩子函数,Vue3也有对应的配置项或Composition API 形式,对应关系如下:

    Vue2配置项Vue3 配置项Vue3 Composition API
    beforeCreate/createdbeforeCreate/createdsetup()
    beforeMount/mountedbeforeMount/mountedonBeforeMount/onMounted
    beforeUpdate/updatedbeforeUpdate/updatedonBeforeUpdate/onUpdated
    beforeDestroyed/destroyedbeforeUnmount/unmountedonBeforeUnmount/onUnmounted

    注意:同样的钩子函数,Composition API 形式配置先执行!

    • 挂载流程:setup->beforeCreate->created->onBeforeMount->beforeMount->onMounted->mounted

    • 更新流程:onBeforeUpdate->beforeUpdate->onUpdated->updated

    • 卸载流程:onBeforeUnmount->beforeUnmount->onUnmounted->unmounted

     

     

    3. Vue3响应式原理

    回顾Vue2中的响应式原理

    Vue2中的对象类型和数组类型分别通过不同的方式来实现响应式:

     

    ref函数支持响应式的原理

    ref函数实现响应式分两种情形:

     

    reactive函数支持响应式的原理

    reactive函数仅支持对象类型数据的响应式,其内部通过ES6中的Proxy创建代理对象,拦截对象中任意属性的变化,包括属性值的读写、属性的添加、属性的删除等,然后通过Reflect对源对象的属性进行操作。

    下面是MDN文档中描述的Proxy与Reflect:

     

     

    4. Vue3模块化开发

    在Vue3中,可以将Composition API制作的某个独立功能单独抽象到一个封装好的函数(hook函数)中,供多个组件进行复用,实现模块化开发,类似于vue2.x中的mixin。

     

     

     

    5. Vue3中的其它一些改变

    全局API转移

    Vue 2中有许多全局 API 和配置,如注册全局组件、注册全局指令等,Vue3.0调整到了app实例上。

    Vue2.x 全局 API(Vue实例)Vue3.x 全局 API (app实例)
    Vue.config.xxxxapp.config.xxxx
    Vue.config.productionTip移除(自动判断是否需要进行提示)
    Vue.componentapp.component
    Vue.directiveapp.directive
    Vue.mixinapp.mixin
    Vue.useapp.use
    Vue.prototypeapp.config.globalProperties

     

    移除.native修饰符

    默认未在子组件emits中声明的事件都为原生DOM事件。

    修改过度所使用的类名

     

    data配置项必须为函数

    Vue2中data配置项允许为对象形式,但会导致组件复用时,共用同一份存储空间的问题,Vue3中直接禁止这种写法。

     

    移除keyCode作为按键修饰符

    定义按键事件时不能使用keyCode作为修饰符,同时也不再支持config.keyCodes。

     

    移除过滤器

    过滤器虽然这看起来很方便,但它需要一个自定义语法,打破大括号内表达式是 “只是 JavaScript” 的假设,这不仅有学习成本,而且有实现成本!建议用方法调用或计算属性去替换过滤器。