VUE3
Vue3现状
-
vue-next 2020年9月18日,正式发布了vue3.0版本
-
主流的组件库已经发布了支持vue3.0的版本
- element-plus基于Vue3.0的桌面端组件库
- vant vant3.0版本移动端组件库
- ant-design-vue
Vue3 优点
-
最火框架,国内最火的框架之一
-
性能提升,运行速度是vue2.x的1.5倍左右
-
体积更小 ,按需编译体积比vue2.x 要更小
-
类型推断,更好的支持TS (typescript)
-
高级给予 暴露了更底层的API和提供更先进的内置组件
-
组合API(composition API) 能够更好的组织逻辑,封装逻辑,复用逻辑
为什么要学习vue3
适应市场学习流行的技术提高提升自己竞争力,加薪
vite基本使用
vite是什么
- 是一个更加轻量(热更新速度快,打包构建速度快)的vue项目的脚手架工具
- 相对于vue-cli 它默认安装的插件非常少,随着开发过程依赖增多,需要自己额外配置
vite使用
- 创建项目 npm init vite-app 项目名称 或者 yarn create vite-app 项目名称
- 安装依赖 npm i 或者 yarn
- 启动项目 npm run dev 或者 yarn dev
Vue3应用
- main.js中导入createApp函数
- 定义App.vue组件,导入main.js
- 使用createApp函数App.vue组件创建应用实例
- 挂载到index.html的#app容器
// 导入createApp函数
import { createApp } from 'vue'
import App from './App.vue'
import './index.css'
// 使用createApp(App) 函数基于App.vue组件创建应用实例
// 挂载到index.html的#app容器
// 扩展功能都是在app上进行
const app =createApp(App)
app.mount('#app')
选项API和组合API
什么是选项API写法Options Api
我们在vue2.x项目中使用的就是选项API写法
风格:data选项写数据,methods选项写函数....一个功能逻辑的代码分散
优点:易于学习和使用,写代码的位置已经约定好
缺点:代码组织性差,相似的逻辑代码不便于复用,逻辑代码多了不好阅读和管理
<template>
<div class="container">
<div>鼠标位置</div>
<div>X轴:{{ x }}</div>
<div>Y轴{{ y }}</div>
</div>
</template>
<script>
export default {
name: 'App',
data() {
return {
x: 0,
y: 0,
}
},
mounted() {
document.addEventListener('mousemove', this.move)
},
methods: {
move(e) {
this.x = e.pageX
this.y = e.pageY
},
},
destroyed() {
document.removeEventListener('mousemove', this.move)
},
}
</script>
组合API Composition API
在vue3项目中使用组合API写法
代码风格: 一个功能逻辑的代码组织在一起(包括数据,函数.....)
优点:功能逻辑复杂的情况下,各个功能逻辑代码组织在一起,便于阅读和维护
缺点: 需要良好的代码组织能力和拆分逻辑能力
补充: 为了能让大家较好的过渡到vue3.0,在vue3中也支持vue2.x的选项Api的写法
<template>
<div class="container">
<div>鼠标位置</div>
<div>X轴:{{ x }}</div>
<div>Y轴{{ y }}</div>
</div>
</template>
<script>
import { onMounted, onUnmounted, reactive, toRefs } from 'vue'
export default {
setup() {
// 定义逻辑数据
const mouse = reactive({
x: 0,
y: 0,
})
const move = (e) => {
mouse.x = e.pageX
mouse.y = e.pageY
}
onMounted(() => {
document.addEventListener('mousemove', move)
})
onUnmounted(() => {
document.removeEventListener('mousemove', move)
})
return {
...toRefs(mouse),
}
},
}
</script>
组合API-setup函数
- setup是一个新的组件选项,作为组件中使用组合API的起点
- 从组件生命周期来看,它(setup)的执行在组件实例创建之前beforeCreate执行
- setup函数中this还不是组件实例,this是undefined
- 在模板(视图)中需要使用的数据和函数,需要在setup中返回
<template>
<div class="container">
<button @click="say">{{ msg }}</button>
</div>
</template>
<script>
export default {
beforeCreate() {
console.log(2)
},
// setup在组件创建实例之前执行
setup() {
console.log(1, this) //this undefined
// 定义数据和函数
const msg = 'hello'
const say = () => {
console.log(msg)
}
return { msg, say }
},
}
</script>
总结:setup组件初始化之前执行,它返回的数据和函数可以在模板中使用
组合API-生命周期
回顾vue2生命周期钩子函数
beforeCreate 创建前
created 创建完成
beforeMount 挂载前
mounted 挂载完成
beforeUpdate 更新前
updated 更新完成
beforeDestroy 销毁前
destroyed 销毁完成
vue3.0生命周期钩子函数
- setup 创建实例前
- onBeforeMount 挂载DOM前
- onMounted挂载DOM后
- onBeforeUpdate 更新组件前
- onUpdated 更新组件后
- onBeforeUnmount 卸载销毁前
- onUnmounted 卸载销毁后
<template>
<div class="container">container</div>
</template>
<script>
// 按需引入
import { onBeforeMount, onMounted } from 'vue'
export default {
setup() {
// 挂载DOM前
onBeforeMount(() => {
console.log('DOM渲染前', document.querySelector('.container'))
//DOM渲染前 null
})
// 挂载DOM后
onMounted(() => {
console.log('DOM渲染后', document.querySelector('.container'))
//DOM渲染后 <div class="container">container</div>
})
//可以多次使用同一个钩子,执行顺序和书写顺序相同
onMounted(() => {
console.log('DOM渲染后2', document.querySelector('.container'))
})
},
}
</script>
总结: 组合API的生命周期钩子有7个,可以多次使用同一个钩子,执行顺序和书写顺序相同
组合API-reactive
reactive是一个函数,它可以定义一个复杂数据类型,成为响应式数据
<template>
<div class="container">
<h2>reactive是一个函数,它可以定义一个复杂数据类型,成为响应式数据</h2>
<div>{{ obj.name }}</div>
<div>{{ obj.age }}</div>
<button @click="updateName">修改数据</button>
</div>
</template>
<script>
// 按需引入
import { reactive } from 'vue'
export default {
setup() {
// 普通数据---不是响应式的
// const obj = {
// name: 'zs',
// age: 18,
// }
// 响应式数据
const obj = reactive({
name: 'zs',
age: 18,
})
// 修改名字
const updateName = () => {
console.log('updateName')
obj.name = 'ls'
}
return { obj, updateName }
},
}
</script>
总结: reactive用来定义响应式对象数据
组合API-toRef函数
定义响应式数据
toRef是函数,转换响应式对象中某个属性为单独响应式数据,并且值是关联的
<template>
<div class="container">
<h2>
toRef是函数,转换**响应式对象**中某个属性为单独响应式数据,并且**值是关联的**
</h2>
<div>{{ name }}</div>
<button @click="updateName">修改数据</button>
</div>
</template>
<script>
// 按需引入
import { reactive, toRef } from 'vue'
export default {
setup() {
// 1 定义响应式数据对象
const obj = reactive({
name: 'ls',
age: 19,
})
console.log(obj)
// 2模板中只需要使用name数据
// 从响应式数据对象中解构出属性数据,不再是响应式数据
// let { name } = obj //不能直接解构,出来的是一个普通数据
// const updateName = () => {
// console.log('updateName')
// obj.name = 'zs'
// }
// -----解决办法
const name = toRef(obj, 'name')
console.log(name, 'name')
const updateName = () => {
console.log('updateName')
// toRef 转换响应式数据包装成对象 value存放值的位置
name.value = 'zss'
}
return { name, updateName }
},
}
总结:有一个响应式对象数据,但是模板中只需要使用其中一项数据
组合API-toRefs函数
定义响应式数据
toRefs是函数,转换响应式对象中所有属性为单独响应式数据,对象成为普通对象,并且值是关联的
<template>
<div class="container">
<h2>
toRefs是函数,转换**响应式对象**中所有属性为单独响应式数据,对象成为普通对象,并且**值是关联的**
</h2>
<div>{{ name }}</div>
<div>{{ age }}</div>
<button @click="updateName">修改数据</button>
</div>
</template>
<script>
// 按需引入
import { reactive, toRef, toRefs } from 'vue'
export default {
setup() {
// 1 定义响应式数据
const obj = reactive({
name: 'ls',
age: 10,
})
// 解构 或者展开响应式数据对象---普通数据
// const { name, age } = obj
// const obj1 = { ...obj }
// toRefs
const obj2 = toRefs(obj)
const updateName = () => {
obj.name = 'zs'
obj.age++
}
// return { ...obj1, updateName }
return { ...obj2, updateName }
},
}
</script>
总结:把响应式对象中的多个或者所有属性做为响应式数据
组合API-ref函数
定义响应式数据
ref函数,常用于简单数据类型定义为响应式数据
- 在修改值,获取值的时候,需要加 .value
- 在模板中使用ref声明的响应式,可以省略 .value
<template>
<div class="container">
<h2>ref函数,常用于**简单数据类型**定义为响应式数据</h2>
<div>{{ name }}</div>
<div>{{ data }}</div>
<button @click="updateName">修改数据</button>
</div>
</template>
<script>
// 按需引入
import { ref } from 'vue'
export default {
setup() {
// 1 name数据
const name = ref('ls')
console.log(name.value)
const updateName = () => {
name.value = 'zs'
}
// ref常用于定义简单数据类型的响应式数据
// 其实也可以定义复杂数据类型的响应式数据
// 对于数据未知的情况下,ref是最适用的
// 初始值
const data = ref(null)
setTimeout(() => {
// 发送请求 拿到数据 {name:'zs'}
// data.value = res.data
data.value = { name: 'zs' }
}, 1000)
return { name, updateName, data }
},
}
</script>
总结:
当你明确知道需要的是一个响应式数据对象,就使用用reactive
其它情况使用ref