vue3的使用
vue插件的补充
ElementPlus:经典中的经典,全面支持Vue3
Vant3:有赞团队开源移动UI组件库,全面支持Vue3
TDesign:鹅厂优质UI组件,配套工具完满,设计工整,文档清晰
Ant Design Vue:阿里前端 UI 库,面向企业级中后台
iView:View Design,要钱
vue3的作用
性能的提升(打包大小减少41%,初次渲染快55%, 更新渲染快133%,内存减少54%)
源码的升级(使用Proxy代替defineProperty实现响应式,重写虚拟DOM的实现和Tree-Shaking)
Vue3可以更好的支持TypeScript
新的特性
Composition API(组合API)
setup配置
ref与reactive
watch与watchEffect
provide与inject
新的内置组件
Fragment
Teleport
Suspense
其他改变
新的生命周期钩子
data 选项应始终被声明为一个函数
组合式api和配置项api
组合式api
都写道一个函数中,定义变量和定义方法,定义计算属性都是放在一次,不是拆到不同地方了
配置项api:之前vue2中的写法
就是不太好找过于分散
创建vue3 项目
vue3完全兼容vue2只是进一步的加强vue2
vue3创建项目的两种方法
cmd创建(跟vue2创建差不多选版本选择vue3)
第二种方法
工具链(项目的创建原理):
webpack和vite:一次性把es高版本转成低版本,把xx.vue 转成xx.js的方式,把es高版本的语法转成低版本
setup
setup是个函数,vue的代码都写在这里面
可以定义函数,可以定义匿名函数
如果想在templage中使用,必须return
如果要对变量加入响应式,需要使用ref包裹变量
data,methods都可以用,但是是setup函数先执行,才走其它
template中使用函数,变量,都优先用setup中的
setup最先执行,是再生命周期的beforeCreate前执行的,内部没有this,也不能用this了
ref函数
作用包裹变量实现响应式(变成前端页面上更改数据)导入方法:放在script标签里import {ref} from 'vue'
实际案例
不想改变前端的量可以这样定义
<template>
<div class="home">
名字:{{ name }}, 年龄是:{{ age }}, 爱好: {{ hobby }}
</div>
</template>
<script>
//导入ref函数
import {ref} from "vue";
export default {
name: 'HomeView',
setup(){
const name = 'yjx'
const age = '18'
const hobby = 'sss'
return {name,age,hobby}
改变前端的变量这样定义
<template>
<div class="home">
名字:{{ name }}, 年龄是:{{ age }}, 爱好: {{ hobby }}
<br>
<button @click="hans">点我增加年龄</button>
<button @click="yzx">点击更换年龄</button>
</div>
</template>
<script>
//导入ref函数
import {ref} from "vue";
export default {
name: 'HomeView',
setup(){
let name = ref('yjx')
let age = ref(18)
const hans = () => {
console.log(age) // 终端上打印数据
age.value = age.value + 1
}
const yzx = () => {
name.value = '久保'
}
return {name, age, hans, yzx}
}
函数定义方法
const 函数名 = () =>
定义常量和变量
前端页面不变的数据定义 const name = ‘数据’
前端改变的变量定义 let name =ref(数据’) 必要加ref函数才可以改变
reactive函数
使用方法
<template>
<div class="about">
名字:{{ data.name }}, 年龄是:{{ data.age }}, 爱好: {{ data.hobby }}
<br>
<button @click="hans">点我增加年龄</button>
</div>
</template>
<script>
import {reactive, ref} from "vue";
export default{
name: 'AboutView',
setup(){
let data = reactive({'name': 'yjx', 'age': 18, 'hobby': '羽毛球'})
const hans = () => {
data.age += 1
}
return {data, hans}
}
}
</script>
需要点的方式来获取数据
ref和reactive
从定义数据角度对比:(ref用来定义:基本类型数据,reactive用来定义:对象(或数组)类型数据)
从原理角度对比:ref通过Object.defineProperty()的get与set来实现响应式(数据劫持),reactive通过使用Proxy来实现响应式(数据劫持), 并通过Reflect操作源对象内部的数据。
从使用角度对比:ref定义的数据:操作数据需要.value、读取数据时模板中直接读取不需要.value,reactive定义的数据:操作数据与读取数据:均不需要.value。
计算,监听属性
方式一简单监听
<template>
<div class="home">
名字:{{ name }}, 年龄是:{{ age }},
<br>
<button @click="hans">点我增加年龄</button>
<button @click="yzx">点击更换年龄</button>
</div>
</template>
<script>
//导入ref函数
import {ref, reactive, watch} from "vue";
export default {
name: 'HomeView',
setup(){
let name = ref('yjx')
let age = ref(18)
const hans = () => {
console.log(age) // 终端上打印数据
age.value = age.value + 1
}
const yzx = () => {
name.value = '久保'
}
watch(name, (newValue, oldValue) => {
console.log(oldValue)
console.log(newValue)
console.log('name变了')
})
return {name, age, hans, yzx}
}
方式二:监听属性之监听对象中的某个属性
<template>
<div class="about">
名字:{{ data.name }}, 年龄是:{{ data.age }}, 爱好: {{ data.hobby }}
<br>
<button @click="hans">点我增加年龄</button>
</div>
</template>
<script>
import {reactive, ref, watch} from "vue";
export default{
name: 'AboutView',
setup(){
let data = reactive({'name': 'yjx', 'age': 18, 'hobby': '羽毛球'})
const hans = () => {
data.age += 1
}
watch(() => data.age, () => {
console.log('data年龄变了')
})
return {data, hans}
}
}
</script>
同时监听多个变量
<template>
<div class="home">
名字:{{ name }}, 年龄是:{{ age }},
<br>
<button @click="hans">点我增加年龄</button>
<button @click="yzx">点击更换年龄</button>
</div>
</template>
<script>
//导入ref函数
import {ref, reactive, watch} from "vue";
export default {
name: 'HomeView',
setup(){
let name = ref('yjx')
let age = ref(18)
const hans = () => {
console.log(age) // 终端上打印数据
age.value = age.value + 1
}
const yzx = () => {
name.value = '久保'
}
watch([name,age], (newValue, oldValue) => {
console.log('name或者msg发生了变化', newValue, oldValue)
})
return {name, age, hans, yzx}
}
计算属性使用computed ,只有取值触发或取值赋值触发函数
基本使用
<template>
<div class="about">
<input type="text" v-model="name">-----{{newName}}
</div>
</template>
<script>
import {computed, reactive, ref, watch} from "vue";
export default{
name: 'AboutView',
setup(){
let name = ref('yzx') input默认框的数据
let newName = computed(() => {
return name.value + 'xn' 后面添加
})
return {newName,name}
了解:计算属性可以取值用,还可以改值
使用方法
<template>
<div class="about">
<input type="text" v-model="name">-----{{newName}}
<br>
<input type="text" v-model="newName">
</div>
</template>
<script>
import {computed, reactive, ref, watch} from "vue";
export default{
name: 'AboutView',
setup(){
let name = ref('')
let newName = computed({
get(){
// 使用计算属性,会触发这里
return name.value + '=xn'
},
set(value){
只要计算属性发生变化,就会执行这里
let res = value.split('=')
// 改变name的值的方法
name.value = res[0]
console.log('计算属性变了,变成', value)
}
})
return {name, newName}
}}
</script>
vue3生命周期
vue3不建议使用配置项api,把所有代码都写在setup函数中
没有destory这俩了,换成了unmounted
vue3与vue2的生命周期对比
beforeCreate===>setup()
created=======>setup()
beforeMount ===>onBeforeMount
mounted=======>onMounted
beforeUpdate===>onBeforeUpdate
updated =======>onUpdated
beforeUnmount ==>onBeforeUnmount
unmounted =====>onUnmounted
案例展示
子件
<template>
<div class="hello">
</div>
</template>
<script>
export default {
name: 'HelloWorld',
created() {
console.log('创建了created')
},
beforeUnmount() {
console.log('beforeUnmount执行了')
},
unmounted() {
console.log('unmounted执行了')
},
props: {
msg: String
}
}
</script>
<style scoped>
</style>
父件
<template>
<div class="home">
<button @click="yjx">点击显示</button>
<HelloWorld v-if="show"></HelloWorld>
</div>
</template>
<script>
import HelloWorld from "@/components/HelloWorld";
//导入ref函数
import {ref, reactive, watch} from "vue";
export default {
name: 'HomeView',
setup(){
let show = ref(true)
const yjx = () => {
show.value = !show.value
}
return {show, yjx}
},components:{
HelloWorld
}
}
</script>
vue3的写法
父件不变
<template>
<div class="hello">
</div>
</template>
<script>
import {ref} from "vue";
import {onBeforeMount, onMounted, onBeforeUpdate, onUpdated, onBeforeUnmount, onUnmounted} from "vue"; 导入方法
export default {
name: 'HelloWorld',
props: {
msg: String
},
setup(){
console.log('vue组件创建了') // (包含了beforeCreate,created) 组件创建完成,就发送Ajax请求,直接写在setup
let name=ref('')
axios.get('地址').then(res=>{ // 发送Ajax请求
name.value=res.data.name
})
var t = setInterval(()=>{ // 定时器
console.log('hello world')
}, 3000)
onBeforeUnmount(()=>{
console.log('onBeforeUnmount执行了')
clearInterval(t)
t = null
})
onUnmounted(()=>{
console.log('onUnmounted执行了')
})
}
}
</script>
<style scoped>
</style>
toPef(解压对象,可以直接使用变量不用点)
...{对象}---》相当于解压,再setup函数中return时,使用return {...toRefs(data)},以后再templte中直接使用内层的变量即可
使用方法
<template>
<div class="home">
{{name}} ------ {{age}} ------ {{hobby}}
<br>
<button @click="yjx">点一下就知道了</button>
<br>
<button @click="yzx">增加年龄</button>
</div>
</template>
<script>
import {ref, reactive, watch, toRefs} from "vue";导入toRefs
export default {
name: 'HomeView',
setup(){
console.log('执行了')
let a={hobby:'篮球', gender: '女'}
let b={...a,name:'式守'}
console.log(b)
var data = reactive({name:'yzx', age: 18})
const yjx = () => {
alert('久保')
}
const yzx = () => {
data.age+=1
}
return {...toRefs(data), yjx, yzx} ....解压对象
},
}
</script>
...toRefs(data) 等同于
vue3setup写法(不需要return,组件导入自动注册)
<script setup> // 这个script里面所有东西都是setup函数
import HelloWorld from "@/components/HelloWorld";// 组件导入
import {ref, toRefs} from "vue";
let name = ref('久保')
const yjx=()=>{
name.value = '02'
}
</script>
<template>
<div>
<h1>式守</h1>
{{name}}----
<br>
<button @click="yjx">点击变名字</button>
<HelloWorld msg="叶子曦"></HelloWorld>
</div>
</template>