vue3
需要会vue2,该文档笔记基于黑马的课,进阶快速入门vue3
vue3 官方文档:https://v3.cn.vuejs.org/
main.js改变
1import { createApp } from 'vue' 2import App from './App.vue' 3 4const app = createApp(App) 5app.mount('#app') /* 挂载app到id为app的元素上 */ 6
不需要new Vue(),直接createApp(App)
App.vue改变
- script在前了,template在后,最后style
- script中加入set up可以在script中直接编写组合式API
- templat中允许多个元素,不再要求唯一根元素
- style中加上scoped在当前组件起作用
组合式API
之前一直是选项式API,现在可以使用组合式API
setup
组合式API:一系列函数,组合起来实现功能
setup是入口函数,在组件创建之前调用
setup写法:
1<script> 2export default { 3 setup() { 4 5 } 6 } 7</script> 8
该钩子执行时间比beforeCreate和created更早,setup中获取不到this
setup中提供的任何函数和变量,需要最后return{}才能使用.但多次return过于繁琐,于是有语法糖:
1<script setup> 2export default { 3 setup() { 4 const count = 0 5 function increment() { 6 count++ 7 } 8 } 9} 10</script> 11
在script标签加上setup属性,就可以直接调用count和increment
reactive和ref
reactive: 响应式对象
ref: 响应式变量
- 从vue包中引入reactive
1import { reactive, ref } from 'vue' 2
- 使用reactive
1const state = reactive(对象类型数据) 2
接受一个对象类型数据,返回一个响应式对象,对象中的属性,属性值都会变成响应式
响应式对象: 当对象中的属性值发生改变时,会自动更新到视图中
reactive处理的是对象类型数据,不能处理简单类型数据
- 导入并使用ref
1import { ref } from 'vue' 2const count = ref(0) 3
接受一个简单/对象类型数据,返回一个响应式变量,变量的值会变成响应式
ref处理的是简单类型数据、对象类型数据
ref底层对简单类型数据进行了包装为对象再调用reactive,所以可以直接使用ref处理简单类型数据
注:
- 脚本中访问数据需要通过.value来访问
- 模板中访问数据不需要.value
- 推荐统一使用ref处理数据
computed
步骤:
- 导入computed
1import { computed } from 'vue' 2
- 使用computed
1const doubleCount = computed(() => count.value * 2) 2
1const doubleCount = computed(() => { 2 get:() => count.value * 2 3 set:(val) => { 4 count.value = val / 2 5 } 6}) 7
watch
步骤:
- 导入watch
1import { watch } from 'vue' 2
- 使用watch
1watch(count, (newVal, oldVal) => { 2 console.log(newVal, oldVal) 3}) 4/*监听单个数据变化*/ 5
1watch( 2 [count1, count2] 3 ([newVal1, newVal2]),[(oldVal1, oldVal2)] => { 4 函数体 5 } 6) 7/*监听多个数据变化*/ 8
1/*额外配置对象写法*/ 2const count = ref(0) 3watch (count, () => { 4 console.log('count:', count.value) 5}, { 6 immediate: true, /* 组件创建时立即调用 */ 7 deep: true, /* 监听对象内部属性变化 */ 8}) 9
1/*精确侦听某个属性变化*/ 2const info = ref({ 3 name: '张三', 4 age: 18 5}) 6 7watch( 8 () => info.value.age, 9 () => console.log('age:', info.value.age) 10) 11
生命周期钩子
- setup: 组件创建之前调用
- onBeforeMount: 组件挂载之前调用
- onMounted: 组件挂载之后调用
- onBeforeUpdate: 组件更新之前调用
- onUpdated: 组件更新之后调用
- onBeforeUnmount: 组件卸载之前调用
- onUnmounted: 组件卸载之后调用
父子通信
父组件向子组件传递数据
语法:
1/* 父组件 */ 2<script setup> 3 import sonComVue from './sonCom.vue' 4</script> 5 6<template> 7 <!-- 1.绑定属性 message--> 8 <sonComVue message="hello"></sonComVue> 9</template> 10
加冒号是变量绑定传递
1/* 子组件 */ 2<script setup> 3 /* 通过defineProps编译器宏接受子组件传递的数据 */ 4 const props = defineProps({ 5 message: String 6 }) 7<script> 8 9<template> 10 {{message}} 11</template> 12
props传过来的数据可以直接使用
defineProps原理:编译阶段的一个标识,实际编译器解析时,会进行编译转换为props选项
子组件向父组件传递数据
- 父组件中给子组件标签通过@绑定事件
- 子组件内部通过emit方法触发事件
语法:
1/* 子组件 */ 2<script setup> 3 /* 通过defineEmits编译器宏定义子组件触发的事件 */ 4 const emit = defineEmits(['get-message']) 5 const sendMsg = () => { 6 emit('get-message', 'hello') 7 } 8</script> 9 10<template> 11 <button @click="sendMsg">点击触发change事件</button> 12</template> 13
要触发的事件要放到defineEmits中
1/* 父组件 */ 2<script setup> 3 import sonComVue from './sonCom.vue' 4 const handleGetMessage = (msg) => { 5 console.log(msg) 6 } 7</script> 8 9<template> 10 <!-- 1.绑定事件 get-message--> 11 <sonComVue @get-message="handleGetMessage"></sonComVue> 12</template> 13
模板引用
通过ref标识获取dom对象或组件实例对象
语法:
1/* 子组件 */ 2<script setup> 3 const count = 999 4 const sayHi = () => { 5 console.log('hello') 6 } 7</script> 8 9<template> 10 <div ref="divRef"> 11 测试组件 {{count}} 12 </div> 13</template> 14
1/* 父组件 */ 2<script setup> 3 import { onMounted, ref } from 'vue' 4 import sonComVue from './sonCom.vue' 5 {/* 调用ref函数生成ref对象,通过ref标识绑定,通过ref对象.value访问绑定元素 */} 6 const input = ref(null) 7 onMounted(() => { 8 console.log(input.value) 9 }) 10 11 const testRef = ref(null) 12 const getComponent = () => { 13 console.log(testRef.value) 14 } 15</script> 16 17<template> 18 <input ref="input" type="text"> 19 <sonComVue ref="testRef"></sonComVue> 20 <button @click="getComponent">获取组件</button> 21</template> 22
defineExpose
默认下语法糖下组件内部属性和方法不开放给父组件访问,如果需要给父组件访问,需要通过defineExpose定义
语法:
1/* 子组件 */ 2<script setup> 3 const count = 999 4 const sayHi = () => { 5 console.log('hello') 6 } 7 defineExpose({ 8 count, 9 sayHi 10 }) 11</script> 12 13<template> 14 <div ref="divRef"> 15 测试组件 {{count}} 16 </div> 17</template> 18
1/* 父组件 */ 2<script setup> 3 import { onMounted, ref } from 'vue' 4 import sonComVue from './sonCom.vue' 5 {/* 调用ref函数生成ref对象,通过ref标识绑定,通过ref对象.value访问绑定元素 */} 6 const input = ref(null) 7 onMounted(() => { 8 console.log(input.value) 9 }) 10 11 const testRef = ref(null) 12 const getComponent = () => { 13 console.log(testRef.value.count) 14 testRef.value.sayHi() 15 } 16</script> 17 18<template> 19 <input ref="input" type="text"> 20 <sonComVue ref="testRef"></sonComVue> 21 <button @click="getComponent">获取组件</button> 22</template> 23
provide和inject
顶层组件向任意底层组件传递数据和方法,实现跨层组件通信
语法:
1/* 顶层组件 */ 2 /* provide ('key', 顶层组件的数据)*/ 3<script setup> 4 import { provide } from 'vue' 5 provide('name', '张三') 6</script> 7 8<template> 9 <div> 10 <sonComVue></sonComVue> 11 </div> 12</template> 13
1/* 子组件 */ 2 /* inject ('key') */ 3<script setup> 4 import { inject } from 'vue' 5 const name = inject('name') 6</script> 7 8<template> 9 <div> 10 {{name}} 11 </div> 12</template> 13
vue3.3新特性
defineOptions
语法:
1defineOptions({ 2 name: 'sonComVue' 3}) 4
相当于替代组件的name属性
1export default { 2 name: 'sonComVue' 3} 4
defineModel
v-model语法糖相当于
1<child v-model="isVisiable"> 2 3<child :modelValue="isVisiable" update:modelValue="isVisible=$event" > 4
而defineModel
语法:
1defineModel({ 2 props: { 3 modelValue: { 4 type: String, 5 default: '' 6 } 7 }, 8 emits: ['update:modelValue'] 9}) 10
语法:
1defineModel({ 2 props: { 3 modelValue: String 4 }, 5 emits: ['update:modelValue'] 6}) 7
pinia
pinia是vue的最新状态管理工具,是vuex替代品
优势:
- API简单(去掉了mutation)
- 去掉modules概念,每个store都是独立模块
- 配合typescript更优化
- 提供组合式风格API,与vue3统一
actions可以直接修改state了,且actions既支持异步又能修改一步。相当于把vuex的mutation好action合二为一
如何使用见官方文档
Pinia 官方文档
定义store
1import { defineStore } from 'pinia' 2 3// `defineStore()` 的返回值的命名是自由的 4// 但最好含有 store 的名字,且以 `use` 开头,以 `Store` 结尾。 5// (比如 `useUserStore`,`useCartStore`,`useProductStore`) 6// 第一个参数是你的应用中 Store 的唯一 ID。 7export const useAlertsStore = defineStore('alerts', { 8 // 其他配置... 9}) 10
- 组合式写法中,getters用computed语法
1import { defineStore} from 'pinia' 2export const useAlertsStore = defineStore('alerts', { 3 doubleCount: computed(() => state.count * 2) 4 return { 5 doubleCount 6 } 7}) 8
storeToRefs
直接解构pinia的store的数据会丢失响应式,因此用storeToRefs解决问题
1import { defineStore} from 'pinia' 2import { storeToRefs } from 'pinia' 3export const useAlertsStore = defineStore('alerts', { 4 doubleCount: computed(() => state.count * 2) 5 return { 6 doubleCount 7 } 8}) 9
1const { doubleCount } = storeToRefs(useAlertsStore()) 2console.log(doubleCount.value) 3doubleCount.value = 10 4
在useStore()之前,store实例不会创建,因此storeToRefs()会报错
解构方法一般不要用,因为是调用而不需要响应修改
持久化
pinia默认是不持久化的,需要安装插件pinia-plugin-persistedstate
1/* main.js */ 2import { createPinia } from 'pinia' 3import piniaPluginPersistedstate from 'pinia-plugin-persistedstate' 4 5const pinia = createPinia() 6pinia.use(piniaPluginPersistedstate) 7
创建store时,将persist选项设置为true即可
选项式:
1import { defineStore } from 'pinia' 2 3export const useAlertsStore = defineStore('alerts', { 4 // 其他配置... 5 persist: true 6}) 7
组合式加第三个参数:
1import { defineStore} from 'pinia' 2import { storeToRefs } from 'pinia' 3export const useAlertsStore = defineStore('alerts', { 4 doubleCount: computed(() => state.count * 2) 5 return { 6 doubleCount 7 } 8}, { 9 persist: true 10}) 11
当然persist里面也可以配置更多参数,如:
1import { defineStore} from 'pinia' 2import { storeToRefs } from 'pinia' 3export const useAlertsStore = defineStore('alerts', { 4 doubleCount: computed(() => state.count * 2) 5 return { 6 doubleCount 7 } 8}, { 9 persist: { 10 enabled: true, // 默认为true 11 key: 'pinia-key', // 自定义key 12 strategies: [{ 13 storage: window.sessionStorage //切换localstorage为sessionStorage 14 }], 15 paths: ['count'] // 只持久化count属性 16 } 17}) 18
具体看官方文档
《vue2到vue3快速上手入门》 是转载文章,点击查看原文。
