Vue3
vue2为选项是(options)API,Vue3为组合是API
相比于Vue2优势:
1. 创建Vue3项目
前置条件:必须保证node的版本高于16.0
创建vue3项目:
npm init vue@latest
2. setup
setup本质:需要将数据和方法return才能给模板使用
<script>
export default {
setup(){
const message = 'this is message'
const logMessage = ()=>{
console.log(message)
}
// 必须return才可以
return {
message,
logMessage
}
}
}
</script>
语法糖:直接在script标签上加上setup
<script setup>
const message = 'this is message'
const logMessage = ()=>{
console.log(message)
}
</script>
3. 响应式数据 - reactive和ref函数
3.1 reactive()
接受对象类型数据的参数传入并返回一个响应式的对象,不接受简单数据类型
<script setup>
import { reactive } from 'vue'
// 响应式数据
// 1. 使用reactive()包装,只能包装对象类型数据
const state = reactive({
count: 1
})
const add = () => {
state.count++
}
</script>
<template>
<div>
<!-- reactive() -->
{{ state.count }} <br>
<button @click="add">+1</button>
</div>
</template>
3.2 ref()
接收简单类型或者对象类型的数据传入并返回一个响应式的对象
在js中访问得加.value,在模板中直接使用
<script setup>
import { ref } from 'vue'
// 响应式数据
// ref() 可以包装基本类型数据, 也可以包装对象类型数据
// 在js中获取数据需要.value获取,在模板中不需要
let count = ref(1)
const addTwo = () => {
// js中需要.value获取
count.value += 2
}
</script>
<template>
<div>
<!-- ref()-->
<!-- 模板中使用直接使用-->
{{ count }}
<button @click="addTwo">+2</button>
</div>
</template>
4. computed
用法和vue2一样,只是写法上发生了改变,computed() 为函数,在函数里面写回调函数,计算要计算的数据
<script setup>
import { computed, ref } from "vue";
const arr = ref([0, 1, 2, 3, 4, 5])
// computed函数里写箭头函数
const computedArr = computed(() => arr.value.filter((item) => item > 2))
let num = 6
const timer = setInterval(() => {
num += 2
arr.value.push(num)
if (num > 10) {
clearInterval(timer)
}
}, 2000)
</script>
<template>
<div>
初始数组:{{ arr }}
<br>
computed: {{ computedArr }}
</div>
</template>
<style scoped>
</style>
5. watch
侦听一个或者多个数据的变化,数据变化时执行回调函数,俩个额外参数 immediate控制立刻执行,deep开启深度侦听
watch()函数第一个参数为监听的ref对象,第二个参数为监听的回调函数,可以监听到新值和旧值,第三个参数为额外参数的对象
- 监听单个数据
- 监听多个,watch函数中要监听的数据写成数组的形式
- 深度监听deep:watch默认为浅层监听,只能监听到基本数据类型的数据的改变,复杂类型只能监听到对应的地址
- 监听器创建时立即执行一次,发生改变时继续执行immediate
- 监听复杂数据类型中指定的数据,第一个参数为回调函数的写法,函数体内写要监听的数据
<script setup>
import { ref, watch } from "vue";
const count = ref(1)
const message = ref("Hello")
const user = ref({
age: 18,
name: 'zs'
})
// watch第一个参数为ref对象,第二个参数为回调函数,可以监听新值和旧值,第三个参数为高级属性对象
// 1. 监听单个
watch(count, (newValue, oldValue) => {
console.log(newValue, oldValue)
})
// 2. 监听多个, 监听的数据写成数组的形式
watch([count, message], (newValue, oldValue) => {
// 只要有一个数据发生改变都会的所有监听数据的新值和旧值
console.log(newValue, oldValue)
})
// 3. 深度监听 deep
watch(user, (newValue, oldValue) => {
console.log('深度监听:', newValue, oldValue)
}, {
// 第三个参数中可以开启深度监听
deep: true
})
// 4. 监听器创建时立即执行一次,发生改变时继续执行 immediate
watch(count, (newValue, oldValue) => {
console.log('immediate:', newValue, oldValue)
})
// 5. 监听复杂类型中的特定数据
watch(()=> user.value.age, (newValue, oldValue) => {
console.log('特定数据age:', newValue, oldValue)
})
const changeCount = () => count.value++
const changeMessage = () => message.value = 'world'
const changeUserAge = () => user.value.age = 20
const changeUserName = () => user.value.name = 'ls'
</script>
<template>
<div>1</div>
<button @click="changeCount">count+1</button>
<button @click="changeMessage">changeMessage</button>
<button @click="changeUserAge">changeUserAge</button>
<button @click="changeUserName">changeUserName</button>
</template>
<style scoped>
button {
margin: 5px;
}
</style>
6. 生命周期函数
导入对应的生命周期函数,在对应的生命周期函数中传入回调函数即可使用,如狗有多个相同的生命周期函数,会按顺序依次执行
<script setup>
// 生命周期
// vue2中的beforeCreate和created相当于vue3组合式API中的setup
// 因此在script标签上加了setup语法糖的可以直接写直接调用
import { onMounted } from "vue";
const getList = () => {
console.log('getList')
}
// 直接调用, 相当于创建vue实例的时候
getList()
// 其他生命周期函数需要写在对应的函数里
onMounted(() => {
console.log('onMounted1')
})
// 相同的生命周期按书写的顺序调用
onMounted(() => {
console.log('onMounted2')
})
</script>
<template>
</template>
<style scoped>
</style>
7. 组件通信
-
父传子
- 父组件给子组件绑定自定义属性传值
- 子组件通过defineProps编译器宏创建props选项接收数据
-
子传父
- 父组件给子组件绑定事件
- 子组件内部通过defineProps编译器宏创建emit方法出发事件
8. 模板引用 - 获取节点
可以获取DOM对象或者组件实例对象
调用ref函数传null生成一个ref对象,通过ref属性绑定到标签上即可获取
setup环境中不能直接使用,因为还没创建完,可以在onMounted或者等元素渲染完成之后调用
获取组件实例得通过defineExpose指定哪些属性或者方法允许外部访问外部才能访问到
9. 跨层级传递数据
- 顶层使用
provide()
函数提供数据- 底层使用
inject()
函数接收数据- 可以传递基本数据类型、复杂数据类型也可以传递方法
语法:
// 传递信息
provide('key', 数据、方法)
// 接收数据
const message = inject('key')
10. Vue3.3新特性
10.1 defineOptions
有
<script setup>
之前,如果要定义 props, emits 可以轻而易举地添加一个与 setup 平级的属性。但是用了
<script setup>
后,就没法这么干了 setup 属性已经没有了,自然无法添加与其平级的属性。简而言之,defineOptions中可以定义选项式的一些属性
<script setup>
import {defineOptions} from 'vue'
defineOptions({
name: 'loginIndex'
})
</script>
10.2 defineModel
可以实现在组件上使用v-model可以自由修改并响应数据
vue3.3需要开启额外配置,3.4以上版本不需要
<script setup>
import { defineModel } from 'vue'
// 使用defineModel接收父组件绑定的v-model可以简单的实现数据的双向绑定,可以直接修改父组件中的值
const modelVal = defineModel()
const changeFatherMeg = () => {modelVal.value = 'sonMessage'}
</script>
vue3.3 需要额外在vite.config.js开启配置
import { fileURLToPath, URL } from 'node:url'
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
// https://vitejs.dev/config/
export default defineConfig({
plugins: [
vue({
script: {
defineModel: true
}
}),
],
resolve: {
alias: {
'@': fileURLToPath(new URL('./src', import.meta.url))
}
}
})
11. pinia
pinia是Vue最新的状态管理工具,是Vuex的替代品,提供更简单的API,对ts支持更好
11. 1. 开始使用
按照官方文档安装完成之后即可使用,也可以在创建项目的时候直接勾选上
- 定义
- 在模块中定义pinia直接使用内置函数
definStore()
进行创建 - 创建的ref()对象就是store数据
- 创建的function就是action,可以发送异步请求
- 创建的computed就是getters
- 最后需要将定义的数据或方法返回才能够使用
- 在模块中定义pinia直接使用内置函数
import { defineStore } from "pinia";
import { computed, ref } from "vue";
export const useCounterStore = defineStore('唯一标识', {
// 核心内容,store, actions, getters
// store
const count = ref(1)
// actions
const changeCount = () => {}
// getters
const computedCount = computed(() => count.value * 2)
// 返回数据使用
return {
count,
changeCount,
computedCount
}
})
-
使用
- 导入定义的store
- 执行方法得到对象
- 根据对象使用里面的方法
- 直接解构的话数据将不是响应式数据,需要使用storeToRefs()包装
<script setup> // 导入store import { useCounterStore } from "@/store/counter.js"; // 执行方法得到store对象 const counterStore = useCounterStore() // 解构使用storeToRefs包装保持响应式 const { count } = storeToRefs(counterStore) </script> <template> <div> <!-- 使用 --> count - {{ counterStore.count }} <!-- 解构数据使用--> 解构count:-- {{ count }} </div> </template>
11.2 持久化插件
官方文档:https://prazdevs.github.io/pinia-plugin-persistedstate/zh/
- 安装插件 pinia-plugin-persistedstate
npm i pinia-plugin-persistedstate
- 使用 main.js
import persist from 'pinia-plugin-persistedstate'
...
app.use(createPinia().use(persist))
- 配置开启持久化
-
persist: true 默认将所有数据进行持久化,key为唯一标识
import { defineStore } from 'pinia' import { computed, ref } from 'vue' export const useCounterStore = defineStore('counter', () => { ... return { count, changeCount, computedCount } }, { persist: true // 开启持久化,默认将所有数据进行持久化,key为唯一标识 })
-
自定义配置
import { defineStore } from 'pinia' import { computed, ref } from 'vue' export const useCounterStore = defineStore('counter', () => { ... return { count, changeCount, computedCount } }, { persist: { // 写成对象形式可以配置更多选项 key: 'startCounter', // 配置自定义key paths: ['count'] // 指定哪些属性进行持久化 ...其他自定义配置 } })
-