vue3技术整理( 基础 )

0、前言

vue2基础篇链接:https://www.cnblogs.com/xiegongzi/p/15782921.html

vue2组件化开发篇链接:https://www.cnblogs.com/xiegongzi/p/15823605.html

vue2高级篇链接:https://www.cnblogs.com/xiegongzi/p/15875808.html

1、创建vue3项目

官网文档:https://cli.vuejs.org/zh/guide/creating-a-project.html#vue-create

1.1、使用vue-cli创建

注意:需要保证自己的vue-cli版本在4.5.0以上

查看自己@vue/cli版本
Vue -V

安装或升级@vue/cli
npm install -g @vue/cli

创建Vue3项目
vue create 项目名

使用ui可视化界面创建
ps:会在浏览器中打开一个管理窗口,进行手动创建和配置选项,目前不建议用,学完所有就可以使用了
vue ui

启动Vue3项目
cd 进入到创建的项目中
npm run serve

vue3技术整理( 基础 )

vue3技术整理( 基础 )

vue3技术整理( 基础 )

vue3技术整理( 基础 )

1.2、使用vite创建

官网地址;https://v3.cn.vuejs.org/guide/installation.html#vite

vue3技术整理( 基础 )

vite是另一门技术,是下一代的前端构建工具
ps:是vue官网打造的,久一代的就是webpack 】。vite官网地址 https://vitejs.cn/

vite的优势:

[TencentCloudSDKException] code:FailedOperation.ServiceIsolate message:service is stopped due to arrears, please recharge your account in Tencent Cloud requestId:d103021b-8ccc-47e6-ba2e-d5f27922d712

[En]

[TencentCloudSDKException] code:FailedOperation.ServiceIsolate message:service is stopped due to arrears, please recharge your account in Tencent Cloud requestId:ca60cfba-ea3f-45ba-ada5-beeae5a609f9

* 轻量快速的热重载( HMR ) ps:webpack也可以热部署,只是vite更轻量和快
– 快体现在热部署的方式不同 ps:官网中有对比图

vue3技术整理( 基础 )
  • 真正的按需编译,无需等待整个应用编译完成再启动【 ps:图中我解读的哪里,是根据路由再找模块 】

整理vite创建vue3的相关指令

创建项目
npm init vite-app 项目名

进入项目目录
cd 项目名

安装依赖
npm install

运行项目
npm run dev

vue3技术整理( 基础 )

vue3技术整理( 基础 )

vue3技术整理( 基础 )

vue3技术整理( 基础 )

2、分析vue-cli创建的vue3项目

使用vscode打开vue-cli创建的项目

2.1、查看整个目录结构

vue3技术整理( 基础 )

vue3技术整理( 基础 )

2.2、分析入口文件main.js

vue3技术整理( 基础 )

其他的东西和vue2中没什么两样

注意点:template中的写法和vue2相比有点变化

vue3技术整理( 基础 )

3、安装vue3的开发者工具

注意:这里安装的测试版(beta)

直接使用google进行安装即可,要是无法进入google应用商店的话,那么:去百度chrome插件网就可以了;或者:下载一个佛跳墙 / 极光
ps:佛跳墙现在的名字貌似改为极光了,下载安装之后,直接链接,然后就可以FQ了,当然还有其他更好的F墙方式

注意:vue2和vue3的开发者工具最好别一起开启,开了vue2就别开vue3,开了vue3就别开vue2,很容器出问题

4、认识基本的Composition API / 组合式API

4.1、认识setup函数

setup是Compostition API / 组合式API的地基,setup是一个函数,且必须有返回值 ,玩vue3,那么就需要提供一个平台,而这个平台就是setup

4.1.1、对setup函数快速上手


  姓名: {{name}}
  性别: {{sex}}
  工种: {{job}}

  调用一下vue3的setup中定义的方法

export default {
  name: 'App',

  // 一、配置setup平台
  setup(){
    // 这里面的配置和vue2中的差不多,什么数据、方法、计算属性、生命周期.......只是写法有区别

    // 配置数据【 ps:直接定义即可 】
    let name = '紫邪情';
    let sex = '女';
    let job = 'Java';

    // 配置方法
    function helloword(){
      // 注意点:alert()里面用的是模板字符串 - 飘字符嘛;${name}就是取上面定义的数据
      alert(我叫: ${name},性别: ${sex}.工种: ${job})
    }

    // setup必须有返回值 return - 就是为了把setup配置的东西交出去嘛,不然别人怎么拿到
    // 但是:return有两种写法

    // 1、对象写法
    return {
      // 返回数据
      name,sex,job,

      // 返回方法
      helloword
    }
  }
}

vue3技术整理( 基础 )

补充:setup函数返回值的另一种写法:返回渲染函数写法 – 了解即可【 ps:这是为了自定义渲染内容的 】

第一步:引入渲染函数h,指令: import {h} from 'vue'

第二步:使用渲染函数 并 返回

// 2、第二种写法:返回渲染函数 - 了解即可
// 这种写法:会将下面自定义写的渲染内容 放到 前面template中去渲染
// 即:template的渲染依赖于下面自定义内容

// 第一步:需要在本组件中引入渲染函数h
// 第二步:使用渲染函数 并 返回
// return ( (h) => h( 'h1', '这是setup中的返回渲染函数用户') )
// 简写
return () => h('h1','这是setup中的返回渲染函数用户')

vue3技术整理( 基础 )

vue3技术整理( 基础 )

4.1.2、聊聊setup函数的细节问题

setup和vue2的写法一起用 -最好:坚决别用

vue3技术整理( 基础 )

vue3技术整理( 基础 )

原因:是因为vue3向下兼容嘛,所以:可以加入vue2的写法

但是:说过不建议vue3和vue2混合使用。来演示一下bug

vue3技术整理( 基础 )

vue3技术整理( 基础 )

注意:反过来就可以啊,即:在vue2的配置中可以获取setup函数中配置的东西,演示就跳过了

另外还有一个注意点:如果采用vue2的配置和vue3的setup中配置了相同的东西,那么:优先使用setup中的,如:在vue2的配置中配置了address数据,又在vue3的setup中配置了address数据,那么:优先使用的是setup中的

setup()的另外一个注意点 和 其可以接收的两个参数 – 演示自行玩

setup执行时机:

  • 在beforeCreate之前执行一次,同时在setup(){ }中的this是undefined,即:在setup中不可以用this拿到东西 【 ps:可以试着定义一个beforeCreate和setup,里面都输出一句话,看控制台谁的话在前面即可 】

setup可以接受的两个参数:

  • props:值为对象, 包含:组件外部传递过来 且 组件内部声明接收了的属性 【 ps:也就是在组件内部和vue2一样配置了props配置项 – 有三种配置方式,vue2的基础知识,滤过了 】
  • 注意点:若在外部传递了数据,而内部没有配置props配置项进行声明接收,那么:vue2中不会有什么错误,但是:在vue3中就会在控制台抛错
  • context:上下文对象 ps:它里面有三个属性
  • attrs:俗称捡漏王。值为对象, 包含:组件外部传递过来,但没有在props配置中声明的属性,相当于vue2中的 this.$attrs
    • 换言之:就是如果父组件传递了数据,但:子组件中的props配置没有声明要接收,那么:传递的数据就在子组件的attrs属性上
  • slots:看名字就知道,就是收到的插槽内容,相当于vue2中的 this.$slots
  • emit:也是看名字就知道的,触发自定义事件的函数嘛,相当于vue2中的 this.$emit
    • 但是:注意在vue3中,这个东西根据vue2的正常写法,好使,可是:控制台会抛警告,不想看到警告,那就在使用了这个emit的组件中,配置一个 emits配置项即可 – 和props声明接收属性的配置一样,如: emits: ['getField']

4.1.3、vue3的setup函数总结

所谓的setup,就是vue3中的一个全新配置项而已,值是一个函数,它是vue3中Composition API / 组合式API的地基,且这个setup函数必须有一个返回值

组件中所用的:数据、方法、计算属性、生命周期等,均可配置在setup函数中【 ps:注意写法不太一样 】

setup函数的两种返回值写法:

  • 1、返回一个对象,若是这种:那么对象中的属性、方法等,在template模板中均可以直接使用 – 重点
  • 2、返回一个渲染函数,这种方式是为了自定义渲染内容,玩法如下:
  • 1)、引入渲染函数h,指令: import {h} from 'vue'
  • 2)、使用,如指令: return () => h('h1','这是setup中的返回渲染函数用户')

注意点:

  • 1、尽量不要与vue2的配置混合使用
  • 在vue2配置( data、methods、computed… )中可以访问到setup函数中的属性、方法等
    • 但是:在setup函数中不能访问到vue2中配置的内容
    • 如果setup和vue2中的配置有重名的,则:优先使用setup中的配置
  • setup不能是一个async函数,因为返回值不再是retunr的对象,而是promise,这样的话:模板看不到return对象中的属性

setup()的另外一个注意点 和 其可以接收的两个参数

  • setup执行时机:
  • 在beforeCreate之前执行一次,同时在setup(){ }中的this是undefined
  • setup可以接受的两个参数:
  • props:值为对象, 包含:组件外部传递过来 且 组件内部声明接收了的属性
    • 注意点:若在外部传递了数据,而内部没有配置props配置项进行声明接收,那么:vue2中不会有什么错误,但是:在vue3中就会在控制台抛错
  • context:上下文对象 【 ps:它里面有三个属性 】
    • attrs:俗称捡漏王。值为对象, 包含:组件外部传递过来,但没有在props配置中声明的属性,相当于vue2中的 this.$attrs
    • 换言之:就是如果父组件传递了数据,但:子组件中的props配置没有声明要接收,那么:传递的数据就在子组件的attrs属性上
    • slots:看名字就知道,就是收到的插槽内容,相当于vue2中的 this.$slots
    • emit:也是看名字就知道的,触发自定义事件的函数嘛,相当于vue2中的 this.$emit
    • 但是:注意在vue3中,这个东西根据vue2的正常写法,好使,可是:控制台会抛警告,不想看到警告,那就在使用了这个emit的组件中,配置一个 emits配置项即可 – 和props声明接收属性的配置一样,如: emits: ['getField']

4.2、ref函数

先做一个实例:修改setup中的数据


  vue3的setup函数得到的操作
  姓名: {{name}}
  性别: {{sex}}
  修改setup中的数据

export default {
  name: 'App',

  // 一、配置setup平台
  setup(){

    let name = '紫邪情';
    let sex = '女';

    function changeData(){
      name = '紫邪晴'
      sex = '男'
      console.log("修改之后的数据: ",name,sex);
    }

    // 1、对象写法
    return {
      // 返回数据
      name,sex,

      // 返回方法
      changeData
    }
  }
}

vue3技术整理( 基础 )

没实现出来,原因就是:vue不认你的修改,因此:需要借助ref函数来套娃

4.2.1、看看ref函数的真身


  vue3的setup函数得到的操作
  姓名: {{name}}
  性别: {{sex}}
  修改setup中的数据

import {ref} from 'vue'
export default {
  name: 'App',

  // 一、配置setup平台
  setup(){

    // 使用ref函数来进行实现,进行套娃,把数据丢给ref函数进行管理
    let name = ref('紫邪情');
    let sex = ref('女');

    function changeData(){
      // console.log("修改之后的数据: ",name,sex);

      // 看一下ref函数的真身
      console.log(name);
    }

    // 1、对象写法
    return {
      // 返回数据
      name,sex,

      // 返回方法
      changeData
    }
  }
}

vue3技术整理( 基础 )

既然知道了ref函数的真身,那么:想要实现数据的改变就变得轻松了

vue3技术整理( 基础 )

vue3技术整理( 基础 )

有个注意点

vue3技术整理( 基础 )

4.2.2、使用ref处理对象类型

4.2.2.1、看一下ref函数中套对象的样子是怎样的

  工种: {{job.type}}
  薪资: {{job.salary}}
  查看一下ref函数中套对象的样子

import {ref} from 'vue'
export default {
  name: 'App',

  // 一、配置setup平台
  setup(){
    // 套对象在ref中
    let job = ref({
      type: 'Java',
      salary: '20k'
    });

    function changeData(){
      // 先看一下ref中套对象的样子是怎样的
      console.log(job.value);
    }

    // 1、对象写法
    return {
      // 返回数据
      job,
      // 返回方法
      changeData
    }
  }
}

vue3技术整理( 基础 )

既然知道了ref函数中套了对象的样子长什么样的,那么:想要修改ref里面套的对象的属性就很好操作了

4.2.2.2、修改ref函数中对象的属性值

vue3技术整理( 基础 )

vue3技术整理( 基础 )

小小总结一下

ref函数修饰的是基本类型时【 ps:即直接用let name = ref(‘紫邪情’) 】,则:数据代理就是Object.dinfineProperty的setter和getter

ref函数修饰的是对象类型时【 ps:即let job = ref( { } 】,则:数据代理的原理是Proxy对象【 ps:window的ES6的全新配置 。这个对象后续会进行说明 】

4.2.3、对ref函数小小总结一波

[TencentCloudSDKException] code:FailedOperation.ServiceIsolate message:service is stopped due to arrears, please recharge your account in Tencent Cloud requestId:e9f69aed-d2a1-408a-be00-b7cbf7f9cf80

[En]

[TencentCloudSDKException] code:FailedOperation.ServiceIsolate message:service is stopped due to arrears, please recharge your account in Tencent Cloud requestId:09e219de-edf0-4da5-b89f-7bc6dbda6e59

ps:即,修改数据之后可以把改后的数据渲染到页面中

语法: const xxx = ref(initValue)

[TencentCloudSDKException] code:FailedOperation.ServiceIsolate message:service is stopped due to arrears, please recharge your account in Tencent Cloud requestId:23edcc8c-3ac6-4d3e-9a3c-f331a45368c5

[En]

[TencentCloudSDKException] code:FailedOperation.ServiceIsolate message:service is stopped due to arrears, please recharge your account in Tencent Cloud requestId:37e6710d-02a0-4e6c-91ee-ca978a89f9c4

* js中操作数据: xxx.value
* 模板中读取数据:不需要.value,直接: <div>{{xxx}}</div>

注意点:

  • ref()函数中接收的数据可以是:基本类型、也可以是对象类型
  • ref函数修饰的是基本类型时 ps:即直接用let name = ref(‘紫邪情’),则:数据代理就是Object.dinfineProperty的setter和getter
  • *ref函数修饰的是对象类型时 ps:即let job = ref({}),则:数据代理的原理是Proxy对象 ps:这个对象其实是由Object转了一遍,即:Object ——> Proxy,而这个对象window的ES6的全新配置 。这个对象后续会进行说明,对象内部 / 属性实质是借助了vue3的一个新函数 ——reactive()&#x51FD;&#x6570;

4.3、认识reactive()函数 – 深度监视

这个函数就是专门用来处理数据是对象 / 数组类型的

reactive()函数不能处理基本类型,想要处理基本类型,那么:就使用ref()函数

ref( { } )这里面套对象的类型时,它的原理就是调用了reactive()函数

简单玩一下reactive()函数

1、引入reactive()函数,指令: import {reactive} from 'vue'
2、使用reactive()函数


  ref托管的数据
  {{name}}

  reactive托管的数据
  {{job.type}}
  {{job.salary}}

  修改ref和reactive托管的数据

import {ref,reactive} from 'vue'
export default {
  name: 'App',

  // 一、配置setup平台
  setup(){
    // 配置基本类型数据 - 通过ref实现
    let name = ref('紫邪情');
    // 使用reactive来管理数据
    let job = reactive({
      type: 'Java',
      salary: '20k'
    })
    // 修改基本类型数据
    function changeData(){
      // 修改ref管理的数据类型
      name.value = '紫邪晴';

      // 修改reactive托管的数据 - 相比ref,不再跟value了
      job.type = 'C';
      job.salary = '3毛';
    }

    return {
      // 返回基本类型数据 - ref托管
      name,

      // 返回reactive托管的数据
      job,

      // 返回函数
      changeData,
    }
  }
}

vue3技术整理( 基础 )

了解reactive的细节问题

前面说:reacitve()函数不能处理基本类型,那测试一下

vue3技术整理( 基础 )

vue3技术整理( 基础 )

reacitve()函数托管数组类型

vue3技术整理( 基础 )

vue3技术整理( 基础 )

想让reactive()函数也能够托管基本类型的数据,怎么办?

  • 把基本类型 使用 对象写法嘛,包装一下呗

vue3技术整理( 基础 )

vue3技术整理( 基础 )

reactive()函数深度监视效果

vue3技术整理( 基础 )

vue3技术整理( 基础 )

4.3.1、对reactive()函数总结一波

作用:定义一个对象类型的响应式数据【 ps:基本类型别用它,用ref函数 】

语法:

  • 引入reactive()函数,指令: import {reactive} from 'vue'
  • 使用: const &#x4EE3;&#x7406;&#x5BF9;&#x8C61; = reactive(&#x6E90;&#x5BF9;&#x8C61;)接收一个对象 / 数组,返回一个代理对象 / proxy对象

reactive定义的响应式数据时”深层次的”

reactive的内部是基于ES6的Proxy实现的,通过代理对象操作源对象内部数据

4.4、vue3中数据监视的原理

4.4.1、Proxy数据监视原理

vue2中数据监视如果是对象类型的,那么是通过Object.defineProperty()的getter和setter来做到数据监视的;如果是数组类型那么就是通过那7个API做到数据监视,但是这种方式有弊端,如下:

[TencentCloudSDKException] code:FailedOperation.ServiceIsolate message:service is stopped due to arrears, please recharge your account in Tencent Cloud requestId:90589c6d-22ce-43ef-a47a-d83ebf778176

[En]

[TencentCloudSDKException] code:FailedOperation.ServiceIsolate message:service is stopped due to arrears, please recharge your account in Tencent Cloud requestId:bc036302-741b-4244-a826-f15ab6fd65be

[TencentCloudSDKException] code:FailedOperation.ServiceIsolate message:service is stopped due to arrears, please recharge your account in Tencent Cloud requestId:d655416b-3445-4cfd-8904-e140357e63ec

[En]

[TencentCloudSDKException] code:FailedOperation.ServiceIsolate message:service is stopped due to arrears, please recharge your account in Tencent Cloud requestId:48afe3a2-c8e3-41ef-943c-7b918b3735ad

但是:vue3中就不会出现上面的几种情况

先来看一下Proxy长什么样子

vue3技术整理( 基础 )

vue3技术整理( 基础 )

使用Proxy进行修改数据


    研究Proxy监视数据原理

        // 定义一个对象
        let person = {
            name: '紫邪情',
            sex: '女'
        }

        // 利用Window.Proxy()来进行修改person

        // 先看一下Proxy的样子
        // console.log( new Proxy(person,{} ) );

        // 使用Proxy进行数据修改
        /*
            people 就是代理对象 它代理的就是person
            new Proxy()就是创建一个代理对象嘛 - 后端的人太熟悉不过了
        */
        const people = new Proxy( person, {
            // 获取对象的属性时调用
            /*
            target 就是源对象 即:person
            propName  就是对象中的属性名  如:name、sex.....

            */
            get(target,propName){
                console.log( "target,propName这两个参数为: ", target,propName);
                console.log(有人获取person中的${propName}属性);
                return target[propName];
            },

            // 修改对象中的属性时调用【 ps:修改含增、改、删除是另一个配置 】
            // value就是修改之后的值
            set( target,propName,value ){
                console.log( "target,propName,value这三个参数为: ", target,propName,value);
                console.log( 有人修改person中的${propName}属性 );
                return target[propName] = value;
            },

            // 删除对象中的属性时调用
            deleteProperty(target,propName){
                console.log( "target,propName这两个参数为: ", target,propName);
                return delete target[propName];
            }
        })

vue3技术整理( 基础 )

4.4.2、Reflect数据监视原理

在vue3中数据监视不止用了window的Proxy对象,还用了window的Reflect对象

Reflect就是反射的意思,这个东西对于玩Java的人来说再熟悉不过了,所以不再过多介绍,在前端中这个是ES6的特性

认识Reflect对象

看看Reflect长什么样

// 先看看Reflect长什么样
console.log(window.Reflect);

vue3技术整理( 基础 )

经过上图的查看之后,其实也就知道Reflect改怎么玩了,调对应的API就可以了
ps:ECMA组织正打算把常用的一些API放到Reflect对象身上,如:目前把Object.defineProperty()就放在Reflect中了 – vue2的数据代理原理的API

使用Reflect实现数据监视

let person = {
    name: '紫邪情',
    sex: '女'
}

// 先看看Reflect长什么样
// console.log(window.Reflect);

// 使用Reflect实现数据监视

// 1、获取对象的属性 - key-value的形式
/*
    key 就是对象名
    value 就是对象的属性名
*/
Reflect.get(person,'name');

// 2、修改对象的属性
Reflect.set(person,'sex','男');
Reflect.set(person,'age', '18');

// 3、删除对象的属性
Reflect.deleteProperty(person,'sex');

vue3技术整理( 基础 )

注意:使用Reflect做对应的操作之后是有返回值的,如:Reflect.set( person,’age’,18 ),返回值是true,所以:就可以利用这个返回值做很多事情,如:进行封装,而Object.defineProperty()并没有返回值

同时:Reflect支持属性名重复,即:若用set()这个API对同一个对象的同一个属性做多次相同的操作,则:不会返回异常,而是返回true / false,因此:才说可以用这个返回值做很多事情;若用Object.defineProperty()来进行相同的操作,则:会直接抛异常,甚至想要后续的代码还能运行,就只能使用try……catch….来对该部分的代码进行包裹了

vue3真正做到数据监视的原理 – 使用Proxy和Reflect对象进行套娃


    vue3实现数据监视的真正原理

        let person = {
            name: '紫邪情',
            sex: '女'
        }

        const people = new Proxy( person, {
            // 获取对象的属性时调用
            get(target,propName){
                console.log( "target,propName这两个参数为: ", target,propName);
                console.log(有人获取person中的${propName}属性);
                // 此处进行了Reflect套娃
                // return target[propName];
                return Reflect.get(target,propName);
            },

            // 修改对象中的属性时调用【 ps:修改含增、改、删除是另一个配置 】
            set( target,propName,value ){
                console.log( "target,propName,value这三个参数为: ", target,propName,value);
                console.log( 有人修改person中的${propName}属性 );
                // 此处进行了Reflect套娃
                // return target[propName] = value;
                return Reflect.set(target,propName,value);
            },

            // 删除对象中的属性时调用
            deleteProperty(target,propName){
                console.log( "target,propName这两个参数为: ", target,propName);
                // 此处进行了Reflect套娃
                // return delete target[propName];
                return Reflect.defineProperty(target,propName);
            }
        })

4.4.3、vue3中数据监视原理总结

通过Proxy代理对象:拦截对象中任意属性的变化,包括:属性值的读写、属性的添加、属性的删除等

通过Reflect反射对象:对被代理对象的属性进行操作,例子如下:

const people = new Proxy(person, {
    // 拦截读取属性值
    get(target,propName){
        console.log( "target,propName这两个参数为: ", target,propName);
        console.log(有人获取person中的${propName}属性);
        // 此处进行了Reflect套娃
        // return target[propName];
        return Reflect.get(target,propName);
    },

    // 拦截修改属性值【 ps:是修改和新增 】
    set( target,propName,value ){
        console.log( "target,propName,value这三个参数为: ", target,propName,value);
        console.log( 有人修改person中的${propName}属性 );
        // 此处进行了Reflect套娃
        // return target[propName] = value;
        return Reflect.set(target,propName,value);
    },

    // 拦截删除属性值
    deleteProperty(target,propName){
        console.log( "target,propName这两个参数为: ", target,propName);
        // 此处进行了Reflect套娃
        // return delete target[propName];
        return Reflect.defineProperty(target,propName);
    }
})

另外:附上Proxy和Reflec对象说明的官网链接

Proxy:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Proxy

Reflect:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Reflect

4.5、reactive() 和 ref()的对比

从定义数据角度对比

  • ref用来定义:基本类型数据
  • reactive用来定义:对象 / 数组类型数据
  • 注:ref也可以用来定义对象 / 数组类型数据,它内部会自动通过reactive转成Proxy代理对象

从原理角度对比:

  • ref通过 Object.defineProperty()的get和set来实现的数据劫持 / 数据监视 / 响应式
  • reactive通过使用Proxy代理对象来实现数据劫持,并通过Reflect操作源对象内部的数据

从使用角度对比:

  • ref定义的数据:操作数据需要 .value,读取数据时模板中直接读取,不需要 .value
  • reactive定义的数据:操作数据与读取数据,均不需要 .value

4.6、Vue3中的Computed 计算属性函数

其实和uve2中的计算属性没什么两样,只是多了一步引入的问题 以及 排放的问题问题而已


  姓;

  名:

  全名: {{person.fullName}}

import { reactive } from '@vue/reactivity'

// 1、引入computed计算属性函数
import { computed } from '@vue/runtime-core'

export default {
  name: 'App',

  setup(){

    // 数据
    let person = reactive({
      firstName: '紫',
      lastName: '邪情'
    })

    // 2、使用计算属性函数 setup中this无效,所以computed()中使用兰姆达和正常写法都无所谓
    // 简写形式 - 只考虑读的问题
    person.fullName = computed(()=>{
      return person.firstName + "-" + person.lastName;
    })

    // 完整写法 - 考虑读和改的问题
   /*  person.fullName = computed({
      get(){
        return person.firstName + "-" + person.lastName;
      },

      set(value){
        const nameDataArr = value.split('-')
        person.firstName = nameDataArr[0]
        person.lastName = nameDataArr[1]
      }
    }) */

    // 返回数据
    return {
      person,
    }
  }
}

4.7、vue3中的watch 监视属性函数

和vue2中的watch也差不多

4.7.1、监视ref()定义的数据

这个猫玩意儿和vue2中差不多

简单写法:监视ref托管的单个响应式数据


  当前值为: {{num}}
  num++

// 1、引入watch函数
import { ref, watch } from '@vue/runtime-core'

export default {
  name: 'App',

  setup(){

    // 准备数据 - 用ref托管
    let num = ref(0)

    // 一、简单写法
    // 2、使用watch函数
    /*
      可以接受三个参数
          第一个:监视的是谁?
          第二个:回调函数 - 新值 和 旧值
          第三个:配置项 - deep深度监视也可以配置
    */
    watch(num , (newValue,oldValue)=>{
      console.log("num的值发生改变了",newValue,oldValue);
    },{immediate:true})

    return {
      num,
    }
  }
}

vue3技术整理( 基础 )

监视多个属性:监视ref托管的多个响应式数据【 ps:数组写法 】


  当前名字为: {{name}}

  改变name

// 1、引入watch函数
import { ref, watch } from '@vue/runtime-core'

export default {
  name: 'App',

  setup(){

    // 准备数据 - 用ref托管
    let num = ref(0)

    let name = ref('紫邪情')

    // 监视ref托管的多个响应式数据 - 变化就在这里 监事的是谁?采用数组写法即可
    watch([num,name],(newValue,oldValue)=>{
      console.log("num 和 name的值发生改变了",newValue,oldValue);
    },{immediate:true})
    return {
      num,name
    }
  }
}

4.7.2、监视reactive()定义的数据

监视reactive托管的一个响应式数据中的全部属性


  姓名:
  性别:
  地址:

  姓名: {{person.name}}
  性别: {{person.sex}}
  地址: {{person.address.detailed.value}}

import { reactive } from '@vue/reactivity'
import { watch } from '@vue/runtime-core'

export default {
  name: 'App',

  setup(){

    // 准备数据 - 用reactive托管
    let person = reactive({
      name: '紫邪情',
      sex: '女',
      address: {
        detailed: {
          value: '浙江省杭州市'
        }
      }
    })

    // 监视reactive托管的一个响应式数据中的全部属性
    watch(person,(newValue,oldValue)=>{
      console.log("person被修改了", newValue,oldValue);
    })

    return {
      person,
    }
  }
}

vue3技术整理( 基础 )

上面这种坑就是在监视此种reactive托管的一个响应式数据的全部属性时,并不能获得旧值oldValue,因为:旧值oldValue和新值newValue一样

但是:还有一种坑,就是:此种类型是强制开启了深度监视,即:配置 deep:false不顶用

vue3技术整理( 基础 )

vue3技术整理( 基础 )

监视reactive托管的一个响应式数据中的某一个属性

// 类型二、监视reactive托管的一个响应式数据中的某一个属性

/*
  奇葩的地方:
      1、要监视的这个属性需要写成函数式 ()=> person.name
      2、可以争取获取newValue、oldValue
*/
watch(()=> person.name , (newValue,oldValue)=>{
  console.log("person中的name属性被修改了",newValue,oldValue);
})

vue3技术整理( 基础 )

监视reactive托管的一个响应式数据中的某些属性 – 函数式数组写法

// 类型三、监视reactive托管的一个响应式数据中的某些属性

/*
  奇葩的地方:
      1、监视的多个属性需要使用数组套起来
      2、数组中的每一个属性需要写成函数式
*/
watch([()=> person.name , ()=> person.sex] , (newValue,oldValue)=>{
  console.log("person中的name和sex属性被修改了",newValue,oldValue);
})

vue3技术整理( 基础 )

特殊情况:监视reactive托管的一个响应式数据中的某一个属性【 ps:此属性套娃了,又是一个对象 】

// 类型四、监视reactive托管的一个响应式数据中的某个属性,但:此属性又套娃了

/*
  奇葩的地方:
      1、需要开启深度监视 即:deep:true 又生效了
      2、不加 deep:true配置,代码会无效
*/
watch(()=> person.address , (newValue,oldValue)=>{
  console.log("person中的address属性被修改了",newValue,oldValue);
},{deep:true})

vue3技术整理( 基础 )

但是:如果不加 deep:true配置呢?

vue3技术整理( 基础 )

vue3技术整理( 基础 )
4.7.2.1、监视reactive托管的一个响应式数据的各种类型总结

注:在vue3中可以同时配置多个watch,而在vue2中配置重复的,那只有前者有效

// 准备数据 - 用reactive托管
let person = reactive({
  name: '紫邪情',
  sex: '女',
  address: {
    detailed: {
      value: '浙江省杭州市'
    }
  }
})

// 类型一、监视reactive托管的一个响应式数据中的全部属性
/*
  此种类型的坑:
      1、无法正确获得oldValue的值【 ps:因newValue和oldValue的值一样 】
      2、简直强制开启了深度监视 【 ps:即deep:false配置无效 】
*/
watch(person,(newValue,oldValue)=>{
  console.log("person被修改了", newValue,oldValue);
},{deep:false})
/*
  如:这里关闭深度监视 理论上:应该监视不到address.detailed.value
      但是:天真
*/

// 类型二、监视reactive托管的一个响应式数据中的某一个属性
/*
  奇葩的地方:
      1、要监视的这个属性需要写成函数式 ()=> person.name
      2、可以争取获取newValue、oldValue
*/
watch(()=> person.name , (newValue,oldValue)=>{
  console.log("person中的name属性被修改了",newValue,oldValue);
})

// 类型三、监视reactive托管的一个响应式数据中的某些属性
/*
  奇葩的地方:
      1、监视的多个属性需要使用数组套起来
      2、数组中的每一个属性需要写成函数式
*/
watch([()=> person.name , ()=> person.sex] , (newValue,oldValue)=>{
  console.log("person中的name和sex属性被修改了",newValue,oldValue);
})

// 类型四、监视reactive托管的一个响应式数据中的某个属性,但:此属性又套娃了
/*
  奇葩的地方:
      1、需要开启深度监视 即:deep:true 又生效了
      2、不加 deep:true配置,代码会无效
*/
watch(()=> person.address , (newValue,oldValue)=>{
  console.log("person中的address属性被修改了",newValue,oldValue);
},{deep:true})

return {
  person,
}

4.8、vue3中的watchEffect 智能监视函数

注:此种监视对应ref托管和reactive托管都可以监视到*


  姓名:
  性别:
  地址:

  姓名: {{person.name}}
  性别: {{person.sex}}
  地址: {{person.address.detailed.value}}

import { reactive } from '@vue/reactivity'

// 1、引入watchEffect函数
import { watchEffect } from '@vue/runtime-core'

export default {
  name: 'App',

  setup(){

    let person = reactive({
      name: '紫邪情',
      sex: '女',
      address: {
        detailed: {
          value: '浙江省杭州市'
        }
      }
    })

    // 2、使用watchEffect函数对响应式数据进行智能监视
    /*
      1、不需要指名要监视谁
      2、不需要newValue 和 oldValue【 ps:因为都不知道要监视谁 】
    */
    watchEffect(()=>{
      // 所谓智能:就体现在这里面的函数体中
      //          要监视谁,取决于这个函数体里面用到了谁,那就监视谁

      // 如:要监视person中的name,那就直接写改写的代码即可,此函数会自动判定,从而监视
      const personName = person.name

      // 如:要监视person中的sex,那就用它就可以了
      const personSex = person.sex

      console.log("watchEffect智能监视函数被调用了");

      // 而此函数体中没有用到的,那么:就不会去监视它
    })

    return {
      person,
    }
  }
}

vue3技术整理( 基础 )

vue3技术整理( 基础 )

vue3技术整理( 基础 )

vue3技术整理( 基础 )

4.9、vue3中的watch函数 和 watchEffect函数的对比

watch函数的套路是:既要指明要监视哪个属性,也有指明监视的回调

watchEffect函数的套路是:不用指明要监视哪个属性,回调中用到了哪个属性,那就监视哪个属性

watchEffect函数和Computed函数有点像:

  • Computed函数注重:计算出来的值 ps:回调函数的返回值。所以必须写返回值
  • watchEffect函数注重:过程 ps:回调函数的函数体。所以不用写返回值

4.10、vue3中的生命周期图

和vue2的生命周期差不多,只是需要注意一些点而已

vue3技术整理( 基础 )

上面这张图官网中有

vue3技术整理( 基础 )

4.10.1、vue3中生命周期的注意项

对比vue2中的生命周期,vue3中改动的地方,如下所示

vue3技术整理( 基础 )

vue3技术整理( 基础 )

2、vue3中生命周期的写法问题

配置项写法 – 和name、setuo()保持平级,写法就是:按照官网中说的哪些名字直接写即可


    export default {
      name: 'App',

      setup() {},

      // vue3中的生命周期 - 配置项写法     ps:和name、setup保持平级即可
      beforeCreate(){ console.log("------beforeCreate-----"); },
      created(){ console.log("------created-----"); },
      beforeMount(){ console.log("------beforeMount-----"); },
      mounted(){ console.log("------mounted-----"); },
      beforeUpdate(){ console.log("------beforeUpdate-----"); },
      updated(){ console.log("------updated-----"); },
      beforeUnmount(){ console.log("------beforeUnmount-----"); },
      unmounted(){ console.log("------unmounted-----"); },
    }

另一种写法:组合式API写法 – 万事引入对应函数嘛 – 不过此种方式名字有点区别

  • beforeCreate ====> setup()
  • created ====> setup()
  • beforeMount ====> onBeforeMount
  • mounted ====> onMounted
  • beforeUpdate ====> onBeforeUpdate
  • updated ====> onUpdated
  • beforeUnMount ====> onBeforeUnMount
  • UnMounted ====> onUnMount

// 1、引入对应的钩子函数
import { onBeforeMount, onMounted } from '@vue/runtime-core'

export default {
  name: 'App',

  setup() {

    // 另一种写法 - 组合式API写法 - 万事引入对应的函数嘛
    /*
      只是注意:setup()就相当于beforeCreate() 和 created()
    */

    // 2、使用对应的钩子函数
    onBeforeMount(()=>{
      console.log("------beforeMount-----");
    })

    onMounted(()=>{
      console.log("------onMounted-----");
    })

    // 其他的都是一样的,就不写了,注意名字即可
  },

需要注意一个点:配置项写法和组合式API写法同时存在同一个钩子函数时
则:setup()中所用的组合式API写法比配置项写法优先执行

4.12、vue3中的 toRef 和 toRefs 数据拆分函数

这两个东西就是为了解决在模板中渲染时稍微方便点而已,因为在模板中使用插值表达式xxx.xxxx.xxx这种取值并不合理,插值表达式的宗旨就是简单取值嘛,所以通过xxx.xxxx.xxx的方式并不好

当然:toRef和toRefs也不一定能够完全解决插值表达式的问题 ps:主要看自己设计

1、使用toRef()函数交出单个数据


  姓名: {{person.name}}
  性别: {{person.sex}}
  地址: {{person.address.value}}

  使用toRef和toRefs函数进行简化

  姓名: {{name}}
  性别: {{sex}}
  地址: {{address}}

// 1、组合式还是逃不开引入的问题
import { reactive, toRef } from '@vue/reactivity'

export default {
  name: 'App',

  setup() {
    let person = reactive({
      name: '紫邪情',
      sex: '女',
      address: {
        value: '浙江杭州'
      }
    })

    return {
      person,
      // 2、使用toRef()函数
      // 使用toRef函数交出单个数据
      /*
        第一个参数: 交出的数据是哪个对象中的
        第二个参数: 要交出的是对象中的哪个属性
      */
      name: toRef(person,'name'),
      sex: toRef(person,'sex'),
      // 这里需要注意一下:要交出的对象里面又套娃了,那么:第一个参数需要再进一步
      address: toRef(person.address,'value'),
    }
  },
}

vue3技术整理( 基础 )

2、使用toRefs()函数


  姓名: {{person.name}}
  性别: {{person.sex}}
  地址: {{person.address.value}}

  使用toRefs函数进行简化

  姓名: {{name}}
  性别: {{sex}}

  地址: {{address.value}}

// 1、组合式还是逃不开引入的问题
import { reactive, toRefs } from '@vue/reactivity'

export default {
  name: 'App',

  setup() {
    let person = reactive({
      name: '紫邪情',
      sex: '女',
      address: {
        value: '浙江杭州'
      }
    })

    return {
      person,
      // 利用toRef()交出数据,需要写多次toRef,所以还是不喜欢,那就用toRefs()函数
      /*
        直接说要交出哪个对象即可
        注意点:return{}是一个对象,所以:使用toRefs就是对象中套对象,因此注意写法
      */
      ...toRefs(person)
    }
  },
}

vue3技术整理( 基础 )

现在回过来看一下,为什么通过toRef() 和 toRefs()函数可以做到数据简化
使用toRef()举例,去看一下它长什么样子? – toRefs()函数是一样的原理

console.log(toRef(person,'name'));

vue3技术整理( 基础 )

4.12.1、vue3的toRef() 和 toRefs()函数总结

作用:创建一个RefImpl引用对象,而此对象的value属性是指向你要交出数据的那个对象的某个属性

  • 解读:创建的这个RefImpl引用对象就相当于中间商,这个中间商代表的就是你要交出去的那个数据 ,注意:是代表啊,意思就相当于是此中间商的引用指向的地址 和 原本你要交出去的对象的某个属性指向的是同一个地方,因此: *此中间商RefImpl可以修改原数据,即:你把数据交出去之后,被修改了,那么原数据中的数据也会被修改,数据保持同步嘛

语法: const name = toRef(person,'name') 记得先引入对应的函数

[TencentCloudSDKException] code:FailedOperation.ServiceIsolate message:service is stopped due to arrears, please recharge your account in Tencent Cloud requestId:c8a451da-bed4-4829-b515-192287cb398a

[En]

[TencentCloudSDKException] code:FailedOperation.ServiceIsolate message:service is stopped due to arrears, please recharge your account in Tencent Cloud requestId:8f44d9b6-2971-47b4-8bae-87591753aac7

扩展: toRefstoRef功能一致,但:可以批量创建多个RefImpl引用对象

  • toRefs的语法: toRefs(person)

Original: https://www.cnblogs.com/xiegongzi/p/15875530.html
Author: 紫邪情
Title: vue3技术整理( 基础 )

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/562827/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球