欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

vue3 文檔梳理快速入門

 更新時(shí)間:2021年09月15日 15:45:45   作者:一個(gè)渴望改變世界的攻城獅  
vue3之所以受廣大袁友的喜歡,優(yōu)點(diǎn)必不可少呀,比如:可以監(jiān)聽動(dòng)態(tài)新增的屬性;可以監(jiān)聽刪除的屬性 ;可以監(jiān)聽數(shù)組的索引和 length 屬性;下面文章小編就來向大家介紹vue3,感興趣的小伙伴不要錯(cuò)過奧

一、setup

組合式 API:

  • setup 選項(xiàng)應(yīng)該為一個(gè)函數(shù)
  • setup 選項(xiàng)函數(shù)接受兩個(gè)參數(shù): props context
  • setup 選項(xiàng)函數(shù)需要返回要暴露給組件的內(nèi)容
  • setup 需要使用 return 返回,才能給組件使用,包含數(shù)據(jù)和方法

1. setup 函數(shù)中的第一個(gè)參數(shù) —— props

setup 函數(shù)中的 props 是響應(yīng)式的,當(dāng)傳入新的 prop 時(shí),它將被更新

export default {
  props: {
    title: String
  },
  setup(props) {
    console.log(props.title)
  }
}

但是,因?yàn)?props 是響應(yīng)式的,你不能使用 ES6 解構(gòu),因?yàn)樗鼤?huì)消除 prop 的響應(yīng)性。
如果需要解構(gòu) prop,可以通過使用 setup 函數(shù)中的 toRefs 來安全地完成此操作。

import { toRefs } from 'vue'

setup(props) {
    const { title } = toRefs(props)

    console.log(title.value)
}

2.  contextcontext

setup 函數(shù)中的第二個(gè)參數(shù) —— contextcontext 上下文是一個(gè)普通的 JavaScript 對(duì)象,它暴露三個(gè)組件的 property

xport default {
  setup(props, context) {
    // Attribute (非響應(yīng)式對(duì)象)
    console.log(context.attrs)

    // 插槽 (非響應(yīng)式對(duì)象)
    console.log(context.slots)

    // 觸發(fā)事件 (方法)
    console.log(context.emit)
  }
}

context 是一個(gè)普通的 JavaScript 對(duì)象,也就是說,它不是響應(yīng)式的,這意味著你可以安全地對(duì) context 使用 ES6 解構(gòu)

export default {
  setup(props, { attrs, slots, emit }) {
    ...
  }
}

二、setup 函數(shù)的返回值

1.setup 函數(shù)的返回值 —— 對(duì)象

如果 setup 返回一個(gè)對(duì)象,則可以在組件的模板中像傳遞給 setup props property 一樣訪問該對(duì)象的 property:

<template>
  <!-- 模板中使用會(huì)被自動(dòng)解開,所以不需要 .value  -->
  <div>{{ readersNumber }} {{ book.title }}</div>
</template>

<script>
  import { ref, reactive } from 'vue'

  export default {
    setup() {
      const readersNumber = ref(0)
      const book = reactive({ title: 'Vue 3 Guide' })

      // expose to template
      return {
        readersNumber,
        book
      }
    }
  }
</script>

注意:從 setup 返回的 refs 在模板中訪問時(shí)是被自動(dòng)解開的,因此不應(yīng)在模板中使用 .value

三、響應(yīng)式系統(tǒng) API

1. reactive

reactive() 接收一個(gè)普通對(duì)象然后返回該普通對(duì)象的響應(yīng)式代理。等同于 2.x 的 Vue.observable()

const obj = reactive({ count: 0 })

響應(yīng)式轉(zhuǎn)換是“深層的”:會(huì)影響對(duì)象內(nèi)部所有嵌套的屬性。基于 ES2015 的 Proxy 實(shí)現(xiàn),返回的代理對(duì)象不等于原始對(duì)象。建議僅使用代理對(duì)象而避免依賴原始對(duì)象。

<template>
  <div id="app">{ state.count }</div>
</template>

<script>
import { reactive } from 'vue'
export default {
  setup() {
    // state 現(xiàn)在是一個(gè)響應(yīng)式的狀態(tài)
    const state = reactive({
      count: 0,
    })
  }
}
</script>

2. ref

接受一個(gè)參數(shù)值并返回一個(gè)響應(yīng)式且可改變的 ref 對(duì)象。ref 對(duì)象擁有一個(gè)指向內(nèi)部值的單一屬性 .value。

const count = ref(0)
console.log(count.value) // 0

count.value++
console.log(count.value) // 1

如果傳入 ref 的是一個(gè)對(duì)象,將調(diào)用 reactive 方法進(jìn)行深層響應(yīng)轉(zhuǎn)換。

模板中訪問:

當(dāng) ref 作為渲染上下文的屬性返回(即在setup() 返回的對(duì)象中)并在模板中使用時(shí),它會(huì)自動(dòng)解套,無需在模板內(nèi)額外書寫 .value:

<template>
  <div>{{ count }}</div>
</template>

<script>
  export default {
    setup() {
      return {
        count: ref(0),
      }
    },
  }
</script>

作為響應(yīng)式對(duì)象的屬性訪問:

當(dāng) ref 作為 reactive 對(duì)象的 property 被訪問或修改時(shí),也將自動(dòng)解套 value 值,其行為類似普通屬性:

const count = ref(0)
const state = reactive({
  count,
})

console.log(state.count) // 0

state.count = 1
console.log(count.value) // 1

注意:如果將一個(gè)新的 ref 分配給現(xiàn)有的 ref, 將替換舊的 ref

const otherCount = ref(2)

state.count = otherCount
console.log(state.count) // 2
console.log(count.value) // 1

注意:當(dāng)嵌套在 reactive Object 中時(shí),ref 才會(huì)解套。從 Array 或者 Map 等原生集合類中訪問 ref 時(shí),不會(huì)自動(dòng)解套:

const arr = reactive([ref(0)])
// 這里需要 .value
console.log(arr[0].value)

const map = reactive(new Map([['foo', ref(0)]]))
// 這里需要 .value
console.log(map.get('foo').value)

類型定義:

interface Ref<T> {
  value: T
}

function ref<T>(value: T): Ref<T>

有時(shí)我們可能需要為 ref 做一個(gè)較為復(fù)雜的類型標(biāo)注。我們可以通過在調(diào)用 ref 時(shí)傳遞泛型參數(shù)來覆蓋默認(rèn)推導(dǎo):

const foo = ref<string | number>('foo') // foo 的類型: Ref<string | number>

foo.value = 123 // 能夠通過!

3. computed

使用響應(yīng)式 computed API 有兩種方式:

(1)傳入一個(gè) getter 函數(shù),返回一個(gè)默認(rèn)不可手動(dòng)修改的 ref 對(duì)象。

const count = ref(1)
const plusOne = computed(() => count.value + 1)

console.log(plusOne.value) // 2

plusOne.value++ // 錯(cuò)誤!

(2)傳入一個(gè)擁有 get set 函數(shù)的對(duì)象,創(chuàng)建一個(gè)可手動(dòng)修改的計(jì)算狀態(tài)。

const count = ref(1)
const plusOne = computed({
  get: () => count.value + 1,
  set: (val) => {
    count.value = val - 1
  },
})

plusOne.value = 1
console.log(count.value) // 0

類型定義:

// 只讀的
function computed<T>(getter: () => T): Readonly<Ref<Readonly<T>>>

// 可更改的
function computed<T>(options: {
  get: () => T
  set: (value: T) => void
}): Ref<T>

4. readonly

傳入一個(gè)對(duì)象(響應(yīng)式或普通)或 ref,返回一個(gè)原始對(duì)象的只讀代理。一個(gè)只讀的代理是“深層的”,對(duì)象內(nèi)部任何嵌套的屬性也都是只讀的。

const original = reactive({ count: 0 })

const copy = readonly(original)

watchEffect(() => {
  // 依賴追蹤
  console.log(copy.count)
})

// original 上的修改會(huì)觸發(fā) copy 上的偵聽
original.count++

// 無法修改 copy 并會(huì)被警告
copy.count++ // warning!

5. watchEffect

立即執(zhí)行傳入的一個(gè)函數(shù),并響應(yīng)式追蹤其依賴,并在其依賴變更時(shí)重新運(yùn)行該函數(shù)。

const count = ref(0)

watchEffect(() => console.log(count.value))
// -> 打印出 0

setTimeout(() => {
  count.value++
  // -> 打印出 1
}, 100)

5.1 停止偵聽

當(dāng) watchEffect 在組件的 setup() 函數(shù)或生命周期鉤子被調(diào)用時(shí), 偵聽器會(huì)被鏈接到該組件的生命周期,并在組件卸載時(shí)自動(dòng)停止。

在一些情況下,也可以顯式調(diào)用返回值以停止偵聽:

const stop = watchEffect(() => {
  /* ... */
})

// 之后
stop()

5.2 清除副作用

有時(shí)副作用函數(shù)會(huì)執(zhí)行一些異步的副作用, 這些響應(yīng)需要在其失效時(shí)清除(即完成之前狀態(tài)已改變了)。所以偵聽副作用傳入的函數(shù)可以接收一個(gè) onInvalidate 函數(shù)作入?yún)? 用來注冊(cè)清理失效時(shí)的回調(diào)。當(dāng)以下情況發(fā)生時(shí),這個(gè)失效回調(diào)會(huì)被觸發(fā):

  • 副作用即將重新執(zhí)行時(shí)
  • 偵聽器被停止 (如果在 setup() 或 生命周期鉤子函數(shù)中使用了 watchEffect, 則在卸載組件時(shí))
watchEffect((onInvalidate) => {
  const token = performAsyncOperation(id.value)
  onInvalidate(() => {
    // id 改變時(shí) 或 停止偵聽時(shí)
    // 取消之前的異步操作
    token.cancel()
  })
})

我們之所以是通過傳入一個(gè)函數(shù)去注冊(cè)失效回調(diào),而不是從回調(diào)返回它(如 React useEffect 中的方式),是因?yàn)榉祷刂祵?duì)于異步錯(cuò)誤處理很重要。

在執(zhí)行數(shù)據(jù)請(qǐng)求時(shí),副作用函數(shù)往往是一個(gè)異步函數(shù):

const data = ref(null)
watchEffect(async () => {
  data.value = await fetchData(props.id)
})

我們知道異步函數(shù)都會(huì)隱式地返回一個(gè) Promise,但是清理函數(shù)必須要在 Promise resolve 之前被注冊(cè)。另外,Vue 依賴這個(gè)返回的 Promise 來自動(dòng)處理 Promise 鏈上的潛在錯(cuò)誤。

5.3 副作用刷新時(shí)機(jī)

Vue 的響應(yīng)式系統(tǒng)會(huì)緩存副作用函數(shù),并異步地刷新它們,這樣可以避免同一個(gè) tick 中多個(gè)狀態(tài)改變導(dǎo)致的不必要的重復(fù)調(diào)用。在核心的具體實(shí)現(xiàn)中, 組件的更新函數(shù)也是一個(gè)被偵聽的副作用。當(dāng)一個(gè)用戶定義的副作用函數(shù)進(jìn)入隊(duì)列時(shí), 會(huì)在所有的組件更新后執(zhí)行:

<template>
  <div>{{ count }}</div>
</template>

<script>
  export default {
    setup() {
      const count = ref(0)

      watchEffect(() => {
        console.log(count.value)
      })

      return {
        count,
      }
    },
  }
</script>

在這個(gè)例子中:

count 會(huì)在初始運(yùn)行時(shí)同步打印出來
更改 count 時(shí),將在組件更新后執(zhí)行副作用。

請(qǐng)注意:初始化運(yùn)行是在組件 mounted 之前執(zhí)行的。因此,如果你希望在編寫副作用函數(shù)時(shí)訪問 DOM(或模板 ref),請(qǐng)?jiān)?onMounted 鉤子中進(jìn)行:

onMounted(() => {
  watchEffect(() => {
    // 在這里可以訪問到 DOM 或者 template refs
  })
})

如果副作用需要同步或在組件更新之前重新運(yùn)行,我們可以傳遞一個(gè)擁有 flush 屬性的對(duì)象作為選項(xiàng)(默認(rèn)為 'post'):

// 同步運(yùn)行
watchEffect(
  () => {
    /* ... */
  },
  {
    flush: 'sync',
  }
)

// 組件更新前執(zhí)行
watchEffect(
  () => {
    /* ... */
  },
  {
    flush: 'pre',
  }
)

5.4  偵聽器調(diào)試

onTrack onTrigger 選項(xiàng)可用于調(diào)試一個(gè)偵聽器的行為。

  • 當(dāng)一個(gè) reactive 對(duì)象屬性或一個(gè) ref 作為依賴被追蹤時(shí),將調(diào)用 onTrack
  • 依賴項(xiàng)變更導(dǎo)致副作用被觸發(fā)時(shí),將調(diào)用 onTrigger

這兩個(gè)回調(diào)都將接收到一個(gè)包含有關(guān)所依賴項(xiàng)信息的調(diào)試器事件。建議在以下回調(diào)中編寫 debugger 語句來檢查依賴關(guān)系:

watchEffect(
  () => {
    /* 副作用的內(nèi)容 */
  },
  {
    onTrigger(e) {
      debugger
    },
  }
)

onTrack onTrigger 僅在開發(fā)模式下生效。

類型定義:

function watchEffect(
  effect: (onInvalidate: InvalidateCbRegistrator) => void,
  options?: WatchEffectOptions
): StopHandle

interface WatchEffectOptions {
  flush?: 'pre' | 'post' | 'sync'
  onTrack?: (event: DebuggerEvent) => void
  onTrigger?: (event: DebuggerEvent) => void
}

interface DebuggerEvent {
  effect: ReactiveEffect
  target: any
  type: OperationTypes
  key: string | symbol | undefined
}

type InvalidateCbRegistrator = (invalidate: () => void) => void

type StopHandle = () => void

6. watch

watch API 完全等效于 2.x this.$watch (以及 watch 中相應(yīng)的選項(xiàng))。watch 需要偵聽特定的數(shù)據(jù)源,并在回調(diào)函數(shù)中執(zhí)行副作用。默認(rèn)情況是懶執(zhí)行的,也就是說僅在偵聽的源變更時(shí)才執(zhí)行回調(diào)。

  • 對(duì)比 watchEffect,watch 允許我們:
  1. 懶執(zhí)行副作用;
  2. 更明確哪些狀態(tài)的改變會(huì)觸發(fā)偵聽器重新運(yùn)行副作用;
  3. 訪問偵聽狀態(tài)變化前后的值。
  • 偵聽單個(gè)數(shù)據(jù)源
  1. 偵聽器的數(shù)據(jù)源可以是一個(gè)擁有返回值的 getter 函數(shù),也可以是 ref:
// 偵聽一個(gè) getter
const state = reactive({ count: 0 })
watch(
  () => state.count,
  (count, prevCount) => {
    /* ... */
  }
)

// 直接偵聽一個(gè) ref
const count = ref(0)
watch(count, (count, prevCount) => {
  /* ... */
})

6.1 偵聽多個(gè)數(shù)據(jù)源

watcher 也可以使用數(shù)組來同時(shí)偵聽多個(gè)源:

watch([fooRef, barRef], ([foo, bar], [prevFoo, prevBar]) => {
  /* ... */
})

6.2 與 watchEffect 共享的行為

watch watchEffect 在停止偵聽, 清除副作用 (相應(yīng)地 onInvalidate 會(huì)作為回調(diào)的第三個(gè)參數(shù)傳入),副作用刷新時(shí)機(jī) 和 偵聽器調(diào)試 等方面行為一致.

類型定義:

// 偵聽單數(shù)據(jù)源
function watch<T>(
  source: WatcherSource<T>,
  callback: (
    value: T,
    oldValue: T,
    onInvalidate: InvalidateCbRegistrator
  ) => void,
  options?: WatchOptions
): StopHandle

// 偵聽多數(shù)據(jù)源
function watch<T extends WatcherSource<unknown>[]>(
  sources: T
  callback: (
    values: MapSources<T>,
    oldValues: MapSources<T>,
    onInvalidate: InvalidateCbRegistrator
  ) => void,
  options? : WatchOptions
): StopHandle

type WatcherSource<T> = Ref<T> | (() => T)

type MapSources<T> = {
  [K in keyof T]: T[K] extends WatcherSource<infer V> ? V : never
}

// 共有的屬性 請(qǐng)查看 `watchEffect` 的類型定義
interface WatchOptions extends WatchEffectOptions {
  immediate?: boolean // default: false
  deep?: boolean
}

到此這篇關(guān)于vue3 文檔梳理快速入門的文章就介紹到這了,更多相關(guān)vue3 文檔梳理內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評(píng)論