重读vue3
基础
风格指南
结构风格
vue推荐: 先声明,后使用
<script setup></script>
<template></template>
<style scoped></style>
子组件命名
<!-- 在单文件组件中,推荐为子组件使用PascalCase的标签名,以此来和原生的 HTML 元素作区分 -->
<!-- ✅: 推荐风格:PascalCase,文件名使用kebab-case风格button-counter.vue -->
<ButtonCounter />
<!-- ❎: 不推荐风格:kebab-case -->
<button-counter />
方法命名
<!-- ✅: 推荐风格:kebab-case -->
<MyComponent @some-event="callback" />
cdn方式使用
<!-- 模块化引入cdn js -->
<script type="module">
import { createApp } from 'https://unpkg.com/vue@3/dist/vue.esm-browser.js'
</script>
<!-- 导入映射表 -->
<script type="importmap">
{
"imports": {
"vue": "https://unpkg.com/vue@3/dist/vue.esm-browser.js"
}
}
</script>
<script type="module">
import { createApp } from 'vue'
</script>
全局处理
// 全局错误处理
app.config.errorHandler = (err) => {}
// 全局组件注册(未使用也无法tree-shaking,会打包到js文件,不是大量使用不推荐)
app.component('Component', Component)
多实例挂载
const app1 = createApp(...)
app1.mount('#app1')
const app2 = createApp(...)
app2.mount('#app2')
自定义全局暴露
vue内部沙盒化,只会暴露常用Math和Date等全局对象
// 此时就可以在spa内部使用window变量
app.config.globalProperties.window = window
动态参数
值为null意为显式移除该绑定
<a :[attributeName]="url" @[eventName]="fn">...</a>
响应语法糖
实验性质:不要混用也不要在生产环境使用💩
let count = $ref(0) // 不用.value
$event变量
<!-- 使用特殊的 $event 变量 -->
<button @click="warn('Form cannot be submitted yet.', $event)">
Submit
</button>
<!-- 使用内联箭头函数 -->
<button @click="(event) => warn('Form cannot be submitted yet.', event)">
Submit
</button>
checkbox自定义真假值
<input
type="checkbox"
v-model="toggle"
true-value="yes"
false-value="no"
/>
动态组件
<component :is="tabs[i]"></component>
进阶
watch vs watchEffect
import { watch, watchEffect } from 'vue'
// 指定追踪依赖变化
watch(key, async (newVal) => {
newVal && (user.value = await (fetch(`https://jsonplaceholder.typicode.com/todos/${key.value}`).then(res => res.json())))
})
// watchEffect会自动追踪依赖属性变化
watchEffect(async () => {
key.value && (user.value = await (fetch(`https://jsonplaceholder.typicode.com/todos/${key.value}`).then(res => res.json())))
})
插槽
<!-- 具名&匿名插槽 -->
<Component>
<template #name>具名插槽</template>
<span v-slot="{message}">默认插槽 {{ message }}</span>
</Component>
<slot name="name"></slot>
<slot></slot>
<!-- 插槽解构,混用请使用显示的默认插槽#default -->
<Component v-slot="{message}" />
<Component>
<template #header="{message}">
{{ message }}
</template>
</Component>
<slot message="插槽解构"></slot>
依赖注入
import { provide, readonly } from 'vue'
provide(k, readonly('v')) // 使用readonly可避免被修改
import { inject } from 'vue'
const v = inject(k)
异步组件
import { defineAsyncComponent } from 'vue'
const AsyncComp = defineAsyncComponent(() =>
import('./components/MyComponent.vue')
)
编译器宏
编译器宏在setup中不需要导入
- defineExpose
- defineEmits
- defineProps
- defineModel
watchEffect
watchEffect(async () => {
const response = await fetch(
`https://jsonplaceholder.typicode.com/todos/${todoId.value}`
)
data.value = await response.json()
})
defineModel
<!-- 父组件 -->
<script setup>
import { ref } from 'vue'
import Child from './Child.vue'
// 当子组件数据变化,父组件title会自动更新
const title = ref('')
</script>
<template>
<MyComponent v-model:title="title" />
{{ title }}
</template>
<!-- 子组件 -->
<script setup>
const title = defineModel('title')
</script>
<template>
<input v-model="title" />
</template>
defineCustomElement与shadow dom(原生)
const CustomElement = defineCustomElement({
props: {
msg: String
},
template: `<div>{{ msg }}</div>`
})
customElements.define('mine-element', CustomElement)
// 此时html就可使用<mine-element msg="影子节点"></mine-element>
指令hook
const myDirective = {
// 在绑定元素的 attribute前或事件监听器应用前调用
created(el, binding, vnode, prevVnode) {},
// 在元素被插入到 DOM 前调用
beforeMount(el, binding, vnode, prevVnode) {},
// 在绑定元素的父组件及他自己的所有子节点都挂载完成后调用
mounted(el, binding, vnode, prevVnode) {},
// 绑定元素的父组件更新前调用
beforeUpdate(el, binding, vnode, prevVnode) {},
// 在绑定元素的父组件及他自己的所有子节点都更新后调用
updated(el, binding, vnode, prevVnode) {},
// 绑定元素的父组件卸载前调用
beforeUnmount(el, binding, vnode, prevVnode) {},
// 绑定元素的父组件卸载后调用
unmounted(el, binding, vnode, prevVnode) {}
}
内置组件
Transition的6种状态
<Transition name="fade">...</Transition>
<style lang="scss" scoped>
.fade-enter-active,
.fade-leave-active {
transition: opacity 0.5s ease;
}
.fade-enter-from,
.fade-leave-to {
opacity: 0;
}
</style>
ts与组合式api
defineProps
<script lang="ts" setup>
// 响应式解构(实验性质): 需要开启plugins: [vue({reactivityTransform: true})]
const { name, age = 20 } = defineProps<{
name: string
age?: number
}>()
</script>
<template>
{{ name }} {{ age }}
</template>
本文作者:sineava
本文链接:https://www.cnblogs.com/sineava/p/18112769
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律