2020年9月18日发布
2022年2月7日称为默认版本,意味vue3是现在也是未来
Ant Design Pc端组件库
Element Plus Pc端组件库
Vant 移动端
VueUse 基于composition 组合式api的常用函数集合
vue3中文文档:https://cn.vuejs.org/guide/introduction.html
1. vue3特点
- Composition API 组合API
- 首次渲染更快
- diff算法更快
- 内存占用更小
- 打包体积更小
- 更好的TypeScript支持
2. vue3项目的创建
- vue-cli脚手架创建—webpack
需要查找依赖,打包所有的模块,然后才能提供服务,更新速度会随着代码体积增加越来越慢
vue create xxx
-
vite构建工具
vite 意为 ‘快速的’,是一种新型的前端构建工具
使用原生ESModule通过script标签动态导入,访问页面的时候加载到对应模块编译并响应
注明:项目打包的时候最终还是需要打包成静态资源,打包工具Rollup
3.vite创建项目
npm create vite@latest
yarn create vite
pnpm create vite
4.代码分析
vue3组件代码和vue2不一样,使用的语法提示和高亮插件也是不一样
vetur插件禁用 安装Vue Language Features (Volar)插件
vue3写法不同
-
组件一个根节点非必需
-
创建应用挂载到根容器
-
入口页面,ESM加载资源
<body> <div id="app"></div> <script type="module" src="/src/main.ts"></script> </body>
组合式API
vue3提供了两种组织代码逻辑的写法:
- 通过data,methods,watch等配置选项组织代码逻辑 是选项API的写法
- 所有逻辑在setup函数中,使用ref,reactive等函数组织代码 是 组合式API写法
option api
<template>
<div>
<button @click="toggle">显示隐藏</button>
<img v-if="show" src="./assets/logo.png" />
<div @click="increment">{{ count }}</div>
</div>
</template>
<script>
export default {
data(){
return {
show:true,
count:0
}
},
methods:{
toggle(){
this.show=!this.show
},
increment(){
this.count++
}
}
}
</script>
组合式api
<template>
<div>
<button @click="toggle">显示隐藏</button>
<img v-if="show" src="./assets/logo.png" />
<div @click="increment">{{ count }}</div>
</div>
</template>
<script setup>
import {ref} from 'vue'
let show =ref(true)
const toggle=()=>{
show.value =!show.value
}
let count = ref(0)
const increment=()=>{
count.value++
}
</script>
setup
- setup函数是vue3特有的选项,作为组合式api的起点
- 从组件生命周期来看,setup在beforeCreate之前执行
- 函数中this不是组件实例 是undefined
- 如果数据或者函数在模板中使用,需要在setup中返回
<script>
import {ref} from 'vue'
export default{
setup(){
console.log("setup")
let show =ref(true)
const toggle=()=>{
show.value =!show.value
}
let count = ref(0)
const increment=()=>{
count.value++
console.log(this)
}
return {show,toggle,count,increment}
},
beforeCreate(){
console.log("beforeCreate")
}
}
</script>
setup语法糖
<script setup>
import {ref} from 'vue'
let show =ref(true)
const toggle=()=>{
show.value =!show.value
}
let count = ref(0)
const increment=()=>{
count.value++
console.log(this)
}
</script>
reactive
- 使用reactive函数传入一个普通对象,返回一个响应式数据对象
- 可以转换简单数据吗?? 不能
<template>
<div>
<p>姓名:{{ state.name }}</p>
<p>年龄{{ state.age }}</p>
<button @click="change">更改</button>
</div>
</template>
<script setup>
// 1.vue中导出reactive函数
import {reactive} from 'vue'
// 使用reactive函数,传入一个普通对象,返回一个响应式数据对象
const state =reactive({name:"lucy",age:23})
const change = ()=>{
state.age=34
state.name ="牛牛"
}
</script>
ref
- 使用ref函数,传入普通数据 or 复杂 ,返回一个响应式数据
- 注意,使用ref创建的数据,js中需要.value ,template中可省略
<template>
<div>
<p>姓名:{{ state.name }}</p>
<p>{{count}}</p>
<button @click="change">更改</button>
</div>
</template>
<script setup>
// 1.vue中导出ref函数
import {reactive,ref} from 'vue'
// 2.使用ref函数 传入普通数据 or 复杂 返回一个响应式数据
let count = ref(0)
let state = ref({name:'lucy'})
const change = ()=>{
// js中使用需要.value
count.value += 3
state.value.name ='zs'
}
</script>
reactive可以转换对象为响应式数据,但是不支持简单数据类型
ref可以转换简单数据类型为响应式数据,也支持复杂数据类型 但是操作的时候需要.value
【推荐】如果能确定数据是对象且字段名称也确定,使用reactive,其他使用ref
案例
<template>
<button @click="toggle">显示隐藏图片</button>
<img src="./assets/vue.svg" alt="" v-show="show">
<hr/>
计数器{{ count }} <button @click="change">累加</button>
</template>
<script setup>
import {ref} from 'vue'
let count = ref(0)
let show = ref(true)
const toggle = ()=>{
show.value = !show.value
}
const change = ()=>{
count.value ++
}
</script>
computed
<template>
<div>
<p>{{ scoreList }}</p>
<p>{{ betterList }}</p>
<input type="checkbox" v-model="allCheck" />
<ul>
<li v-for="item in arr" :key="item.id">
<input type="checkbox" v-model="item.flag" />{{ item.name }}
</li>
</ul>
</div>
</template>
<script setup>
import {ref,reactive,computed} from 'vue'
const scoreList = ref([12,80,100,90,70,60])
// 计算属性
const betterList = computed(()=>scoreList.value.filter(item=>item>90))
const arr = ref([
{id:1,name:'aaa',flag:true},
{id:2,name:'bbb',flag:true},
{id:3,name:'ccc',flag:false},
{id:4,name:'ddd',flag:true}
])
// 完整写法
const allCheck=computed({
get(){
return arr.value.every(item=>item.flag==true)
},
set(v){
arr.value.forEach(item=>{
item.flag=v
})
}
})
// 改变数据 计算属性改变
// setInterval(()=>{
// scoreList.value.push(90,92)
// },1000)
</script>
watch
<template>
<div>
{{ count }}---{{ user.info.age}}---{{ user.name }}
</div>
</template>
<script setup>
import {ref,watch,reactive} from 'vue'
const count =ref(0)
const user=reactive({
name:'tom',
info:{
gender:"男",
age:14
}
})
// 1.监听一个响应式数据
// watch(数据,改变后回调函数)
// watch(count,()=>{
// console.log("count改变了")
// })
// 2.监听多个响应式数据
// watch([数据1,数据2...],回调函数)
// watch([count,user],()=>{
// console.log("数据改变了")
// })
// setTimeout(()=>{
// count.value++
// },1000)
// 3.监听响应式对象数据的一个属性 简单类型
watch(
()=>user.name,
()=>{
console.log("数据改变")
},
{
immediate:true //默认执行一次
}
)
// 4.监听响应式对象数据的一个属性 复杂类型
watch(
()=>user.info,
()=>{
console.log("数据改变了")
},
{
// 开启深度监听
deep:true
}
)
// watch(需要监听的数据,数据改变的函数,配置对象)
// setTimeout(()=>{
// // user.info.age++
// user.name = 'zs'
// },3000)
setTimeout(()=>{
user.info.age++
// user.name = 'zs'
},2000)
</script>
生命周期函数
- vue3中生命周期钩子函数可以调用多次
对比
选项式API | 组合式API |
---|---|
beforeCreate | 不需要 (直接写到setup函数中) |
created | 不需要 (直接写到setup函数中) |
beforeMount | onBeforeMount |
mounted | onMounted |
beforeUpdate | onBeforeUpdate |
updated | onUpdated |
beforeDestroyed | onBeforeUnmount |
destroyed | onUnmounted |
activated | onActivated |
deactivated | onDeactivated |
<template>
<div>
生命周期
</div>
</template>
<script setup>
import {onMounted} from 'vue'
onMounted(()=>{
console.log(1)
})
onMounted(()=>{
console.log(2)
})
</script>
ref获取Dom元素
- 1.创建ref const hRef = ref(null)
- 2.模板中建立关联 <组件 ref = “hRef”/>
- 3.使用 hRef.value
<template>
<div>
<h1 ref="hRef">我是标题</h1>
<HelloWorld ref="myRef"></HelloWorld>
</div>
</template>
<script setup>
import HelloWorld from './components/HelloWorld.vue';
import {ref,onMounted} from 'vue'
// 1创建
const hRef = ref(null)
const myRef = ref(null)
onMounted(()=>{
console.log(myRef.value)
})
</script>