本文最后更新于:2024年4月25日 上午
快速开始
使用官方工具vite
快速初始化一个vue
应用
本文使用vite
在线工具演示(Vite在线体验 )
先清空文件夹,再执行命令初始化一个Vue3
项目
执行后按提示输入项目文件夹名
,包名
,之后选择vue
,继续选择vue
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 > npm create vite > success Install finished in 1. 06s > > ✔ Project name : … learnVue3 > ✔ Package name : … learnvue3 > ✔ Select a framework : › vue > ✔ Select a variant : › vue > > Scaffolding project in /home/projects/vitejs-vite-o33svt/learnVue3...> > Done . Now run :> > cd learnVue3 > npm install > npm run dev
再按提示命令执行,即创建并启动了一个vue
应用,为了学习vue3
,先将src
下的所有的文件/文件夹删除
生成vue3
src
目录新建一个App.vue
单文件组件
src/App.vue
1 2 3 4 <template > <h1 > 🎉 Hello Vue3!</h1 > </template >
src
目录新建一个main.js
文件
src/main.js
1 2 3 4 5 6 7 import { createApp } from 'vue' ;import App from './App.vue' ;const app = createApp (App ); app.mount ('#app' );
vite
热更新后即可看到App.vue
组件
单文件组件的创建与使用
将App.vue
中的h1
封装为组件来示例
src
新建components
文件夹,新建Hello.vue
单文件组件
src/components/Hello.vue
1 2 3 4 5 6 7 8 9 10 11 12 <template > <h1 > 🎉 Hello Vue3!</h1 > </template >
App.vue
导入组件
src/App.vue
1 2 3 4 5 6 7 8 9 10 <script setup > import Hello from './components/Hello.vue' ;</script > <template > <Hello /> </template >
template模板语法
template
可使用{{ data }}
来创建动态内容
src
目录下新建components
文件夹,新建Template.vue
,并在App.vue
注册使用
src/components/Template.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 33 <script setup > const name = 'Jon-a-than' ;let birthYear = 2002 ;setTimeout (() => birthYear = 2000 , 1000 );</script > <template > <h2 > template语法</h2 > <time > {{ new Date() }} </time > <p > My name is <span > {{ name }} </span > </p > <p > I am a <span > {{ new Date().getFullYear() - birthYear }} </span > -year-old boy </p > </template > <style scoped > p > span { color : #00f ; } </style >
在{{ }} 中只可使用单句Javascript
表达式 若变量未使用响应式API
,变量不会动态更新 变量会进行转义而不会插入innerHTML
setup函数
1 2 3 4 <script setup > </script >
setup内导入组件可直接使用 setup内没有全局this
Vue指令
动态属性
template
中的花括号语法无法作用于元素属性,v-bind
指令可以实现动态的元素属性
src/components/Directives/Vbind.vue
1 2 3 4 5 6 7 8 9 10 11 12 13 14 <script setup > const url = "https://qingshaner.com" ;const link = "https://staging-cn.vuejs.org/api/built-in-directives.html#v-bind" ;</script > <template > <h2 > 指令</h2 > <p > <a v-bind:href ="url" > Blog</a > <br /> <a :href ="link" > v-bind语法糖</a > </p > </template >
条件展示
使用v-show
命令可以让元素只在条件满足时显示元素
src/components/Directives/Vshow.vue
1 2 3 4 5 6 7 8 9 10 11 12 <script setup > let isShow = false setTimeout (() => isShow = true , 3000 )</script > <template > <h3 v-show ="!isShow" > 看见了吗</h3 > <h1 v-show ="isShow" > 👋我在这</h1 > </template >
使用v-if
,v-else-if
,v-else
指令也可按条件显示不同的元素
生命周期
🍈钩子函数
setup
创建实例前
onBeforeMount
挂载DOM前
onMounted
挂载DOM后
onBeforeUpdate
更新组件前
onUpdated
更新组件后
onBeforeUnmount
卸载销毁前
onUmounted
卸载销毁后
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 <template > <div class ="container" > </div > </template > <script > import {onBeforeMount, onMounted, onBeforeUpdate, onUpdated, onBeforeUnmount, onUmounted} from 'vue' export default { name : 'App' , setup () { onBeforeMount ( ){ } onMounted ( ){ } onBeforeUpdate ( ){ } onUpdated ( ){ } onBeforeUnmount ( ){ } onUmounted ( ){ } } } </script >
钩子函数无需 return
可直接执行
可注册多个相同钩子(按序执行)
响应式数据
自定义属性
向所用组件传值
1 2 3 4 5 6 7 <script setup > const props = defineProps ({})</script > <template > <p > {{ props.value }}</p > </template >
自定义事件
1 2 3 <script setup > </script >
reactive函数
🍒写入点击记数功能
此时数据变化,但DOM不渲染
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 <template > <div class ="container" > <h1 @click ="cnt" > {{ obj.count }}</h1 > </div > </template > <script > export default { name : 'App' , setup () { const obj = { count : 0 } const cnt = ( ) => obj.count ++ return { obj, cnt } } } </script >
🍒使用reactive函数
用 reactive
函数将 obj
对象构造为响应式数据即可动态响应
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 <template > <div class ="container" > <h1 @click ="cnt" > {{ obj.count }}</h1 > </div > </template > <script > import { reactive } from 'vue' export default { name : 'App' , setup () { const obj = reactive ({ count : 0 }) const cnt = ( ) => obj.count ++ return { obj, cnt } } } </script >
toRef函数
单独返回响应式对象的某一属性
修改 attribute.value
来响应式变化
🥒写入点击记数功能
使用解构得到的为静态值,无法实时更新
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 <template > <div class ="container" > <h1 @click ="cnt" > {{ count }}</h1 > </div > </template > <script > import { reactive } from 'vue' export default { name : 'App' , setup () { const obj = reactive ({ count : 0 , time : 2 }) const { count } = obj const cnt = ( ) => obj.count ++ return { count, cnt } } } </script >
🥒使用toRef函数
用 toRef
函数将属性构造为响应式对象即可响应
通过修改其 value
属性实现响应式数据
该值与原对象关联
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 <template > <div class ="container" > <h1 @click ="cnt" > {{ count }}</h1 > </div > </template > <script > import { reactive, toRef } from 'vue' export default { name : 'App' , setup () { const obj = reactive ({ count : 0 , time : 2 }) const count = toRef (obj, 'count' ) const cnt = ( ) => count.value ++ return { count, cnt } } } </script >
toRefs函数
🍓写入点击记数功能
使用解构得到的为静态值,无法实时更新
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 <template > <div class ="container" > <h1 @click ="cnt" > {{ count }}</h1 > <h2 > {{ time }}</h2 > </div > </template > <script > import { reactive } from 'vue' export default { name : 'App' , setup () { const obj = reactive ({ count : 0 , time : 2 }) const cnt = ( ) => obj.count ++ return { ...obj } } } </script >
🍓使用toRefs函数
用 toRefs
函数将属性集构造为响应式对象
新对象与原对象关联
通过修改其属性的 value
属性实现响应式数据
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 <template > <div class ="container" > <h1 @click ="cnt" > {{ count }}</h1 > <h2 > {{ time }}</h2 > </div > </template > <script > import { reactive, toRefs } from 'vue' export default { name : 'App' , setup () { const obj = reactive ({ count : 0 , time : 2 }) const obj2 = toRefs (obj) const cnt = ( ) => obj.count ++ return { ...obj2, cnt } } } </script >
ref函数
将简单数据类型定义为响应式数据
更改数据需更改 value
属性
🍊定义简单响应式数据
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 <template > <div class ="container" > <h1 > {{ msg }}</h1 > </div > </template > <script > export default { import { ref } from 'vue' name : 'App' , setup () { const msg = ref ('title' ) return { msg } } } </script >
computed函数
数据 根据响应式数据变化而变化时使用计算函数
计算函数返回值只读
🥦计算函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 <template > <div class ="container" > </div > </template > <script > export default { import { computed, ref } from 'vue' name : 'App' , setup () { const oldDate = ref (2020 ) const newDate = computed (() => { return oldDate.value + 1 }) return { oldDate, newDate } } } </script >
get()
set()
watch函数
🍎监听一个简单响应式数据
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 <template > <div class ="container" > </div > </template > <script > export default { import { ref, watch } name : 'App' , setup () { const foo = ref ('bar' ) whatch (foo, (oldDate, newDate ) => { console .log ('foo变化了' ) }) } } </script >
🍎监听一个响应式对象
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 <template > <div class ="container" > </div > </template > <script > export default { import { reactie, watch } name : 'App' , setup () { const foo = reactive ({ name : 'bar' , age : 19 }) whatch (foo, (oldDate, newDate ) => { console .log ('foo变化了' ) }) } } </script >
🍎监听多个响应式数据
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 <template > <div class ="container" > </div > </template > <script > export default { import { reactie, ref, watch } name : 'App' , setup () { const foo = reactive ({ name : 'bar' , age : 19 }) const far = ref (10 ) whatch ([foo, far], () => { console .log ('foo,far至少一个变化了' ) }) } } </script >
🍎监听一个响应式对象的某一属性
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 <template > <div class ="container" > </div > </template > <script > export default { import { reactie, watch } name : 'App' , setup () { const foo = reactive ({ name : 'bar' , age : 19 }) whatch (() => foo.name , () => { console .log ('foo.name变化了' ) }) } } </script >
🍎深度监听
1 2 3 watch (date, callback, { deep : true })
🍎默认执行
1 2 3 watch (date, callback, { immediate : true })
ref属性
🌳获取单个DOM
先定义并返回空的响应式数据
再将 ref
属性绑定到DOM上
1 2 3 4 5 6 7 8 9 10 11 12 13 14 <template > <div class ="container" > <h1 ref ="title" > title</h1 > </div > </template > <script > export default { name : 'app' setup () { const title = ref (null ) return { title } } } </script >
🌳获取v-for
遍历的DOM
定义并返回一个空数组
定义一个DOM插入函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 <template > <div class ="container" > <ul > <li v-for ="i in 4" :key ="i" :ref ="setDom" > 第{{ i }}个</li > </ul > </div > </template > <script > export default { name : 'App' , setup () { const domList = [] const setDom = (el ) => { domList.push (el) } return { setDom } } } </script >
父子通讯
🍁父=>子
用 :key="variable"
绑定给子组件
子元素用 props
接收数据
子元素 setup(props)
传递数据给组合API
App.vue
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 <template > <div class ="container" > <h1 > {{ level }}</h1 > <son :relationship ="level" /> // 绑定传递 </div > </template > <script > import { ref } from 'vue' import son from './son.vue' export default { name : 'App' , components : { son }, setup () { const level = ref ('father' ) return { level } } } </script >
son.vue
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 <template > <div class ="container" > <h1 > 子组件{{ relationship }}</h1 > </div > </template > <script > export default { name : 'son' , props : { relationship : { type : String , default : 'null' } }, setup (props) { console .log (props.relationship ) } } </script >
🍁父<=子
利用 { emit }
(触发自定义事件)向父组件传递数据
父组件函数接收数据
App.vue
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 <template > <div class ="container" > <h1 > 父组件</h1 > <son @msg ="receive" /> </div > </template > <script > import son from './son.vue' export default { name : 'App' , components : { son }, setup () { const receive = (res ) => console .log (res) return { receive } } } </script >
son.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 <template > <div class ="container" > <h1 @click ="pass" > 子组件</h1 > </div > </template > <script > export default { name : 'son' , setup (props, { emit }) { const pass = ( ) => emit ('msg' , 'sonDom' ) return { pass } } } </script >
🍁父<=>子 语法糖
依赖注入
provide
函数给后代提供数据与方法
inject
函数接受父代数据与方法
🍉向后代传值
1 2 import { provide } from 'vue' provide ('key' , value)
🍉接收值
单向数据流
1 const key = inject ('key' )
🍉数据通信
在父组件定义并传递一个数据修改方法
1 2 const changeValue = ( ) => key () provide ('changeKey' , changeValue)
后代接收方法来修改数据
1 const change = inject ('changeKey' )
setup 语法糖
🍍注册与变量
1 2 3 4 5 6 7 8 9 <template > <h1 > {{ title }}</h1 > <Son /> </template > <script setup > import Son from '@...' const title = '糖' </script >
🍍