目录
[TOC]
安装及项目初始化
认识create-vue
create-vue是Vue官方新的脚手架工具,底层切换到了 vite (下一代前端工具链),为开发提供极速响应
使用create-vue创建项目
1 2 3 4
| # 前置条件 - 已安装16.0或更高版本的Node.js
# 执行如下命令,这一指令将会安装并执行 create-vue npm init vue@latest
|
熟悉项目和关键文件
语法
setup
1 2 3 4 5 6 7
| <script setup> const message = 'this is message' const logMessage = () => { console.log(message) } </script>
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| <script> export default { setup() { const message = 'this is message' const logMessage = () => { console.log(message) } return { message, logMessage } } } </script>
|
reactive和ref函数
reactive
接受对象类型数据的参数传入并返回一个响应式的对象接受对象类型数据的参数传入并返回一个响应式的对象
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| <script setup>
import {reactive} from "vue";
const person = reactive({ id: 0, username: 'XiaoFei', age: 18 })
const addAge = () => { person.age++ } </script>
<template> <div>person对象信息:{{ person }}</div> <button @click="addAge">点击添加年龄:{{ person.age }}</button> </template>
|
ref
接收简单类型或者对象类型的数据传入并返回一个响应式的对象
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
| <script setup>
import {ref} from "vue";
const count = ref(0)
const person = ref({ id: 0, username: 'XiaoFei', age: 18 })
const addCount = () => { count.value++ }
const addAge = () => { person.value.age++ }
</script>
<template> <div>普通类型值</div> <div>count:{{ count }}</div> <button @click="addCount">点击添加</button>
<div>传入对象</div> <div>person:{{ person }}</div> <button @click="addAge">点击添加</button> </template>
|
reactive对比ref
- 都是用来生成响应式数据
- 不同点
- reactive不能处理简单类型的数据
- ref参数类型支持更好,但是必须通过.value做访问修改
- ref函数内部的实现依赖于reactive函数
- 在实际工作中的推荐
computed
- 计算属性中不应该有“副作用”,比如异步请求 / 修改dom
- 避免直接修改计算属性中的值,计算属性应该只读的
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| <script setup>
import {ref, computed} from 'vue'
const list = ref([1, 2, 3, 4, 5, 6, 7, 8])
const computedList = computed(() => { return list.value.filter(item => item > 2) }) </script>
<template> <div> 原始数据 —— {{ list }} </div> <div> 计算属性数据 —— {{ computedList }} </div> </template>
|
watch
属性监听,当属性的值改变时,触发watch设置的函数
监听单个 / 多个数据
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
| <script setup>
import {ref, watch} from 'vue'
const count = ref(0) const age = ref(0)
const addCountAndAge = () => { count.value++ age.value++ }
watch(count, (newValue, oldValue) => { console.log("调用 watch 侦听单个数据变化") console.log('count', count.value, newValue, oldValue) })
watch([count, age], ([countNewValue, ageNewValue], [countOldValue, ageOldCount]) => { console.log("调用 watch 侦听多个数据变化") console.log('count', count.value, countNewValue, countOldValue) console.log('age', age.value, ageNewValue, ageOldCount) }) </script>
<template> <div> <button @click="addCountAndAge">Count:{{ count }}</button> <br/> <button @click="addCountAndAge">Age:{{ age }}</button> </div> </template>
|
immediate:watch的第三个参数,传入对象,immediate设置为true,会先执行一次watch的回调函数,不用等监听的属性值改变
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| <script setup>
import {ref, watch} from 'vue'
const count = ref(0)
const addCountAndAge = () => { count.value++ }
watch(count,() => { console.log("watch回调函数执行了") }, {immediate: true}) </script>
<template> <div> <button @click="addCountAndAge">Count:{{ count }}</button> </div> </template>
|
deep
通过watch监听的ref对象默认是浅层侦听的,直接修改嵌套的对象属性不会触发回调执行,需要开启deep,deep开启有性能损耗,尽量不使用deep
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
| <script setup>
import {ref, watch} from 'vue'
const person = ref({ age: 18, count: 1 })
const updateAge = () => { person.value.age++ }
const updateCount = () => { person.value.count++ }
watch( person, () => { console.log("person修改了", person.value) }, {deep: true} )
watch( () => { person.value.age }, () => { console.log("person修改了", person.value) }, {deep: true} ) </script>
<template> <div> <button @click="updateAge">修改age:{{ person.age }}</button> <br/> <button @click="updateCount">修改count:{{ person.count }}</button> </div> </template>
|
生命周期函数
选项式:vue2
组合式:vue3
使用import从vue中引入各个需要使用的生命周期函,同一个生命周期函数可以同时使用多次,该情况应用场景如果接收别人写的项目,不改动别人的代码,在他前面执行新的功能,可以同时使用相同的生命周期函数在他前/后执行即可
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| <script setup>
import {onBeforeMount, onMounted, onBeforeUpdate, onUpdated, onBeforeUnmount, onUnmounted} from 'vue'
onBeforeMount(() => { console.log("onBeforeMount1") })
onBeforeMount(() => { console.log("onBeforeMount2") })
onMounted(() => { console.log("onMounted") })
onBeforeUpdate(() => { console.log("onBeforeUpdate") })
onUpdated(() => { console.log("onUpdated") })
onBeforeUnmount(() => { console.log("onBeforeUnmount") })
onUnmounted(() => { console.log("onUnmounted") }) </script>
|
组件间通信
父传子
父组件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| <script setup>
import Son from './Son.vue' import {ref} from "vue";
const person = ref({ name: "XiaoFei", age: 18 }) </script>
<template> <div> <son :person="person"/> </div> </template>
|
子组件
1 2 3 4 5 6 7 8 9 10 11 12 13
| <template> <div>子组件接收的数据:{{ props }}</div> </template>
<script setup>
const props = defineProps({ person: Object })
console.log(props.person) </script>
|
子传父
父组件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| <script setup>
import Son from './Son.vue'
const getSonData = (sonData) => { console.log("子组件传递的数据:", sonData) } </script>
<template> <div> <son @get-son-data="getSonData"/> </div> </template>
|
子组件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| <script setup> import {ref} from "vue";
const person = ref({ name: "XiaoFei", age: 18 })
const emit = defineEmits(['get-son-data'])
const sentMsg = () => { emit('get-son-data', person) } </script> <template> <button @click="sentMsg">点击后,向父组件传递数据</button> </template>
|
跨组件
provide
和inject
实现跨组件间的任意通讯
如果传递的是方法,方法中有修改传递数据组件中的数据,接收方法的组件拿到该函数也会修改传递数据组件中的数据
传递数据组件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| <script setup> import Son from './Son.vue' import {provide, ref} from "vue";
const user = ref({ username: "123456", password: "223456" })
const testMethod = () => { console.log("传递测试方法") }
provide('user', user)
provide('testMethod', testMethod)
</script>
<template> <son ref="sonRef"/> </template>
|
接收数据组件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| <script setup> import {inject} from "vue";
const user = inject('user')
const testMethod = inject('testMethod')
testMethod() </script> <template> <div> {{ user }} <br/> <button @click="testMethod">使用跨组件接收方法</button> </div> </template>
|
模版引用
通过 ref 标识 获取真实的 dom 对象或者组件实例对象
获取标签对象dom
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| <script setup> import {onMounted, ref} from "vue";
const h1Ref = ref(null)
onMounted(() => { console.log(h1Ref.value) }) </script>
<template> <h1 ref="h1Ref">dom标签</h1> </template>
|
获取vue组件dom及使用testMessage获取组件属性
父组件使用ref获取到的vue组件的dom,默认情况下在 script setup
语法糖下组件内部的属性和方法是不开放给父组件访问的,可以通过defineExpose
编译宏指定哪些属性和方法容许访问
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| <script setup> import {onMounted, ref} from "vue"; import Son from './Son.vue'
const sonRef = ref(null)
onMounted(() => { console.log(sonRef.value) }) </script>
<template> <son ref="sonRef"/> </template>
|
1 2 3 4 5 6 7 8 9 10 11 12
| <script setup> import {ref} from "vue";
const name = ref("XiaoFei")
defineExpose({ name }) </script> <template></template>
|
20231105-Vue3快速上手
项目创建