Vue的几个compose模式

XiLaiTL大约 3 分钟

Vue的几个compose模式

单文件+Composition 的文件格式

/////代码层
<script setup>
//导入区
import {} form 'vue'
import {} form 'child.vue'
//导出变量区
const props = defineProps({msg: String})
//导出事件区
const emit = defineEmits(['response'])
emit('response', 'hello from child')

//响应常量区
const foo = ref(0)
const text = ref(``)
const str = ref(`zheyang`)
const titleClass = ref(`title`)

//属性-计算属性体系
const todos = ref([
  { id: id++, text: 'Learn HTML', done: true },
  { id: id++, text: 'Learn JavaScript', done: true },
  { id: id++, text: 'Learn Vue', done: false }
])
const filteredTodos = computed(() => {
  return hideCompleted.value
    ? todos.value.filter((t) => !t.done)
    : todos.value
})
//
const name = ref('Hello')
const title = computed(() =>`${name.value} - World`)

//变量侦听器体系
const count = ref(0)
watch(count, (newCount) => {
  console.log(`new count is: ${newCount}`)
})

//函数区
function afterClick(){

}
function xxX(){}
function increment() {
  count.value++
}
//生命周期区
onMounted(() => {
  p.value.textContent = 'mounted!'
})
</script>

/////模版页面层
<template>
	<h1 :class='titleClass'>Make me red</h1>
	<input v-model='text'>
	<button @click='increment'>{{ count }}</button>
	<p ref='p'>hello</p>
	<slot>Fallback content</slot>
</template>

/////CSS样式层
<style>
.title {
  color: red;
}
</style>

关键之处在于:三重映射

css->(id,class)->template->(属性的值,插槽内绑定的文本值)->script setup

我们主要要分清楚一个赋值语句的两个地方——等号左边和等号右边(对象内是冒号左边和冒号右边)

即:变量名=变量值

  • 在script setup内,定义了 变量名=变量值。

  • 在template内,在属性内,通过''(最好用单引号)引用了表达式。在插槽内,通过引用了表达式

    属性id、class引用到的变量名的具体的变量值,作为css的class选择器、id选择器名。

  • 在style内,定义选择器。

生命周期

说是生命周期,其实就是触发事件。

前端其实就是一个页面渲染工程,总共有如下事件——

加载数据->渲染页面->根据数据更新渲染页面->组件不再使用时更新渲染页面

等等。

在vue中,对应:

vue的数据对象的创建->dom树的初始化渲染->数据更新同时渲染dom->组件卸载

在对应的事件发生前后,有不同的数据被加载着。

生命周期钩子 | Vue.js (vuejs.org)open in new window

组合式 API:生命周期钩子 | Vue.js (vuejs.org)open in new window

设计模式

https://www.bilibili.com/video/BV1x54y1V7H6open in new window

https://talks.antfu.me/2021/vueconf-chinaopen in new window

接受ref作为函数参数

值类型使用ref,对象类型使用reative

接受Ref作为参数,返回一一个响应式的结果

function add(a: Ref<number>, b: Ref<number>) {
  return computed(() => a.value + b.value)
}

const a = ref(1)
const b = ref(2)

const c = add(a, b)
c.value // 3

同时接受传入值和Ref

function unref<T>(r: Ref<T> | T): T {
  return isRef(r) ? r.value : r
}

function add(
  a: Ref<number> | number,
  b: Ref<number> | number
) {
  return computed(() => unref(a) + unref(b))
}

const a = ref(1)

const c = add(a, 5)
c.value // 6

MaybeRef类型工具

type MaybeRef<T> = Ref<T> | T

让你的函数变得更灵活

重复使用已有Ref

const foo = ref(1)   // Ref<1>
const bar = ref(foo) // Ref<1>

foo === bar // true

Ref体系

ref->得到ref

unref->得到值

type MaybeRef<T> = Ref<T> | T

function useBala<T>(arg: MaybeRef<T>) {
  const reference = ref(arg) // 得到 ref
  const value = unref(arg)   // 得到值
}

Ref组合对象

import { ref, reactive } from 'vue'

function useMouse() {
  return { 
    x: ref(0),
    y: ref(0)
  }
}

const { x, y } = useMouse() //得到ref
const mouse = reactive(useMouse()) //得到自动解包的reactive

mouse.x === x.value // true

异步编程->先构建数据引用,再等待填充

副作用自动清除

Vue中原生的watch、computed API会在组件销毁时自动解除其内部的依赖监听。我们可以编写我们的函数时,遵循同样的模式。

import { onUnmounted } from 'vue'

export function useEventListener(target: EventTarget, name: string, fn: any) {
  target.addEventListener(name, fn)

  onUnmounted(() => {
    target.removeEventListener(name, fn) // <--
  })
}

inject/provide类型安全(略)

状态共享

上次编辑于:
贡献者: XiLaiTL