“携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第10天,点击查看活动详情”
Vue3基础
选项式 API
组件的初始化还是和Vue2那样
组合式API
eg:
import { ref } from 'vue'
// ref 就是一个组合式API
export default {
setup(){
const show = ref(true)
const toggle = () => {
show.value = !show.value
}
const count = ref(0)
const increment = () => {
count.value++
}
return { show,toggle,count,increment }
}
}
setup 函数
❗setup 函数是 Vue3 特有的选项,作为组合式API的起点,注意以下三点:
- 从组件生命周期看,它在
beforeCreate之前执行 - 函数中
this不是组件实例,是undefined - 如果数据或者函数在模板中使用,需要在
setup返回
经验:
今后在vue3的项目中几乎用不到 this
reactive 函数
1. 导入 reactive 函数
import { reactive } from 'vue'
2. 通过 reactive 函数包装成响应式对象
const obj = reactive({
name:'zs',
age:18
})
const btn = () => {
obj.age++
}
3. 返回给模板使用
return { obj,btn }
组合式API-ref函数
ref 函数,可以把任意类型数据转换成响应式。
- 从
vue中导入ref函数 - 在
setup函数中,使用ref函数包装成响应式数据(不分类型) - 最后
setup函数返回一个对象,包含该响应式数据即可
❗使用 ref 的两个注意点:
-
<script>中需要.value -
<template>会自动解套,不需要.value
setup 语法糖
computed 函数
-
导入 computed 函数
import {computed} from 'vue' -
调用 computed 函数并传入一个回调函数
const computedRes = computed(() => { return xx}) -
函数内部记得 return 返回结果
watch 函数
watch 参数
-
被监听的数据
-
回调函数
-
配置项(可选)
基本写法
基础类型
import { ref,watch } from 'vue'
const money = ref(1400)
watch(money,() => {
console.log('钱变化了', money.value)
})
复杂类型
watch(obj,() => {
console.log('obj变化了', obj.value)
},{
deep:true,
immediate:true
}
)
进阶写法
基础类型
import { ref,watch } from 'vue'
const money = ref(1400)
watch(money,(newVal,oldVal) => {
console.log('钱变化了',newVal,oldVal)
})
复杂类型
✨通过 getters 函数写法,可以侦听对象的某个属性
✨通过数组,可同时侦听多个数据
watch(
[()=> obj.value.age,() => obj.value.cp.age],
(newVal,oldVal){
console.log('obj变化了',newVal,oldVal)
},
{
deep:true
}
)
模板ref
获取DOM元素
-
创建 ref
const hRef = ref(null) -
模板 ref 建立关联
<h1 ref="hRef"></h1> -
组件挂载完毕后可以访问 DOM节点
onmounted { hRfe.value }
应用场景
//需求:获取输入框焦点
const iptRef = ref(null)
<input ref="inputRef" type="text" />
const focusClick = () =>{
iptRef.value.focus()
}
// 需求:获取输入框焦点
<audio ref="audioRef" controls>
audioRef.value.play()
父传子
基本结构
在 script 中用defineProps获取 props
// father:
const money = ref(100)
<Children :money="money">
// son:
<script setup>
// 在 script 中获取 props
const props = defineProps({
money:Number,
car:String
})
console.log('在script中获取props', props.money)
</script>
子传父 defineEmits
父
<ChildCom @change-money="changeMoneyFn" :money="money"></ChildCom>
子
定义 emit ,显式声明事件名称
const emits = defaultEmits(['changeMoney'])
const btn = () => {
emit('changeMoney',100) // ❗注意没有 this
}
跨组件通讯
provide 提供数据
provide('count',count)
inject 获取数据
const count = inject('count')
辅助函数toRefs
const user = reactive({ name:'zg',age:80 })
const res = toRfes(user)
把 obj 的每一个属性都变成独立的 ref 对象,所以解构出来的每个属性都是响应式的 ref
const { name,age } = toRefs(user)
核心库
vue-router
基础使用
安装 npm i vue-router@4 --save
导入 创建路由实例的函数 和 创建历史模式 的函数
import { createRouter,createWebHashHistory } form 'vue-router'
// 创建路由实例
const router = createRouter({
history:createWebHashHistory,
routes:[]
})
export default router
挂载路由:
main.js
import router from './router'
// 以插件形式使用 router
app.use(router)
路由配置和路由组件
在路由实例的 路由表
routes: [
{ path: '/home', component: () => import('../views/HomePage.vue') },
{ path: '/login', component: () => import('../views/LoginPage.vue') },
],
路由链接与路由出口
<router-link> <router-view>
vue-router-组合式API
因为我们在 setup 里面没有访问 this,所以我们不能再直接访问 this.$router
或 this.$route
使用 useRouter 和 useRoute 函数:
import { useRouter,useRoute } from 'vue-router'
获取全局路由实例
const router = useRoute()
获取当前路由信息
const route = useRoute()
使用:
router.push('/home')
route.query/route.path/route.fullPath/route.params
pinia
基础使用
安装 npm i pinia@2 --save
在 main.js中使用
import { createPinia } from 'pinia'
app.use(createPinia())
pinia 的 store
三个概念,state、getters 和 actions,可以假设这些概念相当于组件中的 data、 computed 和 methods。
✨pinia没有mutation,用起来更加方便
pinia 支持两种 API 风格:
defineStore('唯一标识',选项式API配置)defineStore('唯一标识', 组合式API函数)
返回值是一个用于获取 store 的函数
建议命名规范:useXxxStore
export const useCounterStore = defineStore('counter',{
state:() => { return { count:0 }}
})
使用
import { useCounterStore } from './store/counter'
// 调用获取 store 的函数
const counterStore = useCounterStore()
{{ counterStore.count }}
选项式API写法
state:()=>{
return { count:100 }
}
// getters 看做 computed
getters: {
doubleCount() {
// 返回计算的结果
return this.count * 2
},
},
// 使用 {{ counterStore.doubleCount }}
// actions 看做 methods,支持同步和异步,传参也很方便
actions: {
// 支持同步
addCount(val) {
this.count += val
},
// 支持异步
addCountASync() {
setTimeout(() => {
this.count++
}, 1000)
},
},
// 使用 @click="couterStore.addCount(10)"
组合式API写法
import { defineStore } from 'pinia'
import { computed,ref } from 'vue'
export const useMoneyStore = defineStore('money',()=>{
// state
const salary = ref(1400)
// getters
const doubleSalary = computed(()=> saraly.value*2)
// actions
const addSalaryAsync = () =>{
setTomeout(()=>{
salary.value++
},1000)
}
// actions
const addSalary = (val)=>{
salary.value += val
}
// 🚨 注意:要使用的数据或方法,记得通过 return 返回
return {salary,doubleSalary,addSalaryAsync}
})
辅助函数storeToRefs
简化使用 store
import { storeToRefs } from 'pinia'
import { useMoneyStore } from './store/money'
const moneyStore = useMoneyStore()
❌直接解构数据会失去响应式
// const { salary,doubleSalary } = moneyStore
✅storeToRefs 解构后还支持响应式
const { salary,doubleSalary } = storeToRefs(moneyStore)
使用:{{ salary }} {{ doubleSalary }}
合并模块管理
从合并管理的模块中导入所需的 store
src/store/index.js
export * from './counter'
export * from './money'
App.vue
import { useCounterStore,useMoneyStore } from './store'
不用分别从 ./store/counter、 ./store/money中导入
TodoList案例
store return 回去时记得+{ }
...未完待续