Vue2-Vue3学习笔记(全)

1.Vue核心

1.1 初识Vue

1.想让Vue工作,就必须创建一个Vue实例,且要传入一个配置对象。

2.root容器里的代码依然符合html规范,只不过混入了一些特殊的vue语法。

3.root容器里的代码被称为“Vue模板”。

4.容器和实例的关系:容器和实例只能是一一对应的关系。开发中只会出现一个vue实例

a.多个容器对应一个实例,只有第一个容器会绑定。

b.多个实例对应一个容器,只有第一个实例会生效。

5.JS表达式和JS代码

a.JS表达式:一个表达式会产生一个值,可以放在任何一个需要值的地方,例如:a,a+b,demo(1),x==y?"A":"B".

b.js代码(语句):只控制走向不产生值

if(){},for(){}

6.{{xxx}}中xxx要写表达式,且xxx可以自动读取到data中的所有属性。

7.一旦data中的数据发生变化,那么模板中用到该数据的地方也会自动更新。




    
    
    Document
    


    

{{name}}

{{name}}

1.2 模板语法

 1.2.1 差值语法

差值语法只管标签内容,例如:上方代码中的yyyy是标签体内容。

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

yyyy

1.2.2 指令语法

指令语法只管标签属性,例如:上方代码中的xxxx是标签属性。

功能:用于解析标签(包括:标签属性,绑定事件等等),xxxx也是是js表达式,且可以读取到data中的所有属性。

如果属性前面加了v-bind,那么属性后面的“xx”内容,就会被当做表达式来执行。

v-bind:可以简写为:

备注:vue中有很多指令,且形式都是:v-***,此处v-bind只是举例子使用。

    

差值语法
你好 {{name}}

指令语法

指令语法
百度 百度

1.3数据绑定

vue有两种绑定方式:单向绑定和双向绑定

单向数据绑定
双向数据绑定
单向数据绑定
双向数据绑定

1.3.1单向绑定(v-bind:)

数据只能从data流向页面,无法从页面影响data

1.3.2双向绑定(v-model:)

数据可以从data流向页面,页面也可以流向data

1.3.3备注

1.双向绑定一般都应用在表单类元素上如:input,select,redio等等,有value的元素,因为只有用户有操做的元素,才有可能改变vaule,才有双向绑定的意义。类似于

等标签,用户无法修改value,自然也没有双向绑定的意义。

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

1.3.4 简写

v-bind:value简写为:value

v-model:value简写为:v-model:

1.3.5 el与data的两种写法

1.3.5.1 el写法

(1)new Vue的时候配置el属性

(2)先创建Vue实例,接收以后通过v.$mount("#id")对el进行绑定

1.3.5.2 data写法

(1)对象式

(2)函数式

在组件中,data必须使用函数式否则会报错。

1.3.5.3 注意:

在Vue管理的函数中,一定不要用箭头函数,否则this就不再是Vue实例了,而是Window。

    

{{name}}

1.4 MVVM模型

1.4.1 概念

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

2.V:视图(View)对应模板

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


    

学校名称:{{name}}

学校地址:{{address}}

VM属性:{{$createElement}}

1.4.2结论

(1)data中的所有属性最后都会出现在vm上。

(2)vm上的所有属性以及vue圆形上的所有属性,在vue模板中都可以直接使用

1.5 数据代理

1.5.1 Object.defineproperty方法

 

1.5.2 数据代理概念

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

    

1.5.3 Vue中的数据代理 

(1)Vue中的数据代理:通过vm对象来代理data中属性的操作(读/写)。

(2)Vue中数据代理的好处:更加方便的操作(读/写)data中的数据。

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

具体内容参考后面的数据劫持。

1.6事件处理

1.6.1事件的基本处理

事件的基本使用:

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

(2)事件的回调需要配置在methods对象中,最终会在vm桑。

(3)methods中配置的函数,不要使用箭头函数,否则this指向的不是vue而是window

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

(5)@click="demo"和@click="demo($event)"效果是一样的,但是后者有传参。

欢迎来到{{address}}

1.6.2 事件修饰符

Vue中的事件修饰符

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

(2)stop:组织事件冒泡(常用)。

(3)once:事件只能触发一次(常用)。

(4)capture:使用事件的捕获模式。

(5)self:只有event.target是当前操作的元素才会触发的时间。

(6)passive:时间的默认行为立即执行,无需等待时间回调执行完毕

  

欢迎来到{{address}}

点我提示信息
div1
div2

1.6.3键盘事件

(1)Vue中常用的按键别名:

                回车=》enter

                删除=》delete(捕获删除和退格键)

                退出=》esc

                空格=》space

                换行=》tab(特殊,必须配合keyDown使用)

                上=》up

                下=》down

                左=》left

                右=》right

(2)Vue未提供别名的按键可以用原始的key值去绑定,但要注意转为kebab-case(短横线命名)

(3)系统修饰键(用法特殊):ctrl、alt、shift,meta(win)

       (3.1)配合keyup使用:按下修饰键的同时,再按下其他键,随后释放其他键,事件才被触发。

        (3.2)配合keydown使用:正常触发事件。

(4)也可以用keyCode去指定按键(不推荐)。

(5)Vue.config.keyCodes.自定义键名=键码,可以定制按键别名。

    

1.6.4总结

1.7.2的修饰符可以连续使用:@click.passive.stop="demo"

1.7.3系统修饰键后面也可以连续使用:@keyUp.ctrl.y="demo"

1.7 计算属性与监视

当页面有两个输入框,且另一个位置需要计算两个框之内的内容时:

1.7.1计算属性

1.7.1.1 差值语法

    


姓名:{{firstName}}{{lastName}}
1.7.1.2计算属性

计算属性:

(1)定义:要用的属性不存在,要通过已有属性进行计算。

(2)原理:底层借助了Object.defineproperty方法提供的getter和setter方法。

(3)get函数什么时候执行:

        (3.1)初次读取属性时会执行一次。

        (3.2)当以来的属性,数据发生改变时,会再次调用。

(4)优势:与methods实现相比,内部有缓存机制(可服复用),效率更高,调试方便。

(5)备注:

        (5.1)计算属性最终会出现在vm上,直接读取即可使用。

        (5.2)如果计算属性要被修改,那么必须写set函数去响应修改,且

set中要引起计算式依赖的数据发生改变。


    


姓名:{{fullName}}

1.7.1.3计算属性简写

当计算属性只考虑读取,不考虑编辑时计算属性可以简写:


    


姓名:{{fullName}}

1.7.2 监视属性

1.7.2.1监视属性两种写法

监视属性watch:

(1)当贝坚实的属性发生变化是,回电好书自动调用,执行相关代码。

(2)监视的属性必须存在才能监视

(3)监视属性的两种写法:

        (3.1).new Vue是传入watch配置

        (3.2)通过vm.$watch监视

     

今天天气很{{info}}

1.7.2.2深度监视

深度监视:

(1)VUe中的watch默认部件是对象内部值得改变。(一层)

(2)配置deep:true可以监测对象内部值改变。(多层)

备注:

(1)Vue自身可以检测对象内部指的改变,但是Vue提供的watch默认不可以。

(2)使用watch根据数据具体结构,决定是否采用深度监视。

 

今天天气很{{info}}

a的值为:{{numbers.a}}


b的值为:{{numbers.b}}

1.7.2.3监视属性简写

1.7.3 计算属性和监视实现对比

computed和watch之间的区别:

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

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

两个重要的小原则:

(1)所有被Vue管理的函数最好写成普通函数,这样this指向的是vm或者组件实例对象。

(2)所有不被VUe所管理的函数(定时器回调函数,ajax回调函数等),做好使用箭头函数,这样this指向的才是vm

今天天气很{{info}}

1.8 class和style绑定

1.8.1 概念

(1)在应用界面中某个(些)元素的样式是变化的。

(2)class/style绑定就是专门实现动态样式效果的技术

1.8.2 class绑定

(1):class='xxx'。

(2)表达式是字符串‘classA’。

(3)表达式是对象{classA:isA,classB:isB}。

(4)表达式是数组['classA','classB']。


    
{{name}}
{{name}}
{{name}}

1.8.3 style绑定

(1):style="{{fontSize:xxx}}"其中xxx是动态值

(2):style="[a,b]"其中ab是样式的对象

{{name}}
{{name}}

1.9 条件渲染

1.9.1条件渲染指令

(1)v-if 与 v-else/v-else-if

                写法:

                (1.1)v-if="表达式"。

                (1.2)v-else-if="表达式"。

                (1.3)v-else。

                    适用于:切换频率较低的场景

                    特点:不展示的dom元素直接移除。

                    注意:v-if可以和v-else-if,v-else一起使用。但是结构不能被“打断”。

(2)v-show

                写法:v-show="表达式"

                适用于:切换频率较高的场景

                特点:不展示的dom元素未被移除,仅仅使用样式隐藏

(3)备注:

        (3.1)使用v-if时,元素可能无法获取到,而v-show元素一定会获取到。

        (3.2)template不能和v-show配合使用,v-if可以

{{name}}
{{name}}

1.9.2 v-if和v-show区别

(1)如果频繁切换用v-show。(页面不显示,但是元素还在)

(2)当条件不成立时,v-if所有子节点都不会解析。(页面不显示,元素也不加载)

1.10 列表渲染

1.10.1循环遍历

v-for指令:

(1)用于展示列表数据。

(2)语法:v-for="(item,index) in xxx" :key="yyy"。

(3)可以遍历:数组,对象,字符串,指定次数。

    
人员列表
  • {{person.name}}-{{person.age}}
汽车信息
  • {{param}}-{{index}}
字符串信息
  • {{char}}-{{index}}
循环指定次数
  • {{char}}-{{index}}

1.10.2 key的原理(面试题)

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

(1)虚拟dom中key的作用:

                key是虚拟dom对象的标识,当状态中的数据发生变化时,vue会根据【新数据】生成【新虚拟dom】,随后vue对【新虚拟dom】与【旧虚拟dom】进行差异比较,比较规则如下:

(2)比较规则:

        (2.1)旧虚拟dom中找到的新虚拟dom相同的key。

                (2.1.1)若虚拟dom中内容没变,直接使用之前的真是dom。

                (2.2.2)若虚拟dom中的内容变了,则生成新的真是dom,随后替换掉页面中

                                真实dom。

        (2.2)旧虚拟dom中未找到与新虚拟dom中相同的key

                (2.2.1)创建新的真是dom,然后渲染到页面。

(3)用index作为key可能会引发的问题:

        (3.1)若对数据进行逆序添加,逆序删除等破坏顺序的操作

                    会产生没有必要的真是dom更新==》界面效果没问题,但是效率低

        (3.2)如果结构中含有输入类dom:

                    会产生错误的dom更新==》页面有问题

(4)开发中如何选择key:

        (4.1)最好使用每条数据的唯一标识作为key,比如id,手机号,身份证号等等。

        (4.2)如果不存在对数据的逆序删除,逆序添加等破坏顺序的操作,仅用作渲染,

                     使用index作为key没有任何问题。

人员列表
  • {{person.name}}-{{person.age}}

1.10.3 列表筛选

可以使用计算实行或者监视属性实现,优先使用计算属性。

人员列表
  • {{person.name}}-{{person.age}}-{{person.sex}}

1.10.4 列表排序

增加排序属性,计算属性fliterPersonList返回搜索之前,进行一次数组排序,然后返回排序后的数组。


    
人员列表
  • {{person.name}}-{{person.age}}-{{person.sex}}

1.10.5 Vue无法检测到的数据改变

如果以对象的形式更新personList[0],Vue无法检测到数据的改变,vue开发工具也不会体现,但是如果先点击按钮,再打开Vue开发工具,则可以看到修改后的数据,但是页面并未修改,故:如果按第二种形式修改data里的属性的内容,Vue无法检测到属性的修改。


    
人员列表
  • {{person.name}}-{{person.age}}-{{person.sex}}

1.10.6 Vue监测原理

Vue中监视数据的原理:

(1)vue会监视data中所有层次的数据。

(2)如何监测对象中的数据:

         通过setter实现监测,且要在new Vue时就要传入检测的数据。

         (2.1)对象中后追加的属性Vue默认不做响应式处理。

         (2.2)如需给后添加的属性做响应式处理请使用如下API:

                  (2.2.1)Vue.set(targer,propertyName/index,value)

                  (2.2.2)vm.$set(targer,propertyName/index,value)

(3)如何检测数组中的数据:

          通过包括数组更新元素的方法实现,本质就做了两件事:

          (3.1)调用原生对应的方法,操作数组中的元素。

          (3.2)重新解析模板,进行页面更新。

(4)在Vue中修改数组中的某个元素一定要调用如下方法:

        (4.1)使用这些API:push()、pop()、shift()、unshift()、splice()、sort()、reverse()

        (4.2)Vue.set()、vm.$set(),不能给vm或vm跟数据对象(data)添加属性。


    

学生信息:

姓名:{{student.name}}

年龄:{{student.age}}

性别:{{student.sex}}

    爱好
  • {{h}}



  • 朋友
  • {{f.name}}--{{f.age}}

1.11 收集表单数据

 1.11.1 数据收集

收集表单数据:

(1) v-model收集的是value的值,用户输入的value。

(2)  v-model收集的是value的值,选中标签所配置的的value。

(3)

(3.1)若没有配置input的value属性,那么v-model收集的是checked勾选状态(true/false)

(3.2)若配置input的value属性:

(3.2.1)如果v-model绑定非数组,那么v-model收集的是checked勾选状态(true/false)

(3.2.2)如果v-model绑定数组,那么v-model收集的是checked勾选选择框对应的value


    
账号:
密码:
年龄:
性别:
爱好: 抽烟 喝酒 打牌
所属校区:
其他信息:
阅读并接受《用户协议》

 1.11.2 v-model的修饰符

v-model的三个修饰符:

(1)lazy:失去焦点后收集数据

(2)number:输入字符串转为有效数字,一般配合type="number"使用。

(3)trim:过滤收尾所有的空格,字符串中间空格无法过滤。

1.12 过滤器

1.12.1 概念

当我们获得了一个时间戳,我们并不需要这个获取到的时间戳,需要这个时间戳代表的时间,此时我们可以用过滤器将其过滤,然后获取对应的时间后使用。

 1.12.2过滤器使用

过滤器:

        定义:对要显示的数据进行特定格式化后在显示(适用于一些简单的逻辑处理)。

        语法:

        (1)注册过滤器:Vue.filter(name,callback)或者new Vue(filters:{})。

        (2)使用过滤器:{{xxx | 过滤器名}} 或 v-bind:属性="xxx | 过滤器名"。

        备注:

        (1)过滤器也可以接受额外的参数,多个过滤器也可以串联

        (2)并没有改变原本的数据,只是产生了新的数据。

 

显示格式化后的时间

{{fmtTime}}

{{getFMTime()}}

{{time | timeFormater }}

{{time | timeFormater('YYYY_MM_DD') |mySlice}}

显示格式化后的时间

{{time }}

{{time | mySlice}}

1.13 内置指令

1.13.1 学过的指令

v-bind:单项绑定解析表达式,可简写为:xxx

v-model:双向数据绑定

v-for:遍历数组,对象,字符串

v-on:绑定事件监听,可简写为@

v-if:条件渲染(动态控制节点是否存在)

v-else:条件渲染(动态控制节点是否存在)

v-show:条件渲染(动态控制节点是否显示)

1.13.2 v-text:

(1)作用:向所在的节点中渲染文本内容

(2)与差值语法不同,v-text会替换掉节点中所有的内容,{{xxx}}则不会替换


    
你好,{{name}}
你好,
你好,

1.13.3 v-html:

v-html指令:

(1)作用:向指定节点渲染包含html结构的内容。

(2)与差值语法的区别:

        (2.1)v-html 会替换掉节点中的所有内容,{{xx}}则不会。

        (2.2)v-html 可以识别html结构

(3)严重注意:v-html有安全性问题!!!

        (3.1)在网站上动态渲染任意HTML是非常文献的容易导致XSS攻击。

        (3.2)一定要在可信的内容上使用v-html,永远不要用在提交的内容上。


    
你好,{{name}}

1.13.4 v-cloak:

v-cloak指令(没有值)

(1)本质是一个特殊的属性,Vue创建完毕后,会删掉c-cloak属性。

(2)使用css配合v-cloak可以解决网速慢导致的页面站输出{{xxx}}的问题。


    
    
你好,{{name}}

1.13.5 v-once:

v-once指令:

(1)v-once所在的节点在初次动态渲染之后就视为静态内容了。

(2)以后数据的改变不会引起v-once所在结构更新,可以用于优化性能。

    
初始化n={{n}}
当前n={{n}}

1.13.6 v-pre:

v-pre指令:

(1)跳过其所在节点的编译过程。

(2)可利用它条过没有使用指令语法,没有使用差值语法的节点,可以加快编译。


    
静态内容
初始化n={{n}}
当前n={{n}}

1.14 自定义指令

参数:

(1)指令所绑定的元素

(2)绑定指令的具体实现

1.14.1 函数式


    
    

当前的n=

放大10倍的n=

放大10倍的n=

1.14.2 对象式

  
    

1.14.3 总结

(1)定义语法:

        (1.1)局部指令:                             

//创建vue实例
            const vm = new Vue({
                directives:{
                    //函数式
                    big(element,binding){
                        },
                    //对象式
                    fbind:{
                         //1.指令与元素成功绑定时(页面刚加载)
                         bind(element,binding){
                             element.value=binding.value
                           },
                         //2.指令所在元素插入页面时
                         inserted(element,binding){
                                element.focus()
                            },
                         //3.指令所在的模板被重新解析时
                         update(element,binding){
                             element.value=binding.value
                             element.focus()
                            }
                        }
                    }
                   
                }
            })

         (1.2)全局指令:

                 (1.2.1)Vue.directive(指令名:配置对象)

                 (1.2.2)Vue.directive(指令名:回调函数)

(2)配置对象中常用的三个回调:

        (2.1)bind:指令与元素成功绑定时调用。

        (2.2)inserted:指令所在元素被插入到页面中时调用。

        (2.3)update:指令所在模板被更新时调用。

(3)备注:

        (3.1)定义指令时不加v-,但是使用时加v-

        (3.2)指令如果是多个单词要用kebab-case方式命名,不要用canelCase命名

                

1.15生命周期

1.15.1 概念

生命周期:

(1)又名:生命周期回调函数,生命周期函数,生命周期钩子。

(2)是什么:Vue在关键时刻帮我们调用的一些特殊名称的函数。

(3)生命周期函数的名字不可更改,但是函数的具体内容是根据具体需求编写的。

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

 1.15.2 重要的生命周期

 vm的生命周期:

创建之前==》调用brforeCreate()函数

创建完毕==》调用created()函数

挂载之前==》调用beforeMount()函数

挂在完毕==》调用mounted()函数==================》【重要的钩子】

更新之前==》调用beforeUpdate()函数

更新完毕==》调用updateed()函数

销毁之前==》调用beforeDestory()函数==============》【重要的钩子】

销毁完毕==》调用destoryed()函数

 

欢迎来打山东省

1.15.3 总结

常用的生命周期狗子:

(1)mounted:发送ajax请求,启动定时器,绑定自定义事件,订阅消息等初始化操作。

(2)beforeDestroy:清除定时器,解绑自定义时间,取消消息订阅等收尾工作。

关于vue销毁:

(1)销毁后的Vue借助开发者工具看不到任何信息。

(2)销毁后的自定义事件会失效,但是原生dom时间依然有效。

(3)一般不会beforeDestroy中操作数据,因为操作了也不会再触发更新,而且立刻销毁。

 2.VUE组件化编程

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

 传统方式:

Vue2-Vue3学习笔记(全)_第1张图片

 问题:

(1)依赖关系混乱。

(3)代码复用率不高。

 组件方式

Vue2-Vue3学习笔记(全)_第2张图片

2.1 模块与组件

2.1.1模块

(1)概念:向外提供特定功能的js程序,一般是一个js文件。

(2)使用原因:js文件很多很复杂。

(3)作用:复用js,简化js的编写,提高js运行效率。

 2.1.2 组件

(1)概念:用来实现局部(特定)功能效果的代码集合(html/css/js/image...)。

(2)使用原因:一个界面功能很复杂。

(3)作用:复用代码,简化项目编码,提高运行效率。

2.1.3 模块化

应用中的js都已模块来编写,这个应用就是一个模块化应用。

2.1.4 组件化

当应用中的功能都是多组件的方式来编写,那么这个应用就是组件化应用

2.2 非单文件组件

定义:一个文件中有多个组件。

2.2.1 非单文件组件使用

(1)Vue组件使用三大步骤:

        (1.1)定义组件(创建组件)

        (1.2)注册组件(全局注册/局部注册)

        (1.3)使用组件(写组件标签)

(2)如何定义一个组件

        (2.1)使用VUe.extend(options)创建,其中options和new Vue(options)传入的options

                     几乎一样,但也有点区别:

                (2.1.1)不写el:组中所有组件都由vm管理,有vm指定el服务的容器。

                (2.1.2)data必须写函数式:避免组件复用时,数据引用造成的数据修改错误。

        (2.2)备注:template可以配置组件结构。

(3)如何注册组件:

        (3.1)局部注册:new Vue()时,传入入参conponents:{}参数。

        (3.2)全局注册:Vue.component('组件名',组件)。

(4)使用组件:使用引入组件时指定的组件名===><组件名><组件名/>


    
root1star


root1end
root2

2.2.2 ★注意点★

(1)关于组件名:

        (1.1)一个单词组成:

                (1.1.1)首字母小写(school)。

                (1.1.2)首字母小写(School)。

        (1.2)多个单词组成:

                (1.2.1)kebab-case命名方式:my-school。

                (1.2.2)CsmelCase命名方式:MySchool(需要脚手架支持)。

        (1.3)备注:

                (1.3.1)组件名尽可能回避HTML已存在的元素名,例如:h1,H1等等。

                (1.3.2)可以使用name配置指定组件在开发者工具中的名字(不影响调用)。

(2)关于组建标签:

        (2.1)单标签

        (2.2)双标签

        (2.3)不适用脚手架单标签多个连续使用会导致后面的无法渲染。

(3)简写方式:

                  const school={},当变量等于一个对象不调用Vue.compent()方法时,在vm引入                      组件时会做判断,如果没有调用,或自动去调用Vue.compent()。

        (3.1)简写:

const schoolConst = {

            template: `

学校名称:{{school.name}}

学校地址:{{school.address}}

`, data() { return { school: { name: "schoolName", address: "schoolAddress" } } }, methods: { alertSchoolName() { alert(this.school.name) } }, }

        (3.2)Vue自检:

        

  function extend(to, _from) {
      for (var key in _from) {
          to[key] = _from[key];
      }
      return to;
  }

2.2.3组件嵌套

root1star
root1end

2.2.4 VueConponent

关于 VueConponent:

(1)shcool组件本质是一个名为VueConponent的构造函数,且不是程序员地赢的,是                   Vue.extent生成的。

(2)我们只需要写或者,Vue解析时会帮我们创建school组件的           实例对象。

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

(4)关于this指向:

        (4.1)组件配置中:data函数,methods中的函数,watch中的函数,computed中的函

                    数,他们的this指向的是【VueComponent实例对象】

        (4.2)new Vue配置中:data函数,methods中的函数,watch中的函数,computed中

                    的函数,他们的this指向的是【Vue实例对象】

(5)一般情况下:

        (5.1)VueComponent实例对象简称==》vc(组件实例对象)

        (5.2)Vue对象简称==》vm

2.2.5 ★内置关系★

2.2.5.1 原型对象
function demo(){
            this.a=1
            this.b=2
        }
        const d=new demo();
        console.log(demo.prototype);//显示原型属性
        console.log(d.__proto__);//隐式原型属性
        console.log(d.__proto__===demo.prototype,"demo.prototype===d.__proto__");//true 他们都是原型对象
        //对原型对象添加一个属性99
        demo.prototype.x=99
 2.2.5.2 Vue和VueComponent

(1)一个重要的内置关系:Vue.prototype===schoolConst.prototype.__proto__(true)。

(2)为什么要有这个关系:让组件实例对象vc可以访问到Vue原型上的属性,方法。

 //1.创建组件school
        const schoolConst = Vue.extend({
            //el: '#root', 组件定义时一定不要写el,因为最终都要被一个vm管理,vm决定服务于谁
            //组件模板
            template:   `

学校名称:{{school.name}}

学校地址:{{school.address}}

`, //组件变量,必须用函数式 data() { return { school: { name: "schoolName", address: "schoolAddress" } } } }) //创建vm new Vue({ el: '#root', //2.注册组件(局部注册) template:" ", components: { //key为注册后的真实key,value为创建的const组件变量名,若两个一样可以简写为一个单词 school: schoolConst, }, }) console.log("Vue.prototype===schoolConst.prototype.__proto__:",Vue.prototype===schoolConst.prototype.__proto__)//true

Vue2-Vue3学习笔记(全)_第3张图片

2.3. 单文件组件

定义:一个文件只有一个组件。

2.3.1 Vue文件







2.3.2App.Vue





2.3.3main.js

import Vue from 'vue'
import App from './App'
new Vue({
    el:"#root",
    template:``,
    components:{App}

})

2.3.4 index.html




    
    
    Document


    

 3.使用脚手架

3.1 初始化脚手架

3.1.1说明

(1)Vue脚手架时Vue官方提供的标准化开发工具(开发平台)。

(2)文档 Vue CLI

3.1.2 具体步骤

(1)配置淘宝镜像:npm config set registry https://registry.npm.taobao.org

(2)全局安装@vue/cli。(仅第一次执行)(npm install -g @vue/cli)

(3)切换到项目路径,使用指令创建项目:vue create xxx

(4)启动项目:npm run serve

3.1.3 项目架构

(1).gitignore:配置不接受git管理的文件。

(2)babel.config.js:es6转es5要用到的babel配置文件(不需要修改)。

(3)package.json:

 "scripts": {
    "serve": "vue-cli-service serve",//运行命令
    "build": "vue-cli-service build",//代码完成后构建命令,将vue文件转为js,css,html文件
    "lint": "vue-cli-service lint"//代码检查
  },

(4)package-lock.json:包管理器版本管理。

(5)src:

        (5.1)main.js:项目入口文件

/* 项目入口文件 */
//引入vue
import Vue from 'vue'
//引入App组件,App是所有组件的父组件
import App from './App.vue'
//关闭vue生产提示
Vue.config.productionTip = false
//创建vue实例对象
new Vue({
  //将app组件放入容器中
  render: h => h(App),
}).$mount('#app')//等于el:"#app"

        (5.2)App.vue

        (5.3)index.html



  
    
    
    
    
    
    
    
    
    <%= htmlWebpackPlugin.options.title %>
  
  
    
    
    
    

备注:详细参考3.1.5

启动失败原因为:语法检查不通过。

        在项目的根目录找到(没有就自行创建)vue.config.js文件,关闭语法检查即可

const { defineConfig } = require('@vue/cli-service')
module.exports = defineConfig({
  transpileDependencies: true,
  lintOnSave:false /*关闭语法检查*/
})

3.1.4 不同版本的VUE

(1)vue.js与vue.runtime.xx.js的区别:

        (1.1)vue.js是完整版的VUE,包含核心功能+模板解析器。

        (1.2)vue.runtime.xx.js是运行版VUE,只包含核心功能,没有模板解析器。

(2)因为vue.runtime.xx.js没有模板解析器,所以不可以用template配置项,需要使用

         render函数,将接受到的createElement函数去指定内容。

3.1.5 修改默认配置

vue隐藏了webpack相关的配置,需要查看可以执行:vue inspect > output.js

可以看到但是无法修改,具体修改方式请参考:

配置参考 | Vue CLI

3.2 配置项

3.2.1 ref属性

(1)被用来给元素或子组件注册引用信息(代替id)。

(2)应用在html不爱券商,获取真是dom元素,应用在组件标签上是组件实例对象(vc)。

(3)使用方式:

        (3.1)打标识:

Ref属性测试

        (3.2)获取:this.$refs.school/this.$refs.title。

        (3.3)获取到子组件之后也可以修改其内部属性。



3.2.2 props属性

功能:让组件接收外部传入数据。

(1)传递数据

(2)接受数据:

        (2.1)props:['name']

        (2.2)限制类型

                

props:{
        id:String,
        name:String,
        size:String
    },

        (2.3)限制类型,限制是否必填,设置默认值

 props: {
    id: {
      type: String, //类型
      required: true, //是否必填
    },
    name: String,
    size: {
      type: String, //类型
      default: "型号(默认)", //是否必填
    },
  }

(3)备注:props事制度的,Vue底层会检测你对props的修改,如果进行了修改会发出警

         告,如果业务需要,那么应该将props的内容复制到data中一份然后修改data中的据。

App.vue


Material.vue



3.3mxin属性

功能:可以把多个组件共用的配置提取成一个混入对象。

使用方式:

(1)定义混合

export const mixin = {
    methods: {
        showName() {
            alert(this.name)
        }
    },
    mounted() {
        //alert("你好啊"+this.name)
    },
    data(){
        return {
            size:"mixinSIze"
        }
    }
}

(2)使用混入

        (2.1)全局混入:import {hunhe} from './mixin'; Vue.mixin(hunhe)。

        (2.2)局部混入:import {hunhe} from './mixin';mixins:['hunhe']

(3)注意:data中的数据以源文件为主,methods中的数据都会执行,而且优先执行混入的

Repository.vue



Material.vue



mixin.js
//引入Vue
import Vue from 'vue'
//引入app
import App from './App'

import {hunhe} from './mixin'
// Vue.mixin(hunhe)
//关闭提示
Vue.config.productionTip=false
new Vue({
    el:"#app",
    render:h=>h(App)
})

3.4插件

功能:用于增强Vue

本质:包含install方法的一个对象,install的第一个参数是Vue(vm的原型),第二个以后的

          参数是插件使用者传递的数据。

定义插件:

export default {
    install(Vue,a,b,c){
        console.log('install',Vue)
        //拿到Vue的构造方法,可以进行操作,Vue原型上的方法和属性vm和vc都能使用
        //全局过滤器
        //Vue.filter()
        //全局指令
        // Vue.directive()
        //全局混入
        // Vue.mixins()
        //给Vue原型增加方法,属性等等
        // Vue.prototype.$myMethod=function(){}
        // Vue.prototype.prototype=""
    }
}

使用插件:Vue.use()。

3.5 scoped样式

作用:让样式在局部生效防止冲突。

写法:

3.6 开发流程总结

(1)组件化编码流程

        (1.1)拆分静态组件:组件按照功能点拆分,命名不要与html元素冲突。

        (1.2)实现动态组件:考虑好数据存放位置,数据是一个组件在用,还是一些都在用。

                (1.2.1)一个组件再用:放在自身即可。

                (1.2.2)一些组件在用,放在他们共同的父组件上。(状态提升)

        (1.3)实现交互:绑定事件。

(2)props适用于:

        (2.1)父组件==》子组件 通信。

        (2.2)子组件==》父组件 通信(要求父组件先给子组件一个函数)。

(3)v-model使用时要切记,v-model绑定的不能是props传过来的值,因为props内传入的

         值是不可以修改的。

(4)props传过来的若是对象型的值,修改对象属性时vue不会报错,但不推荐这样做。

3.7本地存储

webStorage:

(1)储存内容大小一般支持5m左右(浏览器不同也可能不一样)

(2)浏览器通过Window.sessionStorage和window.localStorage属性来实现本地存储机制。

(3)相关API:

        (3.1)xxxxxxStorage.setItem(key,vaule);

                    该方法会把一个兼职顿添加到存储中,如果已有该键,则会更新内容。

        (3.2)xxxxxxStorage.getItem(key);

                     该方法接收一个key作为参数,获取对应的value。

        (3.3)xxxxxxStorage.removeteam(key);

                     该方法接收一个key作为参数,删除对应的key和value。

        (3.4)xxxxxxStorage.clear();

                     清除存储中所有数据。

(4)备注:

        (4.1)sessionStorage存储的内容会随着浏览器窗口关闭而消失。

        (4.2)localStorage存储的内容需要手动调用相应方法才会消失。

        (4.3)xxxxxxStorage.getItem(key);获取不到会返回一个null

        (4.4)保存对象时可用:JSON.stringify(person),

                    解析时用:JSON.parse(localStorage.getItem("personToJson"))

                    JSON.stringify(null)依然是null

saveData() {
      let person = { name: "张三", age: 18 }
      localStorage.setItem("msg", "hello!!");
      localStorage.setItem("numberMsg", 666);
      localStorage.setItem("person",person);
      localStorage.setItem("personToJson", JSON.stringify(person));
    },
    readData() {
      let person = { name: "张三", age: 18 }
     console.log( localStorage.getItem("msg", "hello!!"));
      console.log(localStorage.getItem("numberMsg", 666));
      // console.log(localStorage.getItem("person",person));
      console.log(JSON.parse(localStorage.getItem("personToJson")));
    },
    deleteData() {
      localStorage.removeItem("msg")
      localStorage.removeItem("numberMsg")
      localStorage.removeItem("personToJson")
    },
    clearData(){
      localStorage.clear();
    }

3.8组件自定义事件

(1)一种组件捡的通信方式,适用于:子组件===》父组件

(2)适用场景:A是父组件,B是子组件,B想给A传值,那么就要在A中给B绑定自定义事

         件,事件回调在A中。

(3)绑定自定义事件:

        (3.1)再父组件中使用

 
 

        (3.2)再父组件中使用



        (3.3)若想让自定义事件只触发一次,可以用once修饰符或者$once方法。

(4)触发自定义事件: this.$emit(name,value)。

(5)解绑滴定仪事件: this.$off(name)。

(6)组件上也可以绑定原生DOM事件,要用native修饰符。

(7)注意,通过this.$refs.student.$on(name,回调),板顶自定义事件时,回调要么要么在

         methods中,要么用箭头函数,否则this会指向调用函数的实体。

3.9 ★全局事件总线★

(1)全局事件总线(GlobalEventBus)是一种组件之间通信的方式,适用于任意组件之间

         的通信。

(2)安装全局事件总线:

beforeCreate(){
        Vue.prototype.$bus=this
    }

(3)使用全局事件总线:

        (3.1)接收数据:A组件想接收数据,则在A组件中给$bus绑定自定义事件,回调由A

                    组件自身实现。

mounted(){
    this.$bus.$on('hello',(data)=>{
      console.log('School组件收到了',data)
    })
  }

        (3.2)提供数据

      this.$bus.$emit('hello',this.student.name)

(4)使用完毕后,组件销毁之前最好用$off解绑当前组件所使用的事件

beforeDestroy(){
    this.$bus.$off('hello')
  },

3.10 消息订阅与发布

(1)消息订阅预发布(pubsub)是一种组件间的通信方式,适用于任意组件通信。

(2)使用步骤:

        (2.1)安装pubsub:npm i pubsub-js。

        (2.2)引入import pubsub from 'pubsub-js'

        (2.3)接收数据:A组件接收数据则在A组件内订阅消息,回调函数由A实现::

                      this.pubId=pubsub.subscribe('getStudentName',(msgName,data)=>{ })

                      第一个参数为消息的名称,第二个参数为传入的参数。

        (2.4)提供数据:pubsub.publish('getStudentName',this.student.name)

        (2.5)容器销毁之前,取消消息订阅:  pubsub.unsubscribe(this.pubId)

       

3.11 nextTick

(1)语法:this.$refs.inputTitle.focus()。

(2)作用:在下一次dom更新后在执行指定的回调函数。

(3)适用:数据改变后,基于更新后的dom执行某些操作时,在nextTick中指定回调函数。

3.12 过度与动画

(1)作用:在插入,更新,或者移除dom元素时,在合适的时候给元素添加样式类名。

(2):

Vue2-Vue3学习笔记(全)_第4张图片

(3)写法:

        (3.1)准备好样式

                元素进入:

                .1)v-enter:进入的起点。

                .2)v-enter-active:进入的过程中。

                .3)v-enter-to:进入的重点。

                元素移除入:

                .1)v-leave:离开的起点。

                .2)v-leave-active:离开的过程中。

                .3)v-leave-to:离开的重点。

        (3.2)使用包裹要过度的元素,并配置name属性。

        (3.3)备注:若有多个元素使用transition,要用,且每个元素都要

                    指定key。

transition




transition-group




  transition 引入css     

 4.Vue中的AJAX

4.1 解决跨域问题

4.1.1  方法1

在vue.config.js中添加配置

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

优点:配置简单,请求资源是直接发给前端(8080)即可。

缺点:不能配置多个单例,不能灵活的控制请求是否走代理。

工作方式:若按照上述配置代理,当请求了前端不存在的资源时,那么请求会自动转发,但是若前端有那么就不会转发。

4.1.1  方法2 

在vue.config.js中添加配置

devServer: {
    proxy: {
      //请求前缀为erp的走代理
      '/test/erp': {
        //转发地址
        target: 'http://localhost:8090',
        pathRewrite:{'^/test':''},//重写地址
        ws: true,//用于支持webstocket,不写默认true
        changeOrigin: true//请求头中的host是否为虚拟地址,不写默认true
      },
      '/demo/erp': {
        //转发地址
        target: 'http://localhost:8090',
        pathRewrite:{'^/demo':''},//重写地址
        ws: true,//用于支持webstocket,不写默认true
        changeOrigin: true//请求头中的host是否为虚拟地址,不写默认true
      },
    }
  }

 changeOrigin: 

        true:服务器收到的host为虚拟的,与服务器地址相同。

        false:服务器收到的host为真实的,与请求地址相同。

        默认为true(react默认为false)。

优点:可以配置多个代理,且可以灵活的控制请求是否走代理。

缺点:配置略微繁琐,请求资源必须加前缀。(可以配置路径重写)。

axio,vue-resource

4.2slot插槽

(1)作用:让父组件可以向子组件指定位置插入html结构,也是一种组件间通信额方式,适用于父组件===》子组件。

(2)分类:默认插槽,具名插槽,作用域插槽。

(3)使用方式:


        (3.1)默认插槽:

                    父组件:                    


    
HTML结构

                    子组件:

        (3.2)具名插槽

                    父组件:


    
     

                     子组件:

        (3.3)作用域插槽

                (3.3.1)作用:数组在组件自身,但是数据生成的结构由组件的使用者决定。

                                       (父组件决定结构,子组件提供数据)

                    父组件:


    
    

                    子组件:

5.vuex使用

5.1 理解vuex

5.1.1 vuex定义

(1)概念:专门在Vue中实现集中式状态(也叫:数据、状态数据,之后统称:状态)管理的VUe插件,对vue应用中多个组件共享状态进行集中式的管理(读/写),也是一种组件通信的方式,适用于任何组件。

(2)地址:GitHub - vuejs/vuex: ️ Centralized State Management for Vue.js.

当某个属性,所有组件都需要使用:

Vue2-Vue3学习笔记(全)_第5张图片

Vue2-Vue3学习笔记(全)_第6张图片

5.1.2 使用场景:

(1)当多个组件依赖同一个状态。

(2)来自不同组件的行为要变更同一个状态。

5.2 搭建vuex环境

(1)创建 文件夹:src/store/index.js

//该文件用于vuex中最为核心的store

//引入Vue
import Vue from 'vue'


//引入vuex
import Vuex from 'vuex'

//准备actions 用于响应组件里的动作
const actions = {

}
//准备mutations 用于真正操作state中的数据
const mutations = {

}
//准备state 用于存储数据
const state = {

}
Vue.use(Vuex)

//创建并暴露store
export default new Vuex.Store({
    actions,
    mutations,
    state,
})

(2)在main.js中创建vm时传入store:

import store from './store'
const vm=new Vue({
    el:"#app",
    render:h=>h(App),
    store,
    beforeCreate(){
        Vue.prototype.$bus=this
    }
})

(3)注意:必须在index.js中引入Vue并使用插件vuex,否则new Vuex.Store()会报错。

5.3 基本使用

(1)初始化数据(state),配置actions,配置mutations,操作文件store.js。

//该文件用于vuex中最为核心的store

//引入Vue
import Vue from 'vue'


//引入vuex
import Vuex from 'vuex'

//准备actions 用于响应组件里的动作
const actions = {
    /* add(context,value){
        // console.log("store.actions.add,context=",context,"value=",value)
        context.commit("ADD",value)
    },
    sub(context,value){
        context.commit("SUB",value)
    }, */isOdd(context, value) {
        console.log("store.actions.isOdd",value)
        context.dispatch("demo1", value)
    }, demo1(context, value) {
        console.log("store.actions.demo1",value)
        context.dispatch("demo2", value)
    }, demo2(context, value) {
        console.log("store.actions.demo2")
        if (context.state.sum % 2 != 0) {
            console.log("store.actions.isOdd")
            context.commit("ADD", value)
        }
    }, sleepAdd(context, value) {
        console.log("store.actions.sleepAdd")
        setTimeout(() => {
            context.commit("ADD", value)
        }, 1000);
    }
}
//准备mutations 用于真正操作state中的数据
const mutations = {
    ADD(state, value) {
        // console.log("store.mutations.ADD,state=",state,"value=",value)
        console.log("store.mutations.ADD")
        state.sum += value
    },
    SUB(state, value) {
        console.log("store.mutations.state")
        // console.log("store.mutations.ADD,state=",state,"value=",value)
        state.sum -= value
    }
}
//准备state 用于存储数据
const state = {
    sum: 0,

}
Vue.use(Vuex)

//创建并暴露store
export default new Vuex.Store({
    actions,
    mutations,
    state,
})

(2)组件读取vuex中的数据:$taore.state.sum

(3)修改vuex中的数据:$store.dispatch('action中的方法名',参数)或者$store.commit('mutations中的方法名',参数)。




备注:若没有网络请求或者其他业务逻辑,组件们可以越过actions直接访问mutations中的方法,既直接写commit()。

5.4 getters的使用

(1)概念:当state中的数据需要加工后在使用时,可以使用getters参数。

(2)配置getters属性:

//将state中的数据进行加工
const getters={
    bigSum(state){
        return state.sum*10
    }
}
//创建并暴露store
export default new Vuex.Store({
    actions,
    mutations,
    state,
    getters
})

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

5.5 四个map方法

5.5.1 mapState方法:

用于帮助我们映射state中的数据为计算属性:

computed:{
 //借助mapState生成计算属性,从state中读取数据(对象写法)
    // ...mapState({school:'school',subject:'subject',sum:'sum'})
    // 数组写法
     ...mapState(['school','subject','sum']),
}

5.5.2 mapGetters方法:

用于帮助我们映射getters中的数据为计算属性

computed:{
 //借助mapState生成计算属性,从state中读取数据(对象写法)
    // ...mapGetters({bigSum:'bigSum'})
    // 数组写法
     ...mapGetters(['bigSum']),
}

5.2.3 mapActions方法

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

//对象式
// ...mapActions({sleepAdd:'sleepAdd',isOdd:'isOdd'})
//数组式
    ...mapActions(['sleepAdd','isOdd'])

5.2.4 mapMutations方法

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

   //对象式
 // ...mapMutations({add:'ADD',sub:'SUB'}),
//数组式
    ...mapMutations(['ADD','SUB']),

5.2.5 注意

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

5.6 模块化+命名空间

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

(2)修改store.js,拆分为两个:person.js,count.js

person.js


//人员功能相关的
export default {
    namespaced:true,

    actions: {
        addPerson(context, value) {
            console.log("store.actions.addPerson")
            if (value != "") {
                context.commit("ADDPERSON", value)
            } else {
                alert("请输入姓名")
            }
        }
    },
    mutations: {
        ADDPERSON(state, value) {
            state.personList.push(value)
        }
    },
    state: {
        personList: ['张三']
    },
    getters: {}
}

conut.js


//求和功能相关的
export default {
    namespaced:true,
    actions: {
        isOdd(context, value) {
            console.log("store.actions.isOdd", value)
            if (context.state.sum % 2 != 0) {
                console.log("store.actions.isOdd")
                context.commit("ADD", value)
            }
        }, sleepAdd(context, value) {
            console.log("store.actions.sleepAdd")
            setTimeout(() => {
                context.commit("ADD", value)
            }, 1000);
        },
    },
    mutations: {
        ADD(state, value) {
            // console.log("store.mutations.ADD,state=",state,"value=",value)
            console.log("store.mutations.ADD")
            state.sum += value
        },
        SUB(state, value) {
            console.log("store.mutations.state")
            // console.log("store.mutations.ADD,state=",state,"value=",value)
            state.sum -= value
        },
    },
    state: {
        sum: 0,
    },
    getters: {
        bigSum(state) {
            return state.sum * 10
        }
    }
}

index.js

//该文件用于vuex中最为核心的store

//引入Vue
import Vue from 'vue'
//引入vuex
import Vuex from 'vuex'
import sumOptions from './count'
import personOptions from './person'
Vue.use(Vuex)

//创建并暴露store
export default new Vuex.Store({
    modules:{
        coundAbout:sumOptions,
        personAbout:personOptions,
    }
})

(3)namespaced:true开启命名空间。

(4)开启命名空间后组件,读取state中的数据:

//方式1 直接读取
this.$store.state.personAbout.personList
//方式2 借助mapState读取
...mapState('countAbout',[sum])

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

//方式1 直接读取
this.$store.getters['personAbout/firstName']
//方式2 借助mapGetters读取
...mapState('countAbout',['bigSum'])

(5)开启命名空间后,组件调用dispatch:

//方式1 直接调用dispatch
this.$store.dispatch('personAbout/addPerson',{name:'王'})
//方式2 借助mapActions读取
...mapActions('countAbout',['isOdd','sleepAdd'])

(6)开启命名空间后,组件调用commit:

//方式1 直接调用commit
this.$store.commit('personAbout/ADD_PERSON',{name:'王'})
//方式2 借助mapMutations读取
...mapMutations('countAbout',['ADD','SUB'])

6.vue中的路由

6.1 相关概念

6.1.1 vue-router 相关概念

vue中的一个插件库,专门用来实现SPA应用。

6.1.2 SPA应用相关概念

(1)单页Web应用(single page web application 既:SPA)。

(2)整个应用只有一个完整的页面。

(3)点击页面中的导航链接,不会刷新页面,只会做局部更新。

(4)通过ajax获取数据。

6.1.3 路由的相关概念

(1)路由的概念:

        (1.1)一个路由就是一组映射关系(key-value)。

        (1.2)key为路径,value是function或者component。

(2)路由分类:

        (2.1)后端路由:

                (2.1.1)概念:value是function,用于处理客户端提交的请求。

                (2.1.2)工作过程:服务器接收到一个请求时,根据请求路径找到匹配的函数来

                               处理请求,返回响应数据。

        (2.2)前端路由:

                (2.2.1)概念:value是一个component,用于展示页面内容。

                (2.1.2)工作过程:当浏览器路径发生改变时,就会展示对应的组件。

6.2 路由的基本使用

(1)安装vue-router:命令:npm i vue-router(如果是vue2则使用npm i vue-router@3)。

(2)应用插件:Vue.use(VueRouter)。

(3)编写router配置项:创建router/index.js。

//该文件用于创建整个应用的路由器
import VueRouter from 'vue-router'
import Class from "../compnents/Class.vue";
import Subject from "../compnents/Subject.vue";
//创建并暴露一个路由
export default new VueRouter({
    routes:[

        {
        path:'/class',
        component:Class
    },{
        path:'/subject',
        component:Subject
    }
]
})

(4)实现切换:active-class表示点击后触发的样式,to表示跳转的路由连接。

      

(5)指定点击导航后展示的内容位置:

    

6.3 注意事项

(1)通过路由配置实现展示的组件(既通过实现展示的组件)称之为路由组件,通过编写标签实现展示的,称之为一般组件,一般组件通常存放在components文件夹,路由组件一般存放在pages文件夹。

(2)通过切换实现展示后,不展示的路由组件默认是被销毁的,当切换路由展示路由组件时,会再去重新挂载。

(3)每个组件都有自己的$route属性,里面存储当前组件的路由信息(每个组件$route属性不相同)。

(4)整个组件只有一个router,可以通过$router属性获取到(每个组件$router属性相同)。

6.4 嵌套(多级)路由

(1)配置路由规则时使用children配置项:

​
//该文件用于创建整个应用的路由器
import VueRouter from 'vue-router'
import Class from "../pages/Classes";
import Subject from "../pages/Subject";
import OneClass from '../pages/OneClass'
import TwoClass from '../pages/TwoClass'
//创建并暴露一个路由
export default new VueRouter({
    routes: [
        {
            path: '/class',
            component: Class,
            children: [
                {
                    path: 'oneClass',
                    component: OneClass,
                },
                {
                    path: 'twoClass',
                    component: TwoClass,
                },
            ]
        }, {
            path: '/subject',
            component: Subject
        }
    ]
})

​

(2)使用时要写完整路径:

 
  • 一班
  • 二班

(3)注意:二级路由配置时不要写"/",但是访问时路径要写全路径(加上父路径)。

6.5 query参数

(1)传递参数:

        (1.1)直接拼接:

  • {{item.name}}

        (1.2)对象写法:

        

  • {{item.name}}

(2)接收参数:

名称:{{$route.query.name}}

内容:{{$route.query.content}}

6.6 命名路由

(1)作用:简化路由的跳转。

(2)使用:

        (2.1)给路由命名:

//该文件用于创建整个应用的路由器
import VueRouter from 'vue-router'
import Classes from "../pages/Classes";
import Subject from "../pages/Subject";
import Class from '../pages/Class'
//创建并暴露一个路由
export default new VueRouter({
    routes: [
        {   
            name:'班级',
            path: '/classes',
            component: Classes,
            children: [
                {   
                    name:'班内信息',
                    path: 'class',
                    component: Class,
                },
                {
                    path: 'subject',
                    component: Subject
                }
            ]
        }
    ]
})

        (2.2)使用:

       

 {{item.name}}




 {{item.name}}

若是路径过于繁琐,可以不使用路径,转而使用name属性。

6.7 params参数

(1)配置路由,声明接收params的参数(path中使用占位符):

//该文件用于创建整个应用的路由器
import VueRouter from 'vue-router'
import Classes from "../pages/Classes";
import Subject from "../pages/Subject";
import Class from '../pages/Class'
//创建并暴露一个路由
export default new VueRouter({
    routes: [
        {   
            name:'班级',
            path: '/classes',
            component: Classes,
            children: [
                {   
                    name:'班内信息',
                    path: 'class/:name/:content',
                    component: Class,
                },
                {
                    path: 'subject',
                    component: Subject
                }
            ]
        }
    ]
})

(2)传递参数:

 
  • {{item.name}}
  • {{ item.name }}
  • 注意:如果用对象写法一定要用name属性跳转,而不是path属性。

    (3)接收参数:

    名称:{{$route.params.name}}

    内容:{{$route.params.content}}

    6.8 props配置

    (1)作用:让路由组件更加方便的接受到参数:

    {
       name: '班内信息',
       path: 'class/:name/:content',
       component: Class,
       // 第一种写法 值为对象 局限性比较大一般不用
       /*props:{
       name:"name",
       content:"content"
       } */
       // 第二种写法 值为Boolean 如果值为true,则将所有收到的param参数以props的形式传递给该组件,query接收不到
       // props:true
       // 第三种写法 值为函数 
       props($route){
          return{
                   name:$route.query.name,
                   content:$route.query.content
                }
             }
    }

    6.9 route-link的replace

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

    (2)浏览器历史记录写入模式有两种,push和replace,push是追加历史记录,replace是替换当前记录,默认是push。

    (3) 开启replace模式。

    6.10 编程式路由导航

    (1)作用:不借助实现跳转,让路由跳转更加灵活。

    (2)编码:

    pushShow(item){
          this.$router.push({
                    name: '班内信息',
                    query: {
                      name: item.name,
                      content: item.content,
                    },
                  })
        },
    replaceShow(item){
          this.$router.replace({
                    name: '班内信息',
                    query: {
                      name: item.name,
                      content: item.content,
                    },
                  })
        },
    //返回
    back() {
          this.$router.back();
        },
    //前进
    forward() {
          this.$router.forward();
        },
    //前进或后退指定步数
    testGo() {
          this.$router.go(-1);
        },

    6.11 路由缓存

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

    (2)具体编码:

    
              
     

    (3)注意:include如果不写则默认全部,内容为组件的name属性,并非router内配置的name属性。缓存多个写法为:

    
              
     

    6.12 新生命周期钩子

    (1)作用:路由组件所独有的生命周期钩子,用于捕获组件是否处于激活状态

    (2)使用:

    activated() {
        console.log("Class被激活")
        this.timeId=  setInterval(() => {
        this.opacity -= 0.01;
          if (this.opacity < 0) {
            this.opacity = 1;
          }
        },15);
      },
      deactivated() {
            console.log("Class失活")
        clearInterval(this.timeId)
      },

    (3)补充:$nextTick也属于生命舟曲钩子,当更新数据的dom更新完毕再执行$nextTick内的代码。

    6.13 路由守卫

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

    (2)分类:全局守卫,独享守卫,组件内守卫。

    (3)全局守卫:

    //全局前置路由守卫,每次初始化之前或者路由切换之前,
    router.beforeEach((to, from, next) => {
        console.log("前置路由守卫",from,to)
        let user = localStorage.getItem("user")
        if (to.meta.isAuth) {
            if (user == 'user') {
                next()
            }else{
                alert(user+'无权查看')
            }
        }else{
            next()
        }
    })
    //全局前置路由守卫,每次初始化之前或者路由切换之后,
    router.afterEach((to, from) => {
        console.log("后置路由守卫",from,to)
        document.title=to.name
    })
    

    (4)独享守卫:

    独属于某一个路由的路由守卫,且没有afterEnter路由守卫。

    {
                        name: '班内信息',
                        path: 'class/:name/:content',
                        meta:{
                            isAuth:true
                        },
                        component: Class,
                        beforeEnter:(to, from, next) => {
                            console.log("前置路由守卫",from,to)
                            let user = localStorage.getItem("user")
                            if (to.meta.isAuth) {
                                if (user == 'user') {
                                    next()
                                }else{
                                    alert(user+'无权查看')
                                }
                            }else{
                                next()
                            }
                        }
                    }

    (5)组件内路由守卫:

    通过路由规则,访问或离开该组件时,会调用。(直接使用标签访问组件不会调用)

    //通过路由规则进入该组件时调用
      beforeRouteEnter(to, from, next){
        next()
      },
      //通过路由规则离开该组件时调用
      beforeRouteLeave (to, from, next) {
        next()
      }

    6.14 路由的hash和history

    Vue2-Vue3学习笔记(全)_第7张图片

    (1)对于一个url来说,#及其后面的内容就是hash值。

    (2)hash值不会包含在http请求中。(既不会发送给服务器)

    (3)hash模式:

            (3.1)地址中永远带有#,不美观。

            (3.2)若以后通过第三方手机app分享,若app校验较为严格,则会被认定为不合法。

            (3.3)兼容性好。

    (4)history模式:

            (4.1)地址干净,美观。

            (4.2)兼容性比起hash模式略差。

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

     8.Vue3快速上手

    Vue2-Vue3学习笔记(全)_第8张图片

    vue3地址 

    地址:awesome vue 3 & vue-cli 3+ · GitHub

     8.2 Vue3优势

    (1)性能的提升。

    (2)源码升级。

    (3)支持TypeScript。

    (4)新特性。

    8.1创建Vue3工程

     官方文档:快速上手 | Vue.jsVue.js - 渐进式的 JavaScript 框架https://cn.vuejs.org/guide/quick-start.html

    8.1.1 vue-cli创建

    ##1.查看vue-cli版本:
    vue --version 
    vue -V
    
    ##2.如果版本在4.5.0以下升级或安装执行:
    npm install -g @vue/cli 
    
    ##3.创建:
    vue create vue3_test
    
    ##4.启动:
    cd vue_test
    npm run serve
    
    

     8.1.2 vite 创建

    vite 官网:

    Vite | 下一代的前端工具链下一代前端工具链https://cn.vitejs.dev/weback打包模式:

    Vue2-Vue3学习笔记(全)_第9张图片

    vite打包模式:

    Vue2-Vue3学习笔记(全)_第10张图片

    ##1.创建工程:
    npm init vite-app 
    
    ##2.进入工程目录:
    cd 
    
    ##3.安装依赖:
    npm install
    
    ##4.启动:
    npm run serve
    
    

     8.2常用composition API

    组合式API

    8.2.1 setup函数

    (1)概念:Vue3中的一个新的配置项,值为一个函数。

    (2)setup是所有Compositon API的“表演的舞台”。

    (3)组件中所用到的:数据,方法等等,均要在setup中配置。

    (4)setup函数中的两种返回值:

            (4.1)若返回一个对象,则对象中的属性,方法,在模板中均可以直接使用(常用)。

            (4.2)若返回一个渲染函数,则可以自定义渲染内容(了解)。

    (5)注意:

            (5.1)尽量不要与Vue2.x混用:

                    (5.1.1)Vue2.x中的(data,methods,computed等等)可以访问到setup的方

                                   法,属性。

                    (5.1.2)setup中不能访问到Vue2.x中的(data,methods,computed等等)。

                    (5.1.3)如果重名,setup优先级高。

            (5.2)setup不能是一个async函数,因为返回值不再是一个return对象,而是

                        promise,模板看不到return中的属性

    总结:setup用于替代 Vue2 中的 beforeCreate 和 created 钩子函数。setup 选项是一个函数,它在组件实例被创建之前执行,并返回一个包含状态和方法等配置信息的对象。

    import { h } from "vue";
    export default {
      name: "App",
      setup() {
        let person = {
          name: "张三",
          age: 18,
        };
        function sayHello() {
          alert(`${person.name}:hello word,年龄:${person.age}`);
        }
        //返回一个对象
        return {
          person,
          sayHello,
        };
        //返回一个渲染对象
        /* return ()=>{
        return h('h1',person.name)
      } */
      },
    };
    

    8.2.2 ref函数

    (1)作用:用于定义一个响应式的数据。

    (2)语法:const xxx=ref(initValue)。

            (2.1)创建一个包含响应式数据的引用对象(reference对象)。

            (2.2)js中操作数据用xxx.value操作。

            (2.3)模板中读取:直接{{xxx}}。

    (3)备注:

            (3.1)接收基本类型:响应式还是依靠Object.defineProperty()的get与set实现。

            (3.2)接收对象类型:内部使用了Vue3中的一个新函数reactive函数,底层是用Proxy

                         实现的。

    import { ref } from "vue";
    export default {
      name: "App",
      setup() {
        /* let person = {
          name: ref("张三"),
          age: ref(18),
        }; */
         let person =ref({
          name: "张三",
          age: 18
        });
        function changeInfo(){
          console.log(person)
          person.value.age=25
        }
        return {
          person,
          changeInfo
        };
      },
    };

    8.2.3 reactive函数

    (1)作用:定义一个响应式数据(基本数据不用他,用ref函数)。

    (2)语法:const 代理对象=reactive(源对象) 接受一个对象或数组,返回一个代理对象(proxy对象)。

    (3)reactive定义的响应式数据是深层次的。

    (4)内部基于es的proxy实现,通过代理对象操作源对象内部的数据。

    let person = reactive({
          name: "张三",
          age: 18,
          hobby: [1, 2, 3, 4, 5],
          a: {
            b: {
              c: {
                d: 666,
              },
            },
          },
        });
    
        function changeInfo() {
          person.hobby[0]=111;
        }
        return {
          person,
          changeInfo,
        };

    8.2.4 响应式原理

    8.2.4.1 vue2中的响应式

    对象类型:通过Object.defineProperty()对属性的读取,修改进行拦截(数据劫持)。

    数组类型:通过重写数组的一系列方法来实现拦截。(对数组的变更方法进行了包裹)。

    问题:

            (1)新增属性,删除属性,界面不会更新。(监测不到数据修改)

            (2)不通过制定方法修改数组,界面不会自动更新。(监测不到数据修改)

    
        
        Document
    
    
    
    

    Vue2-Vue3学习笔记(全)_第11张图片

    当我们创建一个响应式对象,修改其中的属性会触发相应的方法,而我们添加的属性,并不是响应式的,并非通过get和set方法操作属性,而vue2的更新dom操作就是在set方法中实现的,所以监控不到属性的新增和删除。

    具体参考:1.Vue核心-CSDN博客

    Vue核心的1.5小结数据代理以及1.10.5 Vue无法检测到的数据改变和解决方案。

    8.2.4.2 vue3中的响应式

    (1)了解Reflect(反射):

     let person = {
          name: "张三",
          age: 18,
        };
        let p={}

    当出现如下代码时,会出现语法错误导致页面无法正常渲染。

    Object.defineProperty(p, "name", {
          get() {
            console.log("有人读取了p.name属性");
            return person.name;
          }
        });
        Object.defineProperty(p, "name", {
          get() {
            console.log("有人读取了p.name属性");
            return person.name;
          }
        });

    当我们使用Reflect操作时,失败并不会出现错误,而是返回一个false。

      const a= Reflect.defineProperty(p, "name", {
          get() {
            console.log("有人读取了p.name属性");
            return person.name;
          }
        });
        const b= Reflect.defineProperty(p, "name", {
          get() {
            console.log("有人读取了p.name属性");
            return person.name;
          }
        });
        console.log('a',a,'b',b)
    a true b false

    所以,当我们使用第一种方法,去操作一个属性有可能会出现异常,导致页面出现问题,而是用第二种方式去操作,会返回一个操作结果是否成功。站在代码兼容性考虑,是有必要使用Reflect来操作属性的。

    (2)了解Proxy:

    p=new Proxy(person,{
            //读取属性调用
            get(target,propName){
                console.log('有人读取了p的',propName,"属性,值",person.propName)
                return target[propName]
            },
            //修改,新增属性调用
            set(target,propName,value){
                console.log('有人修改了p的',propName,"属性,原值",person.propName,'改为:',value)
                 target[propName]=value
            },
            //删除属性调用
            defineProperty(target,propName){
                console.log('有人删除了了p的',propName,"属性")
               return delete target[propName]
            },
            
        }) 

    创建一个Proxy对象当我们对该对象进行属性操作时:

    Vue2-Vue3学习笔记(全)_第12张图片

    当我们对对象的属性进行增删改查操作时,都会被相应的监控的,并且执行的操作会在person上执行。

    (3)总结:当结合了Proxy和Reflect后就形成了vue3的响应式:

                       Proxy(代理):拦截对象中任意属性的变化(增删改查)。

                       Reflect(反射):对被代理对象的属性执行操作(不会出现语法错误)。

    p=new Proxy(person,{
            //读取属性调用
            get(target,propName){
                console.log('有人读取了p的',propName,"属性,值",person.propName)
                return Reflect.get(target,propName)
            },
            //修改,新增属性调用
            set(target,propName,value){
                console.log('有人修改了p的',propName,"属性,原值",person.propName,'改为:',value)
                 Reflect.set(target,propName,value)
            },
            //删除属性调用
            defineProperty(target,propName){
                console.log('有人删除了了p的',propName,"属性")
               return Reflect.defineProperty(target,propName)
            },
            
        }) 

    Proxy和Reflect的浅层理解:Proxy和Reflect-CSDN博客

    8.2.5 reactive和ref

    从定义角度相比:

            ref:用来定义基本数据类型。

            reactive:用来定义对象或数组类型数据。

    从原理角度相比:

            ref:通过Object.defineProperty()的get和set来实现响应式(数据劫持)。

            reactive:通过Proxy来实现响应式(数据劫持),并通过Reflect操作源对象内数据。

    从使用角度相比:

            ref:操作数据需要用xxx.value,读取时不需要xxx.value。

            reactive:操作和读取数据都不用xxx.value

    8.2.6 setup的两个注意点

    (1)setup执行时机在beforeCreate之前,且只执行一次,this是undefined。

    (2)setup的参数:

            (2.1)props:值对象,包含:组件外传递过来的,且组件内部生命接受了的属性。

            (2.2)context:上下文对象:

                    (2.2.1)attrs:值对象,外部传递进来,但props未接收的属性(this.$attrs)。

                    (2.2.2)slots:收到的插槽内容,相当于this.$slots。(最好用v-slot命名)。

                    (2.2.3)emit:分发自定义事件的函数(this.$emit)。

    8.2.7 计算与监视属性

    8.2.7.1 计算属性 computed

    (1)与vue2.x的computed配置功能一致。

    (2)写法:   

    import { computed } from "vue";
    setup(props, context) {
        const data = reactive({
          person: {
            name: {
              firstName: "张",
              lastName: "三",
            },
            age: 18,
          },
        });
        //计算属性--简写--只考虑回写没考虑修改
        /* data.person.fullName=computed(()=>{
           return data.person.name.firstName+"--"+ data.person.name.lastName
        }) */
        //计算属性--完整写法
        data.person.fullName = computed({
          get() {
            return data.person.name.firstName + "-" + data.person.name.lastName;
          },
          set(value) {
            const nameArr = value.split("-");
            data.person.name.firstName = nameArr[0];
            data.person.name.lastName = nameArr[1];
          },
        });
        return {
          data,
        };
      },
    8.2.7.2 监视属性 watch

    与vue2中的watch功能一致。

    问题:

            (1)监视reactive定义的响应式数据时,oldValue无法正确获取(由于旧值和新值实际

                     上是同一个引用,因此旧值和新值看起来总是相同的。),且默认开启了深度监

                     视,无法关闭(deep配置失效)。

            (2)监视reactive定义的响应式数据中的某个对象属性时,deep配置又生效了。

     //情况1:监视ref定义的一个响应式数据
        watch(sum,(newValue, oldValue)=>{
            console.log("sum被修改了", newValue, oldValue);
        }) 
    
        //情况2:监视ref定义的多个响应式数据
        watch([sum,msg],(newValue, oldValue)=>{
            console.log("sum或msg被修改了", newValue, oldValue);
        })
        //传入第三个参数配置对象
        watch(sum,(newValue, oldValue)=>{
            console.log("sum被修改了", newValue, oldValue);
        },{immediate:true})
        /* 
            情况3:监视reactive定义的对象 全部属性
            1.reactive定义的数据无法正确获取oldValue 
            2.强制开启了深度监视且无法关闭(deep配置失效了)
        */
        watch(data,(newValue,oldValue)=>{
            console.log('person变化了',newValue,oldValue)
        })
        /* 
            情况4:监视reactive定义的对象 某个属性
        */
        watch(()=>data.age,(newValue,oldValue)=>{
            console.log('person变化了',newValue,oldValue)
        })
        /* 
            情况5:监视reactive定义的对象 某些属性
        */
         watch([()=>data.age,()=>data.name],(newValue,oldValue)=>{
            console.log('person变化了',newValue,oldValue)
        }) 
        /* 
            特殊情况:监视reactive定义的对象 中的对象属性
        */
         watch(()=>data.job,(newValue,oldValue)=>{
            console.log('person变化了',newValue,oldValue)
        },{deep:true}) 
    8.2.7.2 补充

    (1)监视ref定义的基本数据类型的值时,不可以用xxx.value否则无法监视到。

    (2)监视ref定义的对象属性时,需要用xxx.value否则由于内存中地址未改变,无法监视到ref请求reactive生成的Proxy的代理类,也可以开深度监视来实现,监视对象属性中的内容。

    8.2.7.3 wactcEffect函数

    watcg:既要指明监视的属性,也要指明监视的回调。

    watchEffect:不指明监视的属性,在回调中用到了哪个属性就监视哪个属性。

    watchEffect优点类似于computed:

            computed注重的是结果(回调函数的返回值),所以必须return。

            watchEffect注重的是过程(回调的函数体),所以不用写返回值。

        watch(data, (newValue, oldValue) => {
          console.log("person变化了", newValue, oldValue);
        },{immediate:true}); 
    
        watchEffect(()=>{
          console.log('watchEffect的回调')
          const x=data.age
        })

    8.2.8 Vue3中的生命周期

    Vue3.0中可以继续使用Vue2.x的生命周期钩子,但是有两个被更名:        

    beforeDestroy===》beforeUnmount
    destroyed    ===》unmounted

    Vue3.0也提供了Composition API形式的生命周期钩子,与Vue2.x对应关系如下:

           

    beforeCreate   ===>    setup()
    created        ===>    setup()
    beforemount    ===>    onBeforeMount
    mounted        ===>    onMounted
    befoerUpdate   ===>    onBeforeUpdate
    updated        ===>    onUpdated
    beforeUnmount  ===>    onBeforeUnmount
    unmounted      ===>    onUnmounted

    App:

    
    
    
    

    Demo:

    
    
    
    

    8.2.9 自定义hook函数

    定义:本质是一个函数,把steup函数中使用的Composition API进行的封装。

    类似于Vue2.x中的mixin。

    自定义hook的优势:服用代码,让setup中的逻辑更加清楚。

    新建hooks文件夹,并创建功能对应的js文件(以点击获取鼠标当前xy轴位置为例):

     userPoint.js

    import {
        reactive,
        onMounted,
        onBeforeUnmount
    } from "vue";
    
    export default  function () {
        let point = reactive({
            x: 0,
            y: 0
        })
        function savePiont(event) {
            point.x = event.pageX
            point.y = event.pageY
            console.log(event.pageX)
            console.log(event.pageY)
        }
        onMounted(() => {
            window.addEventListener('click', savePiont)
        }),
            onBeforeUnmount(() => {
                window.removeEventListener('click', savePiont)
            })
        return point
    }
    

    Demo.vue

    
    
    
    

    8.2.10 toRef

    作用:创建一个ref对象,其value指向另一个对象中的某个属性。

    语法:const name=toRef(person,'name')。

    应用:将响应式对象中的某个属性单独提供给外部使用时。

    扩展:toRefs与toRef功能一致,但是可以创建多个ref对象,已发toRefs(person)。

    
    
    
    

    8.3 其他Composition API

    8.3.1 shallowReactive和shallowRef

    shallowReactive:只处理对象最外层属性的响应式(浅响应式)。

    shallowRef:只处理基本数据类型的响应式,不进行对象响应式的处理。

    使用场景:

            如果有一个对象,结构比较深,但是变化时值是外层属性变化===》shallowReactive。

            如果有一个对象,后续不会修改对象属性,而是产生新的对象替换===》shallowRef。

    8.3.2 readonly和shallowReadonly

    readonly:让一个响应式数据变为只读的(深只读)。

    shallowReadonly:让一个响应式数据变为只读的(浅只读)。

    使用场景:不希望数据被修改时。

    8.3.3 toRaw和markRaw

    toRaw:

            作用:讲一个有reactive生成的响应式对象转为普通对象。(ref的不行)

            使用场景:用于读取响应式对象对应的普通对象,对这个普通对象的所有操作不会引起

                              页面的更新。

    markRaw:

            作用:标记一个对象,使其永远不会在成为响应式对象。

            使用场景:

                    (1)如果我们声明了一个reactive的对象,后续对这个对象进行属性添加的操作,

                             添加上的属性默认就是响应式的,而有些值不应该设置为响应式的,例如:

                             异常复杂的第三方类库等等。

                    (2)当显然具有不可变数据源的大列表时,条过响应式转换可以提高性能。

    8.3.4 customRef

    作用:创建一个自定义的ref,并对其依赖项跟踪和更新出发进行显示控制(可以实现自定义的控制页面更新时机,track告诉get方法这个参数需要跟踪,triger通知vue更新dom)。

    实现防抖:

    
    
    
    

    8.3.5 provide与inject

    作用:实现祖与后代组件之间的通信。

    父组件中有一个provide选项来提供数据,后代组件有一个inject选项来开始使用这些数据。

    具体写法:

    祖组件:

    setup() {
        let car=reactive({
          name:'奔驰',
          price:400000
        })
        //给自己的后代组件传递数据
        provide('car',car)

    后代组件:

     let car=inject('car')
        console.log("二级子组件",car)
      },

    8.3.6 响应式数据的判断

    isRef:检查一个值是否为ref对象。

    isReactive:检查一个值是否是由reactive创建的响应式代理。

    isReadonly:检查一个对象是否是由readonlu创建的只读代理。

    isProxy:检查一个对象是否由reactive或者readonly方法创建。

    8.4 Composition API的优势

    8.4.1 Options API 

    传统的OptionsAPI(配置API)中,新增或修改一个需求,要分别在data,methods,computed里修改

    8.4.2 Composition API

    让相同功能的变量,函数等等更加有序的组织在一起(借助hook函数)。

    8.5 新的组件

    8.5.1 Fragment

    在Vue2.x中,组件必须有一个跟标签。

    在Vue3中,组件可以没有跟标签,内部会将多个标签包含在一个Fragment的虚拟内存中。

    优势:减少标签层级,减小内存占用。

    8.5.2 Teleprot

    概念:Teleprot是一种能够将我们组件中的html结构移动到指定位置的技术。

    
    
    
    

    将代码直接传送到html的body内。

    8.5.3 Suspense

    等待异步组件时渲染一些额外内容,让应用有更好的用户体验。

    使用步骤:

            异步引入组件:

    import { defineAsyncComponent } from "vue";
    const Demo = defineAsyncComponent(() => import("./componets/Demo1.vue"));

    使用Supense包裹组件,并配置好default与fallback:

    
          
          
        

    8.6 其他

    8.6.1 全局API转移

    Vue2.x中有序地全局API和配置。

    例如:注册全局组件,注册全局指令等等

    //全局组件
    Vue.component('MyButton',{
    data:()=>({
        cont:0
    }),
    template:''
    })
    //全局指令
    Vue.directive('focus',{
        inserted:el=>el.focus()
    })

    Vue3对这些API做出了调整:

            将全局API(Vue.xxx)调整到应用实例app上

    Vue2-Vue3学习笔记(全)_第13张图片

    8.6.2 其他改变

    8.6.2.1 data选项

    data选项始终都要被声明为一个函数。

    8.6.2.2 过渡类名的更改

            Vue2.x写法:

    v-enter,
    v-leave-to{
        opacity:0
    }
    v-leave,
    v-enter-to{
        opacity:1
    }

            Vue3写法:

    .v-enter-from,
    v-leave-to{
        opacity:0
    }
    .v-leave-from,
    v-enter-to{
        opacity:1
    }
    8.6.2.3 移除keyCode

    移除keyCode作为v-on修饰符,同时也不再支持config.keyCodes

    8.6.2.4 移除native

    移除native作为v-on修饰符:

            父组件绑定事件:

            子组件js声明自定义事件(不声明则被认为是js原生事件):

    export default {
        emits:['close']
    }
    8.6.2.5 移除过滤器

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

    7.Vue UI库

    7.1移动端常用的UI

    (1) Vant:Vant 4 - A lightweight, customizable Vue UI library for mobile web apps.A lightweight, customizable Vue UI library for mobile web apps.icon-default.png?t=N7T8https://vant-ui.github.io/vant/#/zh-CN

    (2)Cube UI:cube-ui: cube-ui 是由滴滴开源的基于 Vue.js 实现的移动端组件库icon-default.png?t=N7T8https://gitee.com/mirrors/cube-ui

    (3)Mint UI:

    Mint UIicon-default.png?t=N7T8https://mint-ui.github.io/#!/zh-cn

    7.2 PC端常用UI

    (1)Element UI:

    Element - The world's most popular Vue UI frameworkElement,一套为开发者、设计师和产品经理准备的基于 Vue 2.0 的桌面端组件库icon-default.png?t=N7T8https://element.eleme.io/(2)IView UI:

    iView / View Design 一套企业级 UI 组件库和前端解决方案基于 Vue.js 的 UI 组件库,用于研发企业级中后台产品。iView 官网。icon-default.png?t=N7T8https://www.iviewui.com/

    使用UI组件库一般按需引入。

     欢迎补充。

    你可能感兴趣的:(java)