前端前端vue重读vue3
omi基础
风格指南
结构风格
vue推荐: 先声明,后使用
<script setup></script> <template></template> <style scoped></style>
   | 
 
子组件命名
  <ButtonCounter />
  <button-counter />
 
  | 
 
方法命名
 <MyComponent @some-event="callback" />
 
  | 
 
cdn方式使用
 <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) => {}
  app.component('Component', Component)
 
  | 
 
多实例挂载
const app1 = createApp(...) app1.mount('#app1')
  const app2 = createApp(...) app2.mount('#app2')
   | 
 
自定义全局暴露
vue内部沙盒化,只会暴露常用Math和Date等全局对象
 app.config.globalProperties.window = window
 
  | 
 
动态参数
值为null意为显式移除该绑定
<a :[attributeName]="url" @[eventName]="fn">...</a>
   | 
 
响应语法糖
实验性质:不要混用也不要在生产环境使用💩
$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()))) }, {   immediate: bool,    once: bool,    deep: bool  })
 
  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>
 
  <Component v-slot="{message}" /> <Component>   <template #header="{message}">     {{ message }}   </template> </Component> <slot message="插槽解构"></slot>
 
  | 
 
依赖注入
import { provide, readonly } from 'vue' provide(k, readonly('v')) 
  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'
 
  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)
 
  | 
 
组件异步加载
defineAsyncComponent(() => import('./components/AsyncComp.vue')) 
  | 
 
指令hook
const myDirective = {      created(el, binding, vnode, prevVnode) {},      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>
  const { name, age = 20 } = defineProps<{   name: string   age?: number }>() </script>
  <template>   {{ name }} {{ age }} </template>
   |