vue3直白教程(梳理)

墨城發表於2023-02-24

1、setup script

用法:

<script setup lang="ts">
// 在這裡寫vue的邏輯
</script>

<template>
  <div>哈哈</div>
</template>

2、ref & reactive & 事件

說明:
1、ref:需要響應式的常量,賦值時需要xxx.value
2、reactive:需要響應式的物件或者陣列,可直接使用或賦值
3、事件:在setup script中,直接定義事件

用法:

<script setup lang="ts">
import { ref, reactive } from 'vue'

// 常量
const name = ref('小明')
// 物件、陣列
const user = reactive({
  name: '小紅',
  gender: '女'
})

const handleAdd = () => {
  arr.push({ name: '哈哈哈' })
}
</script>

<template>
  <button @click="switchName">
    我叫 {{name}},性別{{user.gender}}
  </button>
  <button @click="handleAdd">新增</button>
</template>

3、computed & watch & watchEffect

說明:
1、computed:計算函式
2、watch:監聽函式,可監聽常量和引用變數,可傳immediate和deep。可監聽物件也可只監聽物件的某個屬性
3、watchEffect:跟watch差不多,但是watchEffect不需要說明監聽誰,用到誰就監聽誰

用法:
<script setup lang="ts">
import { ref, reactive, computed,watch, watchEffect } from 'vue'

// 常量
const name = ref('小明')
// 物件、陣列
const user = reactive({
  name: '小紅',
  gender: '女'
})

// computed計算出userText
const userText = computed(() => {
  return `我叫${user.name},我是${user.gender}的`
})

// 監聽user物件
watch(user, (next) => {
  console.log('user被修改了', next)
}, {
  immediate: false, // 首次執行
  deep: true // 深度監聽物件
})

// 可監聽物件的某個屬性,這裡監聽user.gender
watch(() => user.gender, (next, pre) => {
  console.log('user.gender被修改了', next, pre)
})

// 不需要說明監聽誰
// 用到user.gender就監聽user.gender
watchEffect(() => {
  const gender = user.gender
  console.log('user.gender被修改了', gender)
})
</script>

<template>
  <div>{{ userText }}</div>
</template>

4、生命週期

vue2 - vue3

beforeCreate -> 沒了
created -> 沒了
beforeMount -> onBeforeMount
mounted -> onMounted
beforeUpdate -> onBeforeUpdate
updated -> onUpdated
beforeUnmount -> onBeforeUnmount
unmounted -> onUnmounted
activated -> onActivated
deactivated -> onDeactivated
errorCaptured -> onErrorCaptured

<script setup lang="ts">
import {onBeforeMount,onMounted,onUpdated,onBeforeUpdate,onBeforeUnmount, onUnmounted,onActivated,onDeactivated,onErrorCaptured} from 'vue'

onBeforeMount(() => {
  console.log('掛載前')
})
onMounted(() => {
  console.log('掛載')
})
onBeforeUpdate(() => {
  console.log('更新前')
})
onUpdated(() => {
  console.log('更新')
})
onBeforeUnmount(() => {
  console.log('銷燬前')
})
onUnmounted(() => {
  console.log('銷燬')
})
onActivated(() => {
  console.log('kee-alive啟用本元件')
})
onDeactivated(() => {
  console.log('kee-alive隱藏本元件')
})
onErrorCaptured(() => {
  console.log('錯誤捕獲')
})
</script>

5、defineProps & defineEmits

父元件:

<script setup lang="ts">
import { ref } from 'vue'
import Dialog from './Dialog.vue'

const msg = ref('我是msg')
const changeMsg = (val: string) => {
  msg.value = val
}
</script>

<template>
// 傳進子元件
<Dialog :msg="msg" @changeMsg="changeMsg" />
</template>
子元件:

<script setup lang="ts">
import { defineProps, defineEmits } from 'vue'

// 註冊父傳子的props
const { msg } = defineProps({
  msg: {
    type: String,
    required: true
  }
})

// 註冊父傳子的事件
const emits = defineEmits(['changeMsg'])
const handleClick = () => {
  // 修改父元件的值
  emits('changeMsg', '修改msg')
}

</script>

<template>
  <div @click="handleClick">{{ msg }}</div>
</template>

6、defineExpose

說明:這個API主要主要作用是:將子元件的東西暴露給父元件,好讓父元件可以使用

<!-- 子元件 -->
<script setup>
import { ref } from 'vue'

const msg = ref('hello vue3!')
function change() {
  msg.value = 'hi vue3!'
  console.log(msg.value)
}
// 屬性或方法必須暴露出去,父元件才能使用
defineExpose({ msg, change })
</script>
<!-- 父元件 -->
<script setup>
import ChildView from './ChildView.vue'
import { ref, onMounted } from 'vue'

const child = ref(null)
onMounted(() => {
  console.log(child.value.msg) // hello vue3!
  child.value.change() // hi vue3!
})
</script>

<template>
  <ChildView ref="child"></ChildView>
</template>

7、全域性API

說明:

1、vue3已經沒有filter這個全域性方法了
2、vue.component -> app.component
3、vue.directive -> app.directive
4、之前Vue.xxx現在都改成app.xxx

// 全域性自定義指令
app.directive('focus', {
  mounted(el) {
    el.focus()
  }
})

// 全域性自定義元件
import CustomComp from './components/CustomComp.vue'

app.component('CustomComp', CustomComp)

8、自定義指令

vue2:

Vue.directive('xxx', {
  // 指令繫結到指定節點,只執行一次
  bind() {},
  // 指定節點插入dom
  inserted() { },
  // 節點VNode更新時,可能剛更新,沒完全更新
  update() {},
  // VNode完全更新
  componentUpdated() {},
  // 指令從指定節點解綁,只執行一次
  unbind() {}
})
vue3:

app.directive('xxx', {
    // 在繫結元素的 attribute 或事件監聽器被應用之前呼叫, 在指令需要附加須要在普通的 v-on 事件監聽器前呼叫的事件監聽器時,這很有用
    created() {},
    // 當指令第一次繫結到元素並且在掛載父元件之前呼叫
    beforeMount() {},
    // 在繫結元素的父元件被掛載後呼叫
    mounted() {},
    // 在更新包含元件的 VNode 之前呼叫
    beforeUpdate() {},
    // 在包含元件的 VNode 及其子元件的 VNode 更新後呼叫
    updated() {},
    // 在解除安裝繫結元素的父元件之前呼叫
    beforeUnmount() {},
    // 當指令與元素解除繫結且父元件已解除安裝時, 只呼叫一次
    unmounted() {},
});

9、defineAysncCompoment & Suspense

說明:這個API用來載入非同步元件,就是用不到他就不載入,用到了才會載入
注:defineAysncCompoment需配合vue3的內建全域性元件Suspense使用,需要用Suspense包住非同步元件

const AsyncPopup = defineAsyncComponent({ 
  loader: () => import("./LoginPopup.vue"),
   // 載入非同步元件時要使用的元件
  loadingComponent: LoadingComponent,
   // 載入失敗時要使用的元件
  errorComponent: ErrorComponent, 
  // 在顯示 loadingComponent 之前的延遲 | 預設值:200(單位 ms)
  delay: 1000, 
  // 如果提供了 timeout ,並且載入元件的時間超過了設定值,將顯示錯誤元件
  // 預設值:Infinity(即永不超時,單位 ms)
  timeout: 3000 
})

// 使用時,可控制顯隱
<Suspense v-if="show" >
  <AsyncPopup />
</Suspense>

10、自定義hook——useUser

// useUser.ts
import { reactive, computed } from 'vue'

const useUser = () => {
  const user = reactive({
    name: '小紅',
    gender: '女'
  })

  const userText = computed(() => `我叫${user.name},我是${user.gender}的`)

  const switchGender = () => {
    user.gender = '男'
  }

  return {
    switchGender,
    userText,
  }
}

export default useUser
使用hook

<script setup lang="ts">
import useUser from './useUser'

const {userText,switchGender} = useUser()

</script>

<template>
  <div @click="switchGender">
    {{ userText }}
  </div>
</template>

11、useRouter & useRoute

說明:
1、useRouter:用來執行路由跳轉
2、useRoute:用來獲取路由引數

<script setup>
import { useRouter } from 'vue-router'

const router = useRouter()
function onClick() {
  // 跳轉
  router.push({
    path: '/about',
    query: {
      msg: 'hello vue3!'
    }
  })
}
</script>
<script setup>
import { useRoute } from 'vue-router'

const route = useRoute()
console.log(route.query.msg) 
// hello vue3!
</script>

12、Teleport

說明:Teleport可以將你的元件,掛載到任意一個節點之下,只要你指定一個選擇器,可以是id、class

// Dialog.vue
<template>
  <div>hello world</div>
</template>
<script setup lang="ts">
import Dialog from './Dialog.vue'

</script>

<template>
  // 將Dialog元件掛載到id為app的節點下
  <Teleport to="#app">
    <Dialog />
  </Teleport>
</template>

//自用梳理

相關文章