const app = new Vue({})
Vue.use()
Vue.mixin()
Vue.component()
Vue.directive()
const app = Vue.createApp({})
app.use()
app.mixin()
app.component()
app.directive()
- v-enter --- v-enter-from
- v-leave-to --- vl-eave-to
- v-leave --- v-leave-from
- v-enter-to --- v-enter-to
options api
对应 react class component
composition api
对应 react hooks
,setup 只会调用一次,hooks 可多次调用Proxy
代替 Object.defineProperty
options api
中的 data methods computed… 可以发访问setup
中的属性和方法setup
中不能访问options api
中的 data methods computed…render
函数)、两个参数:props:参数、context:上下文( attrs, slots, emit )setup(props, { attrs, slots, emit }) {
return {}
}
undefined
,通过 getCurrentInstance
获取实例import { getCurrentInstance } from 'vue'
const instance = getCurrentInstance()
import {
onBeforeMount,
onMounted,
onBeforeUpdate,
onUpdated,
onBeforeUnmount,
onUnmounted
} from 'vue'
reference
对象:创建一个包含响应式的引用对象,接受类型可以是基本类型,也可以是对象类型,除了 template 和reactive
,需通过.value
修改其值;Object.defineProperty
,对象依赖于proxy
;<template>
<p ref="elemRef">文字</p>
</template>
<script setup>
import { ref, onMounted } from 'vue'
const elemRef = ref(null)
onMounted(() => {
console.log(elemRef.value)
})
</script>
reactive
的值会失去响应式import { ref, reactive } from 'vue'
const nameRef = ref('张三')
const state = reactive({
name: nameRef
})
</script>
ref
类型并且两者保持引用关系;<script setup>
import { toRef, reactive } from 'vue'
const state = reactive({
age: 20,
name: '张三'
})
const ageRef = toRef(state, 'age')
</script>
ref
,两者保持引用关系<script setup>
import { toRefs, reactive } from 'vue'
function useFeatureX() {
const state = reactive({
x: 1,
y: 2
})
return toRefs(state)
}
const { x, y } = useFeatureX()
</script>
<HelloWorld @onSayHello="sayHello" />
export default {
emits: ['onSayHello'],
setup(props, { emit }) {
emit('onSayHello', '内容')
}
}
<button @click="one($event) two($event)">click</button>
.value
import { watch } from 'vue'
watch(
data, // 监听一个基本类型
// [data1,data2], // 监听多个 ref 基本属性
// objdata, // ref 引用类型
(newValue, oldValue) => {},
{ immediate: true } // 初始化监听
)
watch(
() => obj.xx, // 监听一个 reactive
// [ () => obj1.xx, () => obj2.xx ], // 监听多个 reactive
(newValue, oldValue) => {},
// { immediate: true , deep: true} // 引用类型设置深度监视
)
immediate:true
import { watchEffect } from 'vue'
watchEffect(() => {
// ...
})
<my-input v-model="val" />
const val = ref('hello')
props: {
modelValue: String
},
const handler = (e: Event) => {
const targetValue = (e.target as HTMLInputElement).value
context.emit('update:modelValue', targetValue) // 相当于自定义modal $emit
}
<myComponent v-bind:age.sync="age"></myComponent>
<template>
<p>{{ age }}</p>
<user-info v-model:ageRef="age"></user-info>
</template>
<script>
import { reactive, toRefs } from 'vue'
import UserInfo from './UserInfo.vue'
export default {
name: 'VModel',
components: { UserInfo },
setup() {
const state = reactive({
age: '20'
})
return toRefs(state)
}
}
</script>
<template>
<input :value="ageRef" @input="$emit('update:ageRef', $event.target.value)" />
</template>
<script>
export default {
name: 'UserInfo',
props: {
ageRef: String
}
}
</script>
vue2.x
components:{
'my-component':() => import('./xx.vue')
}
vue3.x
import { defineAsyncComponent } from 'vue'
components:{
AsyncComponent: defineAsyncComponent(() => import('./xx.vue'))
}
直接将元素插入到某个节点之中
<teleport to="body">
...
</teleport>
用于实现异步,组件内部有两个插槽。
<Suspense>
<template>
<AsyncComponent/>
</template>
<template #fallback>
<span>loading...</span>
</template>
</Suspense>
before:
// 1
defineProps({
modelValue: {
type: Number,
required: true,
default: 0
}
})
// 2
defineProps(['modelValue'])
now:
const modelValue = defineModel<number>({ default: 0 })
before:
const emits = defineEmits<
SE<{
clickCount(num: number): void
}>
>()
const emits = defineEmits<{
(e: 'clickCount', num: number): void
}>()
now:
const emits = defineEmits<{
clickCount: [num: number]
}>()
<div>
<span>hello</span>
<span>{{ name }}</span>
<span :class="blue">张三</span>
<span :id="zhangsan">张三</span>
<span :id="lisi" :class="black">{{ obj.name }}</span>
</div>
import { createElementVNode as _createElementVNode, toDisplayString as _toDisplayString, normalizeClass as _normalizeClass, openBlock as _openBlock, createElementBlock as _createElementBlock } from "vue"
export function render(_ctx, _cache, $props, $setup, $data, $options) {
return (_openBlock(), _createElementBlock("div", null, [
_createElementVNode("span", null, "hello"),
_createElementVNode("span", null, _toDisplayString(_ctx.name), 1 /* TEXT */),
_createElementVNode("span", {
class: _normalizeClass(_ctx.blue)
}, "张三", 2 /* CLASS */),
_createElementVNode("span", { id: _ctx.zhangsan }, "张三", 8 /* PROPS */, ["id"]),
_createElementVNode("span", {
id: _ctx.lisi,
class: _normalizeClass(_ctx.black)
}, _toDisplayString(_ctx.obj.name), 11 /* TEXT, CLASS, PROPS */, ["id"])
]))
}
以上TEXT 、PROPS 、CLASS
则为标记的不同类型,只会去比较有标记的区域,静态则不会进行对比。