VUE3学习笔记

VUE3出现已经很长时间了,由于工作比较忙,项目比较紧,现在才看,已经晚于很多人了。

这是vue3学习笔记,边学边写。

1,项目创建

  可以使用git下载:winpty vue.cmd create hello-world 使用之后会让你选择vue2还是3

  可以直接node创建:vue create demo

2,组件传值

  多了个类型校验,传值大体写法用法还是一样的

props:{
  list: {
    type: Array, //定义接受数据格式
    required: true,
    default() {
      return ["q", "w"];
    },
  }
}

 

3,插槽

  插槽的写法就有些区别了,使用方式修改了一些,但是大体还是没有变化的。

  在父组件中原先是可以直接使用一般的元素标签,现在只能使用<template>标签包裹

  vue2中 slot="main" 与 name=”main” 搭配使用即可实现插槽

  vue3中 slot="main" 与 v-slot:main 或者 #main 搭配使用,传值方式如下代码

  父组件写法

 1 <template>
 2   <HelloWorld :msg="msg" :list="list" :a="a">
 3     <!-- 写法一 -->
 4     <!-- <template v-slot:header="scope">
 5       <h3 style="color: red">这是插槽++{{scope.text}}+{{scope.text1}}</h3>
 6     </template> -->
 7     <!-- 写法二 -->
 8     <template #header="{ Text1, text }"> 这是插槽++{{ Text1 }}++{{ text }} </template>
 9   </HelloWorld>
10 </template>
11 
12 <script>
13 import HelloWorld from "./components/HelloWorld.vue";
14 export default {
15   name: "App",
16   components: {
17     HelloWorld,
18   },
19   data() {
20     return {
21       msg: false,
22       list: undefined,
23       a: "warning",
24     };
25   },
26 };
27 </script>

  子组件写法

 1 <template >
 2   <div class="hello">
 3     <slot name="header" :text="text" :Text1="text1"></slot>
 4     <div>{{ a }}</div>
 5     <div>{{ msg }}</div>
 6     <div v-for="(item, index) in list" :key="index">
 7       {{ item }}
 8     </div>
 9     <div>
10       count:{{count}}
11     </div>
12   </div>
13 </template>
14 
15 <script>
16 import { ref } from "vue";
17 export default {
18   name: "HelloWorld",
19   props: {
20     msg: {
21       type: Boolean,
22       required: true,
23       default: true,
24     },
25     a: {
26       type: String,
27       required: true,
28       validator(value) {
29         // 这个值必须与下列字符串中的其中一个相匹配
30         return ["success", "warning", "danger"].includes(value);
31       },
32     },
33     list: {
34       type: Array,
35       required: true,
36       default() {
37         return ["q", "w"];
38       },
39     },
40   },
41   data() {
42     return {
43       text: "子组件数据",
44       text1: "批量传值",
45     };
46   },
47   // 在data中声明的对象,在methods中写的function,在mounted、computed、watch中写的js,都可以写在setup中的
48   setup(props) {
49     var count = ref(12)
50     console.log(props.values,count.value, "][");
51     return {
52       count
53     };
54   },
55 };
56 </script>

 

4,setup (重点)

 4.1 setup 与 旧写法的关系

     在vue2中,我们将数据定义在函数 data 中,执行函数定义在各个生命周期中,数据处理在监听函数或者计算属性,

  在vue3中,setup 函数可以做到所有,生命周期,数据处理,监听属性等。但是需要按需引入。

   setup 也是vue2中的一个配置,与data ,methods 是同等级的。

   学习内容来自 https://www.bilibili.com/video/BV1Za4y1r7KE?p=1&vd_source=775fbdfbeeb51662faa8e88c32941a4b

 1 <template>
 2   <div>
 3     {{ msg }}
 4   </div>
 5   <div>
 6     789
 7   </div>
 8 </template>
 9 <script lang="ts">
10 export default {
11   data() {
12     return {
13       msg: 'hello word'
14     }
15   },
16   beforeCreate() {
17     console.log('beforeCreate');
18   },
19   setup() {
20     console.log(this,'this');
21     console.log('setup');
22   }
23 }
24 </script>

   

  由输出可以看出,setup执行时间是高于 beforecreate 的,并且在这里面this是指向undefined的,所以在setup中不能使用this,这也是 vue3的一种方向,淡化this

  在setup与data里面数据与methods事件冲突时候,是会执行setup 数据与事件

既然 data 与setup 是同步存在的,那么他们之间是不是可以自由访问,data 访问setup数据,setup访问data数据

  经测试可以得出结论,由于setup创建时间早于 beforecreate ,所以说在data 中是可以访问setup里面的数据的,setup 是不能访问data 里面的数据的,

  旧的可以访问新的,新的不可以访问旧的

 4.2  setup 中数据响应式

  在vue2中,响应式数据直接写在data里面就可以了,直接就是响应式,在vue3中,有setup,并且无法访问到data里面的数据,所以说setup有他自己的实现响应式数据的方法

  vue3 的响应式数据原理是基于 ES6 的 Proxy 特性来实现的。Proxy 允许你创建一个对象的代理,从而可以拦截和自定义对象的各种操作,比如属性访问、赋值、枚举、函数调用等。

  在 3 中创建响应式就需要使用 ref  reactive 来创建

  ref 用来创建 基本类型 与 对象类型 的响应式数据

  reactive 只能用来创建 对象类型 响应式数据 

  在代码与输出可以看到,ref创建出来的响应式数据 会用一个 名字叫 refimpl的对象包裹,reactive创建出来的响应式数据 会由 proxy包裹

  但是在ref 创建出来的对象类型的数据中是含有 proxy 的。所以说ref 创建的对象类型,底层还是由reactive 实现的。

  因为reactive创建出来的对象类型响应式数据是深层次的便利,所以在ref中响应式对象也是深层次的便利 。2中无法知道数组索引长度的缺点与对象无法深层次便利问题都已修复

  在使用时候,在script 标签内部  通过 ref 定义出来的数据需要使用 XXX.value 来获取,通过reactive定义的数据则不需要

  在使用时候,在 template 标签内部  通过 ref 与 reactive 定义的响应式数据 都可以直接使用

  reactive 使用局限性当你使用 reactive 重新分配一个对象时候,会失去响应式。可以使用 Object.assign() 来实现重新分配新对象并且变成响应式

  ref 与 reactive 使用原则:

     1,如果是基本类型响应式数据,使用ref 

    2,如果是层次不深,没有很多嵌套的对象类型响应式数据。使用 ref 与reactive 都可以

    3,如果是深层次对象类型响应式数据,使用 reactive 

  ref 标记组件与DOM元素

  在vue2中使用ref标记组件之后,父组件可以随意查看子组件内部属性与方法,在3中就加了限制,子组件让你看哪个,才能看哪个

  父组件代码

 1 <template>
 2   <person ref="appVue" />
 3   <button @click="showPer">点击展示</button>
 4 </template>
 5 
 6 <script lang="ts" setup>
 7 import { ref } from 'vue'
 8 import person from '@/views/person.vue'
 9 let appVue = ref()
10 function showPer() {
11   console.log(appVue.value.name, '===');
12 }
13 </script>

  子组件代码

 1 <template>
 2   <div>姓名:{{ name }}</div>
 3   <div>年龄:{{ age }}</div>
 4  
 5 </template>
 6 <script lang="ts" setup name="person">
 7 import { ref,defineExpose } from 'vue'
 8 let name = ref('景天')
 9 let age = ref(24)
10 defineExpose({ name })
11 </script>

  在子组件中暴露了 name父组件才能访问到name,如果没有暴露是访问不到的。就是说,让你看哪个才能看哪个

 

   toref 与 torefs 用法

  在开发中会遇到这种情况,比如说一个响应式的表单,现在我只需要表单中某个属性,去做一些操作,在vue3中就需要用到 toref 与 torefs了

  

  看代码,简单的说就是点了按钮1之后,数据更新了,但是视图没有更新,意味着,age并不是响应式,只是单纯的定义了一个age

  但是age 使用toref包裹之后就是变成响应式了,点击之后,数据与视图层都有更新。

  同样的,如果数据比较多,那就是用 解构赋值,并且使用 torefs 这样新的数据都是响应式的,并且互相绑定,改这个,另一个也会修改

1 let obj = reactive({
2   name: '景天',
3   age: 22
4 })
5 let { name, age } = toRefs(obj)

 

  (未完待续)

 

posted @ 2023-06-26 16:16  马文庆i  阅读(49)  评论(0编辑  收藏  举报