sleepyShen1989 / blog

MIT License
0 stars 0 forks source link

【复习】Vue3文档备忘 #15

Open sleepyShen1989 opened 1 year ago

sleepyShen1989 commented 1 year ago

Vue3文档备忘

工具链

性能优化

// vite.config.js
define: {
  __VUE_OPTIONS_API__ : false
}

v-model

另一种在组件内实现 v-model 的方式

<!-- CustomInput.vue -->
<script setup>
import { computed } from 'vue'

const props = defineProps(['modelValue'])
const emit = defineEmits(['update:modelValue'])

const value = computed({
  get() {
    return props.modelValue
  },
  set(value) {
    emit('update:modelValue', value)
  }
})
</script>

<template>
  <input v-model="value" />
</template>

与外部状态系统集成

将外部状态放在一个 shallowRef 中。一个浅层的 ref 中只有它的 .value 属性本身被访问时才是有响应性的,而不关心它内部的值。当外部状态改变时,替换此 ref 的 .value 才会触发更新

不可变数据

immer

// immer.js
import produce from 'immer'
import { shallowRef } from 'vue'

export function useImmer(baseState) {
  const state = shallowRef(baseState)
  const update = (updater) => {
    state.value = produce(state.value, updater)
  }

  return [state, update]
}

// App.vue
<script setup>
import { useImmer } from './immer.js'

const [items, updateItems] = useImmer([
  {
     title: "Learn Vue",
     done: true
  },
  {
     title: "Use Vue with Immer",
     done: false
  }
])

function toggleItem(index) {
  updateItems(items => {
    items[index].done = !items[index].done
  })
}
</script>

<template>
  <ul>
    <li v-for="({ title, done }, index) in items"
        :class="{ done }"
        @click="toggleItem(index)">
        {{ title }}
    </li>
  </ul>
</template>

<style>
.done {
  text-decoration: line-through;
}
</style>

状态机:

XState

// machine.js
import { createMachine, interpret } from 'xstate'
import { shallowRef } from 'vue'

export function useMachine(options) {
  const machine = createMachine(options)
  const state = shallowRef(machine.initialState)
  const service = interpret(machine)
    .onTransition((newState) => (state.value = newState))
    .start()
  const send = (event) => service.send(event)

  return [state, send]
}

// App.vue
<script setup>
import { useMachine } from './machine.js'

const [state, send] = useMachine({
  id: 'toggle',
  initial: 'inactive',
  states: {
    inactive: { on: { TOGGLE: 'active' } },
    active: { on: { TOGGLE: 'inactive' } }
  }
})
</script>

<template>
  <button @click="send('TOGGLE')">
    {{ state.matches("inactive") ? "Off" : "On" }}
  </button>
</template>

RxJS

RxJS @vueuse/rxjs

sleepyShen1989 commented 1 year ago

动画

Transition

自定义REF

// demo:对ref值变化进行防抖处理
import { customRef } from 'vue'

export default function (value, delay = 500) {
  let timer = null

  return customRef((track, trigger)=>{
    return {
      get() {
        track();
        return value
      },
      set(newValue) {
        clearTimeout(timer)
        timer = setTimeout(()=>{
          value = newValue;
          trigger()
        }, delay)
      }
    }
  })
}

watchEffect

清除副作用

在侦听函数中执行网络请求,在网络请求还没达到的时候,我们停止了侦听器或者侦听函数被再次执行,那么上一次的网络请求应该被取消

// watchEffect传入的函数的参数
const stopWatch = watchEffect((onInvalidate)=>{
  console.log('watchEffect执行')
  const timer = setTimeout(()=>{
    console.log('模拟网络请求')
  })
  onInvalidate(()=>{
    clearTimeout(timer)
  })
})

获取dom元素

// dom挂载完再执行
<div ref="title">123</div>

const title = ref(null)
watchEffect(()=>{
  console.log(title.value)
},{
  flush: "post"
})

provide/inject

通过provide提供可变数据时,记得使用readonly包裹提供的数据,防止其被子组件修改

import { provide, ref, readonly } from 'vue'
const name = ref('abc')
provide('name', readonly(name))