目录

一、main.js文件的不同

二、app.vue组件的不同

三、添加了新的配置项——setup

四、ref函数

五、reactive函数

六、Vue3里面的响应式使用

七、setup函数的注意事项

1.setup函数的执行时间

2.setup函数的参数

八、computed计算属性

九、watch监视函数

1.watch监视ref定义的基本数据类型

2.watch监视reactive定义的对象和数组类型

3.watchEffect智能监视(Vue3里面新添加的)

十、生命周期

十一、toRef函数

十二、其他组合式API

1.shallowReactive

2.shallowRef

3.readonly和shallowreadonly

4.toRaw和markRaw

十三、vue3里面新的组件

1.fragment组件

2.Teleport传送组件


一、main.js文件的不同

我们先分析vue3里main.js文件

注意:vue3的main.js里面不能再写vue2的写法了。

保险起见,还是将Vue3的完整main.js代码贴在这里

二、app.vue组件的不同

我们首先打开一个崭新的vue3 app.vue文件

我们可以清晰的看到<template>标签下没有根div,也就是说:

<vue3组件中的模板标签可以没有根标签>

但是,为了给组件加上样式,我们还是习惯于写上根标签

三、添加了新的配置项——setup

setup是所有组合式api(composition API)表演的舞台

他的值是一个函数

  • 组件中的数据(data)、方法(methods)、生命周期等都要配置在setup中
  • setup函数的返回值有两种情况:返回一个对象,返回一个渲染函数
  • 返回一个对象时,对象里面的东西可以再模板函数里面不加this直接使用(重点关注)
  • 返回一个渲染函数时,可以自定义渲染函数的内容(仅作了解)

我们对app.vue文件做如下修改

<template>
  <h1>一个人的信息</h1>
  <h3>姓名:{{ name }}</h3>
  <h3>年龄:{{ age }}</h3>
  <button @click="sayHello">说话</button>
</template>

<script>

export default {
  name: 'App',
  setup(){
    // 再setup里面直接写数据和方法
    // 数据
    let name = '张三'
    let age = 18
    //方法
    function sayHello(){
      alert(`我叫${name}, 我今年${age}岁了,你好啊!`)
    }

    return {
      name,
      age,
      sayHello
    }
  }

}
</script>

这里面就可以看出setup函数的基本用法,注意alert里面的既不是单引号也不是双引号,

注意点:

  • vue2的配置不要和vue3混用,会出现问题:
    • vue2的配置中可以访问到setup的属性和方法
    • 但Vue3的setup配置中不能访问到Vue2的配置(data、methods、computed等)
    • 如果Vue2和Vue3的属性名字有重名的,以vue3配置的数据优先
  • setup函数不能是一个async函数,因为返回值不再是return的对象,而是promise,模板函数看不到return对象中的属性

四、ref函数

在上一节中,我们这样定义属性:

这不是一个响应式的属性定义方式,如果我们此时用一个函数修改name和age的值,值可以修改,但是页面不会渲染更新之后的内容

使用ref需要先引入

import {ref} from 'vue'

ref封装好的属性会变成一个对象,

这个对象叫做引用实例的实现对象,我们的属性值并不是直接通过对象名字访问的,而是要 对象名.value 访问

但是在模板函数里面 Vue3会帮我们自动.value,所以模板函数里面还是跟原来的差值表达式一样

请看响应式代码

<template>
  <h1>一个人的信息</h1>
  <h3>姓名:{{ name }}</h3>
  <h3>年龄:{{ age }}</h3>
  <button @click="changeInfo">改变内容</button>
</template>

<script>
import {ref} from 'vue'

export default {
  name: 'App',
  setup(){
    // 再setup里面直接写数据和方法
    // 数据
    let name = ref('张三')
    let age = ref(18)
    function changeInfo(){
      name.value = '李四'
      age.value = 48
      console.log(name,age);
    }

    return {
      name,
      age,
      changeInfo
    }
  }

}
</script>

用ref处理对象的信息,几乎没什么特别的

就不再赘述了

五、reactive函数

在上一节中,我们使用ref函数时们需要不停的使用.value来访问

现在,对于对象数据类型,我们可以使用reactive替换ref, 当然之前还需要引入

在后面访问的时候就不需要加上.value了

我们使用reactive处理数组来简单的示范下

1.先引入

2.给数组添加响应式

3.在setup函数中return给模板函数

4.在函数中修改

优雅,实在是太优雅了

尽管reactive处理数组和对象非常轻松,但是它不能处理基本数据类型(Number, String 等)

解决方法

把所有的数据都封装在一个类里面,面向对象式的存储数据

六、Vue3里面的响应式使用

尚硅谷的老师详细讲解了Vue3的响应式原理以及他和Vue2的不同,方便以后查阅,这里只给出连接

尚硅谷视频=>

在vue3里面,基本数据类型的响应式的使用使用跟vue2没有太大的差别,但是对于数组和对象数据,Vue3的使用方法比vue2要更加简单。

代码

<template>
  <h1>一个人的信息</h1>
  <h3 v-show="person.name">姓名:{{ person.name }}</h3>
  <h3>年龄:{{ person.age }}</h3>
  <h3 v-show="person.sex">性别:{{ person.sex }}</h3>
  <h3>爱好: {{ hobby }}</h3>
  <button @click="addSex">添加性别属性</button>
  <button @click="deleteName">删除name属性</button>
  <button @click="changeInfo">改变内容</button>
</template>

<script>
import {reactive} from 'vue'

export default {
  name: 'App',
  setup(){
    //reactive给对象数据添加响应式
    let person = reactive({
      name : '张三',
      age : 18
    })

    //用ref处理对象信息
    let job = reactive({
      type:'前端工程师',
      salay:"30K"
    })

    // reactive处理数组属性
    let hobby = reactive(['抽烟','喝酒','烫头'])
    
    // 方法
    function changeInfo(){
      hobby[0] = '学习'
    }
    function addSex(){
      person.sex = '男'
    }
    function deleteName(){
      // 从对象里面删除属性
      delete person.name
    }

    return {
      person,
      job,
      hobby,
      addSex,
      deleteName,
      changeInfo
    }
  }

}
</script>

七、setup函数的注意事项

1.setup函数的执行时间

setup函数的会在beforeCreate生命周期函数之前执行一次,此时this的值时undefined

也就是说,在setup函数里面,我们不能通过this访问到任何东西

2.setup函数的参数

setup函数可以接受两个参数,

  • 第一个参数时props对象,用于接收父组件传递过来的数据,单数props对象必须先调用

我们先演示第一个参数:在传递给setup函数之前必须先接收


页面控制台:

这就证明props传递进来的数据是响应式的

接下来演示第二个参数

值得注意的是,在vue3里面,对于具名插槽,我们使用 v-slot:而不是#或者slot="",这只是一个API兼容的问题

我们先从自定义事件开始说起

在App.vue组件里面

在Demo_1.vue组件里面

<template>
  <h1>一个人的信息</h1>
  <h3 v-show="person.name">姓名:{{ person.name }}</h3>
  <h3>年龄:{{ person.age }}</h3>
  <h3 v-show="person.sex">性别:{{ person.sex }}</h3>
  <h3>爱好: {{ hobby }}</h3>
  <button @click="addSex">添加性别属性</button>
  <button @click="deleteName">删除name属性</button>
  <button @click="changeInfo">改变内容</button>
</template>

<script>
import {reactive} from 'vue'

export default {
  name: 'App',
  setup(){
    //reactive给对象数据添加响应式
    let person = reactive({
      name : '张三',
      age : 18
    })

    //用ref处理对象信息
    let job = reactive({
      type:'前端工程师',
      salay:"30K"
    })

    // reactive处理数组属性
    let hobby = reactive(['抽烟','喝酒','烫头'])
    
    // 方法
    function changeInfo(){
      hobby[0] = '学习'
    }
    function addSex(){
      person.sex = '男'
    }
    function deleteName(){
      // 从对象里面删除属性
      delete person.name
    }

    return {
      person,
      job,
      hobby,
      addSex,
      deleteName,
      changeInfo
    }
  }

}
</script>

注意context组件的写法,context.emit('hello',666);后面是传递的参数

在看vue3组件里面的插槽,这里以具名插槽为例

在Demo.vue组件里面

在App.vue组件里面

具体的使用方法跟vue2没有太大的差别

至于第一项,个人感觉意义不大,毕竟父组件传递参数我们都是要写props来接收的。

八、computed计算属性

跟Vue2的原理基本相同,用法请看代码,不再赘述

<template>
    <h1>一个人的信息</h1>
    姓:<input type="text" v-model="person.firstName"><br>
    名:<input type="text" v-model="person.lastName"><br>
    <span>全名:{{ fullName }}</span><br>
    全名:<input type="text" v-model="person.fullName">
</template>

<script>
import {computed,reactive} from 'vue'

export default {
  name: 'Demo_1',
  setup(){
    let person = reactive({
        firstName:'张',
        lastName:'三'
    })

    //计算属性
    //简写版,不考虑计算属性被修改的情况
    // person.fullName = computed(()=>{
    //     return person.firstName + '-' + person.lastName
    // })

    //完整版,计算属性被修改了还可以返回去渲染
    person.fullName = computed({
        get(){
            return person.firstName + '-' + person.lastName
        },
        set(value){
            const NameArr = value.split('-')
            person.firstName = NameArr[0]
            person.lastName = NameArr[1];
        }
    })

    return {
        person,
    }
  }

}
</script>

get和set实现响应式的原理需要注意

九、watch监视函数

在Vue3中,watch监视函数也是一个组合式API(使用前需先调用),这个函数有三个参数

  • 第一个参数是监视的元素
  • 第二个参数是监视的回调
  • 第三个参数是监视的配置

1.watch监视ref定义的基本数据类型

先简单看一下代码:

<template>
    <div>
        <h3>count的值为:{{ count }}</h3>
        <button @click="count += 1">点我增加count的值</button>
        <button @click="count -= 1">点我减少count的值</button>
        <hr>
        <h3>此时的数据为:{{ msg }}</h3>
        <button @click="msg += '!'">点击修改数据</button>
    </div>
</template>

<script>
import { ref,watch } from 'vue'

export default{
    setup(){
        //数据
        let count = ref(0)
        let msg = ref('你好啊')

        //watch监视
        //因为setup里面没有this,所以我们用回调函数
        //watch函数第一个参数是监视的元素,第二个参数是监视的回调,第三个参数是监视的配置

        //情况一,监视ref所定义的响应式数据
        // watch(count,(NewValue,OldValue)=>{
        //     console.log(`count的值变了,新值为${NewValue},旧值为${OldValue}`);
        // })

        //情况二,监视ref定义的多个数据,同时监视多个数据的变化
        watch([count,msg],(NewValue, OldValue)=>{
            // console.log(`count或msg的值变了,新值为${NewValue},旧值为${OldValue}`);
            console.log("count或msg的值变了",NewValue, OldValue);
        },{immediate:true})

        return{
            count,
            msg
        }
    }
}
</script>

跟vue2不同的是,Vue3里面的watgch函数可以不断的被调用,也就是说,在监视多个元素时,我们不仅可以写成数组的形式,还可以直接写还几个watch函数

2.watch监视reactive定义的对象和数组类型

watch监视reactive定义的数据时会出现两个bug,

  • watch不能正确的获得OldValue的值,目前这个bug无法解决。
  • watch强制开启深度监听,也就是deep配置无效

我们只看第一个bug

我们还是直接看代码、

<template>
    <div>
        <h3>姓名: {{ person.name }}</h3>
        <h3>年龄:{{ person.age }}</h3>
        <button @click="person.name += '~'">修改姓名</button>
        <button @click="person.age++">修改年龄</button>
    </div>
</template>

<script>    
import { reactive,watch } from 'vue'

export default{
    setup(){
        //数据
        let person = reactive({
            name:'张三',
            age:18
        })
        watch(person,(NewValue,OldValue)=>{
            console.log("person的值变了",NewValue,OldValue);
        })

        return{
            person
        }
    }
}
</script>

加入我们要是想单独监视对象里面的某一个属性怎么办呢?

聪明的小伙伴也许已经想到应该怎么办了

但是如果这样写,vue会报出一个警告

并且我们修改age的值时watch也没有监听到

我们应该把这玩意写成一个函数。

这样就成了

3.watchEffect智能监视(Vue3里面新添加的)

watchEffect函数也是一个组合式的api,它不需要指定监视的对象,在他的回调函数里面用了谁他就监视谁,在实际操作中非常方便

简单演示一下

请看下列说明

十、生命周期

在Vue3里面的生命周期钩子既可以写配置项(跟Vue2里面一样),也可以写成组合式API(写在setup 里面)

但是组合式API的优先级更高

具体的跟vue2的差不多,用的也少,所以就不再赘述了.

vue3生命周期API文档=

图示

十一、toRef函数

vue3里面非常重要的一个API

先看问题:

我们在实现上面几节的代码时,总觉得 person. 写起来很繁琐

所以我们可以在return时对数据做一些处理

我们的意思是在return里面将 person. 写完,在模板函数里面就不用写了。

可是,这样一下,我们发现模板函数里面的响应式功能没了,这是为什么呢?

仔细一想不难发现,我们给name赋值,只是将一串字符串赋值给一个变量而已,跟person里面的属性没有半毛钱关系,也就是说上面的写法就相当于:

我们对name、age、salay变量做修改,根本不会影响到person里面的属性值,这就是页面不渲染响应式的原因

解决办法,那肯定是要使用我们的toRefAPI了

附上完整代码

<template>
    <h3>一个人的信息</h3>
    <h3>姓名:{{ name }}</h3>
    <h3>年龄:{{ age }}</h3>
    <h3>薪资:{{ salay }}K</h3>
    <hr>
    <button @click="name+='~'">修改姓名</button>
    <button @click="age++">增长年龄</button>
    <button @click="salay++">涨薪</button>
</template>

<script>
import { reactive, toRef } from 'vue'

    export default{
        setup(){
            let person = reactive({
                name:'张三',
                age:18,
                job:{
                    j1:{
                        salay:20
                    }
                }
            })

            return {
                //使用toRef关键字就可以解决问题
                name: toRef(person,'name'),
                age :  toRef(person,'age'),    
                salay : toRef(person.job.j1,'salay')
            }
        }
    }
</script>

关于这个API的原理,尚硅谷有很详细的解释

有时候我们需要展出的数据很多,一个一个写又很麻烦了。所以出现了toRefs

值得注意的是,这里的展开只有一层,也就是模板函数里面的salay要这样写

也很方便

十二、其他组合式API

尚硅谷详细介绍=》

1.shallowReactive

顾名思义,这个就是浅层次的reactive

他只确保第一层响应式数据,对于第一次数据里面有对象或数组的,对象或数组里面的属性值就不是响应式的

2.shallowRef

跟上面的shallowReactive一样

当传入的是基本数据类型的时候,shallowRef和ref没有区别,但是当传入的是对象或数组类型的时候,shallowRef不做处理

也就是:shallowRef不处理对象或数组类型

3.readonly和shallowreadonly

readonly是只读的意思,有点类似于const将变量保护起来,不让别人对变量做修改。

可以看看控制台的警告

readonly是深层次的保护,不管是基本数据类型还是对象、数组,只要是再readonly的包裹下都不允许做修改

shallowReadonly是浅层次的保护,对于对象或数组的属性值shallowReadonly不做处理

4.toRaw和markRaw

  • toRaw把某个·数据从响应式转化为不是响应式(将响应式的数据还原为其原始的数据)
  • markRaw把某个数据标记为非响应式,使其永远也不能成为响应式数据

注意:

  • toraw只能处理reactive定义的响应式对象,若是处理ref定义的数据,会变成undefined

十三、vue3里面新的组件

1.fragment组件

原谅孩子太多了敲不下去了~~~

也就是说,vue3自带一个根标签叫做frangment,可以节省空间,提高效率

2.Teleport传送组件

这是我个人很喜欢的一个组件,使用它可以实现弹窗+遮罩层的效果。在很多UI组件库里面也用到了

这个组件的应用我写了另外的一篇博客,请大家移步:

(1条消息) 使用VUE3+teleport组件实现遮罩层和弹窗效果_CTGU_ 21_ emo~~~~的博客-CSDN博客_vue遮罩效果

希望和大家共勉,最后祝大家程序员节快乐~~~~

GitHub 加速计划 / vu / vue
207.54 K
33.66 K
下载
vuejs/vue: 是一个用于构建用户界面的 JavaScript 框架,具有简洁的语法和丰富的组件库,可以用于开发单页面应用程序和多页面应用程序。
最近提交(Master分支:2 个月前 )
73486cb5 * chore: fix link broken Signed-off-by: snoppy <michaleli@foxmail.com> * Update packages/template-compiler/README.md [skip ci] --------- Signed-off-by: snoppy <michaleli@foxmail.com> Co-authored-by: Eduardo San Martin Morote <posva@users.noreply.github.com> 4 个月前
e428d891 Updated Browser Compatibility reference. The previous currently returns HTTP 404. 5 个月前
Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐