第一章 Vue3基础 v1.0
第一部分 Vue3基本介绍
一、Vue3的优势
- 更容易维护:组合式API的引入与TypeScript支持
- 更快的速度:重写diff算法、模板编译优化与更高效的组件初始化
- 更小的体积:良好的TreeShaking与按需引入
- 更优的数据响应式:Proxy
二、选项式API与组合式API
选项式 API (Options API):
在 Vue 2 及早期版本中,我们主要使用的是选项式 API。每个 Vue 组件的选项都组织在一个对象中,包括 data、methods、computed、watch、lifecycle hooks 等。
组合式 API (Composition API):
Vue 3 引入了组合式 API,允许我们使用函数式的方式来组织组件的逻辑。它依赖于 setup 函数,该函数提供了一个响应式系统的入口点,并允许我们使用 ref、reactive、computed 等函数来创建响应式状态,以及使用 watch 和 watchEffect 来观察状态的变化。
使用对比(点击按钮使数字加1)
<script>
export default {
data () {
return {
count: 0
}
},
methods: {
addCount () {
this.count++
}
}
}
</script>
<script setup>
import { ref } from 'vue'
const count = ref(0)
const addCount = () => count.value++
</script>
三、代码结构
1.main.js
import './assets/main.css'
import { createApp } from 'vue'
import App from './App.vue'
// 使用 new Vue() 创建一个应用实例并挂载
createApp(App).mount('#app')
2.App.vue
<!-- setup允许在script中直接编写组合式API -->
<script setup>
// js逻辑结构
// 与Vue2不同,Vue3中组件只需要import即可使用,不需要注册
</script>
<template>
<!-- 模板结构 -->
</template>
<style scoped>
/* 样式结构 */
</style>
第二部分 组合式API
一、基本使用
1.setup选项
setup选项执行时机:早于beforeCreate钩子函数
<script setup>
const data = "abc"
const logData = () => {
console.log(data)
}
</script>
<script>
//<script setup>实际是一种语法糖,其完整写法与解释如下
export default {
setup () {
const data = "abc"
const logData = () => {
console.log(data)
}
return {
data,logData
}
}
}
</script>
2.ref()与reactive()
// 作用:接受一个简单类型或对象类型数据,返回一个封装后的响应式对象
// 一般推荐使用:统一代码规范
import { ref } from 'vue'
const data = ref(17)
console.log(data.value) // ref()对数据会进行一层封装,如需获取数据需要访问其value属性
// 作用:接受一个对象类型数据,返回一个响应式对象
// ref()通过包装数据再通过reactive()实现响应式数据的生成
import { reactive } from 'vue'
const data = reactive({
day : 17
})
console.log(data.day)
3.计算属性
思想与Vue2基本一致,只是修改了写法为使用computed函数
<script setup>
// 1.导入computed函数
import { computed } from "vue"
// 2.定义执行函数
const computedValue = computed(() = >{
// 计算逻辑
})
</script>
4.监听器
思想与Vue2基本一致,只是修改了写法为使用watch函数
<script setup>
// 1.导入watch函数
import { watch, ref } from "vue"
const value = ref(100)
// 2.调用watch监听变化
watch(value, // value应当是响应式数据
(newValue, oldValue) => {
// 数据变化操作逻辑
})
</script>
<script setup>
// 1.导入watch函数
import { watch, ref } from "vue"
const value1 = ref(100)
const value2 = ref(200)
// 2.调用watch监听变化
watch([value1, value2], // value1, value2应当是响应式数据
([newValue1, newValue2], [oldValue1, oldValue2]) => {
// 数据变化操作逻辑
})
</script>
<script setup>
// 1.导入watch函数
import { watch, ref } from "vue"
const value1 = ref(100)
// ...
// 2.调用watch监听变化
watch([value1, ...],
([newValue1, ...], [oldValue1, ...]) => {
// 数据变化操作逻辑
},{
immediate: false, // 进入页面立即执行
deep: false // 深度监听,默认浅层监听(监听复杂类型)
})
</script>
<script setup>
// 1.导入watch函数
import { watch, ref } from "vue"
const data = ref({column: 'value'})
// 2.调用watch监听变化
watch(() => data.value.column,(newValue, oldValue) => { // 指定监听column数据
// 数据变化操作逻辑
})
</script>
5.模板引用
通过ref标识获取真实的dom对象或组件实例对象
<script setup>
import { ref } from 'vue'
const myRef = ref(null) // 通过相同名称进行绑定,需要在挂载阶段之后才能获取到并使用
</script>
<template>
<myCom ref="myRef"></myCom>
</template>
6.defineExpose
默认情况下setup中组件内部的属性与方法是不开放给父组件访问的
可以通过 defineExpose 编译宏指定哪些属性与方法允许访问
<script setup>
import { ref } from 'vue'
const msg = ref('msg')
defineExpose({
msg
})
</script>
二、生命周期
选项式API | 组合式API |
---|---|
beforeCreate/created | setup |
beforeMount | onBeforeMount |
mounted | onMounted |
beforeUpdate | onBeforeUpdate |
updated | onUpdated |
beforeUnmount | onBeforeUnmount |
unmounted | onUnmounted |
注:Vue3没有destroy相关生命周期函数
<script setup>
// beforeCreate 与 created 相关代码直接写在setup执行
// 其他生命周期,以onMounted为例
import { onMounted } from 'vue'
onMounted(() => {
// 逻辑代码,多次使用生命周期函数不会冲突,而是依次执行
})
</script>
三、组件通信
1.父子通信
①父传子
通过 defineProps 编译器宏接收子组件传递的数据
<script setup>
const props = defineProps({
message: String
})
</script>
<template>
{{ message }}
</template>
<script setup>
// 引入子组件
import sonCom from './son-com.vue'
</script>
<template>
<sonCom message="msg"/>
</template>
②子传父
通过 defineEmits 编译器宏生成emit方法
<script setup>
const emit = defineEmits(['get-msg'])
const sendMsg = () => {
emit('get-msg', 'msg')
}
</script>
<template>
<button @click="sendMsg">sendMsg</button>
</template>
<script setup>
import sonCom from './son-com.vue'
const getMessage = (msg) => {
console.log(msg)
}
</script>
<template>
<sonCom @get-message="getMessage"/>
</template>
2.跨层级组件通信
使用provide和inject(传递的可以是普通数据/响应式数据/函数)
顶层组件:provide('key', data)
底层组件:const message = inject('key')
四、Vue3.3新特性
1.defineOption
Vue3.3引入了defineOption宏,用于在setup中定义Options API的选项
defineOption宏可以定义任意选项(props,emits,expose,slots除外)
<script setup>
defineOptions({
name: 'MyCom',
// 更多自定义属性
})
</script>
2.defineModel
用于配合v-model,快速实现自定义组件双向数据绑定
使用defineModel: defineModel是试验阶段特性,使用需要在vite.config.js中开启
开启defineModel
export default defineConfig({
plugins:[
vue({
script: {
defineModel: true
}
})],
})
示例:使用defineModel
<script setup>
import MyInput from 'my-input.vue'
import { ref } from 'vue'
const txt = ref("123456")
</script>
<template>
<MyInput v-model="txt"></MyInput>
{{ txt }}
</template>
<script setup>
import { defineModel } from 'vue'
const modelValue = defineModel()
</script>
<template>
<input type="text" :value="modelValue" @input="e => modelValue = e.target.value">
</template>
<script setup>
import MyInput from 'my-input.vue'
import { ref } from 'vue'
const txt = ref("123456")
</script>
<template>
<MyInput :modelValue="txt" @update:modelValue="txt=$event"></MyInput>
{{ txt }}
</template>
<script setup>
import { defineProps, defineEmits } from "vue";
defineProps({
modelValue: String
})
const emit = defineEmits(['update:modelValue'])
</script>
<template>
<input type="text" :value="modelValue" @input="e => emit('update:modelValue', e.target.value)">
</template>
第三部分 Pinia
Pinia是Vue最新的状态管理工具,是Vuex的替代品,详见官方网站:Pinia
一、简介
- 提供了更加简单的API
- 提供符合组合式风格的API
- 去掉modules概念,没一个store都是一个独立的模块
- 配合TypeScript更加友好,提供可靠的类型推断
二、安装
1.create-vue创建时添加
npm create vue@lastest # 直接创建时选择 => Add Pinia for state management (Yes)
2.在Vue3项目中引入
npm install pinia
import { createApp } from 'vue'
import { createPinia } from 'pinia'
import App from './App.vue'
const pinia = createPinia() // 创建pinia实例
const app = createApp(App)
app.use(pinia)
app.mount('#app')
三、使用
1.使用示例
export const useCounterStore = defineStore('counter', () => {
const count = ref(0) // ref() 即 state属性
const doubleCount = computed(() => count.value * 2) // computed() 即 getters
function increment() { // function() 即 action
count.value++
}
return { count, doubleCount, increment }
})
export const useCounterStore = defineStore('counter', {
state: () => ({ count: 0 }),
getters: {
double: (state) => state.count * 2,
},
actions: {
increment() {
this.count++
},
},
})
2.storeToRefs()
作用:使从store中提取属性时保持其响应性
<script setup>
import { useDataStore } from 'data'
import { storeToRefs } from 'pinia'
const dataStore = useDataStore()
const { data } = storeToRefs(dataStore) // 此时data响应式不会丢失
</script>
<script setup>
import {useDataStore} from 'data'
const dataStore = useDataStore()
const { data } = dataStore // 此时data响应式丢失
</script>