Vue学习八:vue3

发布时间 2023-09-19 23:10:00作者: 数星观月

一、vue3创建项目与介绍

vue3创建项目与vue2使用vue-cli(基于webpack)脚手架不同,vue3使用create-vue(基于vite,更快)。创建项目的指令如下,首先看一下node的版本(node -v),16以上才支持。第一次创建项目会去下载create-vue比较慢,等一会就好了。

npm init vue@latest

然后关掉命令行,重新打开cd到自己需要创建项目的路径,再使用上面的命令创建项目。

然后按照上面三条指令进入到项目中,下载依赖,启动项目。

vue3的优势

更容易维护
1 .组合式API
2.更好的TypeScript支持
更快的速度
1.重写diff算法
2.模版编译优化
3.更高效的组件初始化
更小的体积
1.良好的TreeShaking
2.按需引入
更优的数据响应式
Proxy

组合式API个人理解,对于一个数据vue2中将其拆分到不同的部分处理,如data、methods、computed等,这样数据少还容易维护,一旦数据过多就难以维护了。vue3则不同,将一个数据的所有操作都放在一起,这样数据多了也不用怕了。

Vue3项目的关键文件

1. vite.config.js -项目的配置文件基于vite的配置
2. package.json -项目包文件核心依赖项变成了Vue3.x 和vite
3. main.js-入口文件createApp函数创建应用实例
4. app.vue -根组件SFC单文件组件script - template - style
变化- -:脚本script和模板template顺序调整
变化二:模板template不再要求唯一根元素
变化三:脚本script添加setup标识支持组合式API
5. index.html-单页入口提供id为app的挂载点

二、组合式API(一些函数)

setup
1.执行时机,比beforeCreate还要早
2.setup函数中,获取不到this(this是undefined )
3.数据和函数,需要在setup最后return, 才能模板中应用

//原始复杂写法
<script>
export default{
    setup() {
        const message = 'hello world'
        const logMessage = () => {
            console.log(message)
        }
        return {
            message,
            logMessage
        }
    }
}
</script>
//语法糖写法
<script setup>
const message = 'hello world'
const logMessage = () => {
    console.log(message)
}
</script>

reactive和ref函数

vue3中默认数据不是响应式的,vue2是响应式的,数据变化,视图自然更新,因此vue3中的数据如果想要是响应式的就可以使用上面两个函数。(响应式的好处,如果前端需要修改后端某个数据,在这个事件触发修改后面重新获取数据,这样就能更新局部dom元素,不用重新加载整个页面;视图更新,数据变化的好处就是,我们获取更新的数据不需要再用函数去获取视图中的值,直接拿就行了;数据双向绑定需要看绑定的视图在哪个地方,有可能在根组件,也可能在子组件,这样因为单向数据流那么绑定的方式就不同了)

reactive()
作用:接受对象类型数据的参数传入并返回-一个响应式的对象
1.从vue包中导入reactive函数
2.在< script setup>中执行reactive函数并传入类型为对象的初始值,并使用变量接收返回值

用法如下,点击按钮给一个对象中一个数加一

<script setup>
import { reactive } from 'vue'
const state = reactive({
    count:100
})
const setCount = () => {
    state.count++
}
</script>


<template>
  <div class="box">
        {{state.count}}
    </div>
    <button @click="setCount">+1</button>
</template>

<style scoped>
.box{
    width:50px;
    height: 50px;
    border: 1px solid black;
}
</style>
View Code

ref()
作用:接收简单类型或复杂类型,返回一个响应式的对象
本质:是在原有传入数据的基础上,外层包了一层对象,包成了复杂类型
底层:包成复杂类型之后,再借助reactive 实现的响应式
注意点:
1.脚本中访问数据,需要通过. value
2.在template中, .value不需要加(帮我们扒了一层)

<script setup>
import { ref } from 'vue'
const state = ref(0)
console.log(state.value)
</script>

<template>
  <div class="box">
        {{state}}
    </div>
</template>

computed计算属性函数
计算属性基本思想和Vue2的完全一致,组合式API下的计算属性只是修改了写法
核心步骤:
1.导入computed函数
2.执行函数在回调参数中return基于响应式数据做计算的值,用变量接收

demo如下:获取列表中大于2的元素

<script setup>
import { computed,ref } from 'vue'
const list = ref([1,2,3,4,5,6,7,8,9])
const computedList = computed(() => {
    return list.value.filter(item => item > 2)
})
</script>

<template>
  <div class="box">
        {{list}}
        {{computedList}}
    </div>
</template>

<style scoped>
.box{
    width:400px;
    height: 20px;
    border: 1px solid black;
}
</style>
View Code

watch函数
作用:侦听一个或者多个数据的变化,数据变化时执行回调函数
俩个额外参数: 1. immediate ( 立即执行) 2. deep ( 深度侦听)
基础使用-侦听单个数据
1.导入watch函数
2.执行watch函数传入要侦听的响应式数据(ref对象)和回调函数
immediate
说明:在侦听器创建时立即触发回调,响应式数据变化之后继续执行回调
deep深度监视,默认watch 进行的是浅层监视
const ref1 = ref(简单类型)可以直接监视
constref2=ref(复杂类型)监视不到复杂类型内部数据的变化

watch(ref对象,(newValue,oldValue) => {...},{immediate: ,deep: })

三、生命周期函数

关于vue2和vue3中生命周期函数的对应关系见下图和下demo

<script setup>
import { onMounted } from 'vue'
//beforeCreate和created钩子里面的代码放在setup里面直接声明再执行即可
const getList = () => {
    console.log('发送请求,获取数据')
}
getList()
//如果有些代码需要在mounted生命周期中执行
onMounted(() => {
    console.log('mounted生命周期函数 - 逻辑1')
})
//写成函数调用的方式,可以调用多次,并不会冲突,而是按照顺序执行
onMounted(() => {
    console.log('mounted生命周期函数 - 逻辑1')
})
</script>

<template>
  <div class="box">
    </div>
</template>

<style scoped>
.box{
    width:400px;
    height: 20px;
    border: 1px solid black;
}
</style>
View Code

四、父子通信

组合式API下的父传子
基本思想
1.父组件中给子组件绑定属性
2.子组件内部通过props选项接收
组合式API下的子传父
基本思想
1.父组件中给子组件标签通过@绑定事件
2.子组件内部通过emit方法触发事件

demo如下:父传子,子传父

父组件

<script setup>
import {ref} from 'vue'
//局部组件导入即用,不用注册了
import Son1Com from '@/components/Son1Com.vue'
const money = ref(100)
const changeFn = () => {
    money.value -= 20
}
</script>

<template>
  <div class="box">
        <!--给子组件,以添加属性的方式传值-->
        <Son1Com @changeMoney='changeFn' message='天生我才必有用' :money='money'></Son1Com>
    </div>
</template>

<style scoped>
.box{
    width:400px;
    height: 20px;
    border: 1px solid black;
}
</style>
View Code

子组件

<script setup>
const props = defineProps({
    message:String,
    money:Number
})
console.log(props.message)
const emit = defineEmits(['changeMoney'])
const buy = () =>{
    //需要emit触发的事件
    emit('changeMoney',5)
}
</script>

<template>
    <!--props传来的数据,模块中可以直接用-->
    <div>
        {{message}}-{{money}}
        <button @click="buy">花钱</button>
    </div>
</template>

<style>
</style>
View Code

provide和inject

可以从上往下跨层传递普通数据、响应式数据和函数,语法如下。

//父组件,key为变量名,value可以是普通数据、响应式数据和函数
import {provide} from 'vue'
provide(key,value)
//子组件
import {inject} from 'vue'
const key = inject(key)

五、模板引用

使用
1.调用ref函数生成一个ref对象
2.通过ref标识绑定ref对象到标签
3.通过ref对象.value即可访问到绑定的元素(必须渲染完成后,才能拿到)

<script setup>
import {ref,onMounted} from 'vue'
const pRef = ref(null)
onMounted(() => {
    console.log(pRef.value)
})
</script>

<template>
  <div class="box">
        <p ref="pRef">阿龙学前端</p>
    </div>
</template>

defineExpose()
默认情况下在<script setup>语法糖下组件内部的属性和方法是不开放给父组件访问的,可以通过defineExpose编译宏指定哪些属性和方法允许访问
六、新特性

Vue3.3新特性-defineOptions
Vue 3.3中新引入了defineOptions 宏。顾名思义,主要是用来定义Options API的选项。可以用defineOptions定义任意的选项,props, emits, expose, slots除外( 因为这些可以使用defineXXX来做到)

Vue3中的v-model和defineModel
在Vue3中,自定义组件上使用v - model,相当于传递一个modelValue属性,同时触发update :modelValue事件