// 1
interface Config {
name: string;
}
props: {
config: Object as PropType<Config>,
required: true
}
// 2 readonly
const PropType = {
msg: string,
age: {
type: Number,
required: true
}
} as const
export default defineComponent({
name: '',
props: PropType
})
// 需要加上 eslint 忽略
const image = require("./assets/logo.png") // eslint-disable-line
const numRef = ref(1)
setInterval(() => {
numRef.value += 1
})
// setup 只会执行一次, 此处 num 不会新增
const num = numRef.value
setup(){
// 注意,应该写在这
const num = numRef.value
return () => {
h('div', num)
}
}
const yourRef = ref({})
onMounted(() => {
yourRef.value.doValidate()
})
<JSONSchemaForm contextRef={yourRef} />
css in js :vue-jss
<script setup lang="ts">
import { defineEmits, defineProps, watchEffect } from 'vue'
const props = defineProps<{ msg: string }>()
const emit = defineEmits<{
(e: 'change', id: number): void
(e: 'update', value: string): void
}>()
watchEffect(() => console.log(props.msg))
</script>
// context.ts
export const uniqueKey = Symbol()
// 父组件
<script setup lang="ts">
import { provide, reactive } from 'vue'
const data = reactive({ data: { a: 1 } })
provide(uniqueKey, data)
</script>
// 子组件
<script setup lang="ts">
import { inject, watchEffect } from 'vue'
const data = inject(uniqueKey)
watchEffect(() => {
// 此时 data 是响应式的,可以监听到
console.log(data)
})
</script>
setup () {
const context: { a: number; } | undefined = {a: 1}
if(!context) {
throw Error('should not be undefined')
}
return () => (<div>1</div>)
}
// ctx 在生产环境里拿不到
const { ctx } = getCurrentInstance()
// 可以
const { proxy } = getCurrentInstance()
// 纯函数
function sum(a: number, b: number) {
return a + b
}
sum(1, 2)
// 接收 Ref 作为函数参数,返回响应式结果
function sum1(a: Ref<number>, b: Ref<number>) {
return computed(() => a.value + b.value)
}
const a = ref(1)
const b = ref(2)
const c = sum1(a, b)
c.value // 3
// 同时传入 ref 和 number 类型
function sum2(a: Ref<number> | number, b: Ref<number> | number) {
return computed(() => unref(a) + unref(b))
}
const a = ref(1)
const c = sum2(a, 5)
c.value // 6
// 例子
import { computed, unref, Ref } from 'vue'
// 类型
type MaybeRef<T> = Ref<T> | T
export function useTimeAgo(
time: MaybeRef<Date | number | string>,
) {
return computed(() => someFormating(unref(time)))
}
import { useTitle } from '@vueuse/core'
const title = useTitle()
title.value = 'Hello World'
// 网页的标题随 Ref 改变
// -----------------------------
import { ref, computed } from 'vue'
import { useTitle } from '@vueuse/core'
const name = ref('Hello')
const title = computed(() => {
return `${name.value} - World`
})
useTitle(title) // Hello - World
name.value = 'Hi' // Hi - World
const foo = ref(1) // Ref<1>
const bar = ref(foo) // Ref<1>
foo === bar // true
function useFoo(foo: Ref<string> | string) {
// 不需要额外操作
const bar = isRef(foo) ? foo : ref(foo)
// 与上面的代码等效
const bar = ref(foo)
/* ... */
}
这个技巧在编写不确定参数类型的函数时十分有用。
import { ref, reactive } from 'vue'
function useMouse() {
return {
x: ref(0),
y: ref(0)
}
}
const { x, y } = useMouse()
// reactive 包装
const mouse = reactive(useMouse())
mouse.x === x.value // true
可以直接使用 ES6 解构其中的 Ref 使用根据使用方式,当想要自动解包的功能时,可以使用 reactive 将其转换为对象
// context.ts
import { InjectionKey } from 'vue'
export interface UserInfo {
id: number
name: string
}
export const injectKeyUser: InjectionKey<UserInfo> = Symbol()
// parent.vue
import { provide } from 'vue'
import { injectKeyUser } from './context'
export default {
setup() {
provide(injectKeyUser, {
id: '7', // 类型错误
name: 'Anthony'
})
}
}
// child.vue
import { inject } from 'vue'
import { injectKeyUser } from './context'
export default {
setup() {
const user = inject(injectKeyUser)
// UserInfo | undefined
if (user)
console.log(user.name) // Anthony
}
}
// shared.ts
import { reactive } from 'vue'
export const state = reactive({
foo: 1,
bar: 'Hello'
})
// A.vue
import { state } from './shared.ts'
state.foo += 1
// B.vue
import { state } from './shared.ts'
console.log(state.foo) // 2
不兼容 SSR
export default defineComponent({
setup(props) {
const value = useVModel(props, 'value')
return { value }
}
})
<template>
<input v-model="value" />
</template>
// Vue2.x
Vue.prototype.$api = axios
Vue.prototype.$eventBus = eventBus
// Vue3.x
app.config.globalProperties.$api = axios
app.config.globalProperties.$eventBus = eventBus
// 使用
<script setup lang="ts">
import { ref, onMounted, getCurrentInstance } from "vue";
onMounted(() => {
const instance = <any>getCurrentInstance();
const { $api, $eventBus } = instance.appContext.config.globalProperties;
// do something
})
// main.ts
app.config.errorHandler = (err, vm, info) => {
console.log('[全局异常]', err, vm, info)
}
控制台输出直观 ref 方法:
这里还有另一种方式,就是在控制台的设置面板中开启 「Enable custom formatters」选项。
这时候你会发现,控制台输出的 ref的格式发生变化了: