一.Vue2升级Vue3.2写法
1.获取 this
<script setup>
import { getCurrentInstance } from 'vue'
const { proxy, appContext } = getCurrentInstance()
const global = appContext.config.globalProperties
</script>
2.全局注册属性,方法,使用
import { createApp } from 'vue'
import App from './App.vue'
const app = createApp(App)
app.config.globalProperties.name = '沐华'
<script setup>
import { getCurrentInstance } from 'vue'
const { appContext } = getCurrentInstance()
const global = appContext.config.globalProperties
console.log(global.name)
</script>
3.支持多个根节点
<template>
<div>1</div>
<div>2</div>
</template>
4.dom获取
<template>
<el-form ref="formRef"></el-form>
<child-component />
</template>
<script setup lang="ts">
import ChildComponent from './child.vue'
import { getCurrentInstance } from 'vue'
import { ElForm } from 'element-plus'
const formRef = ref(null)
console.log(formRef.value)
const { proxy } = getCurrentInstance()
proxy.$refs.formRef.validate((valid) => { ... })
const formRef = ref<InstanceType<typeof ChildComponent>>()
const formRef = ref<InstanceType<typeof ElForm>>()
formRef.value?.validate((valid) => { ... })
</script>
5.初始化
<script setup>
import { onMounted } from 'vue'
const getData = () => {
xxxApi.then(() => { ... })
}
onMounted(() => {
getData()
})
</script>
6.解除绑定
<script setup>
import { onBeforeUnmount, onDeactivated } from 'vue'
onBeforeUnmount(() => {
clearTimeout(timer)
window.removeAddEventListener('...')
})
onDeactivated(() => {
clearTimeout(timer)
window.removeAddEventListener('...')
})
</script>
7.响应式参数
<template>
<div>{{ count }}</div>
</template>
<script setup>
import { ref, reactive } from 'vue'
const count = ref(1)
const arr = ref([])
console.log(arr.value)
const data = reactive({
name: '沐华',
age: 18,
...
})
console.log(data.name)
</script>
8.toRef 和 toRefs
<script setup>
import { reactive, toRef, toRefs } from 'vue'
const data = reactive({
name: '沐华',
age: 18
})
const { name, age } = data
const name = toRef(data, 'name')
const { name, age } = toRefs(data)
name.value = '沐沐华华'
</script>
9.watch
<script setup>
import { watch, ref, reactive } from 'vue'
const name = ref('沐华')
const data = reactive({
age: 18,
money: 100000000000000000000,
children: []
})
watch(name, (newName, oldName) => { ... })
watch(
() => data.age,
(newAge, oldAge) => { ... }
)
watch([data.age, data.money], ([newAge, newMoney], [oldAge, oldMoney]) => { ... })
watch(data.children, (newList, oldList) => { ... }, {
immediate: true,
deep: true,
flush: 'pre',
onTrack (e) { debugger }
onTrigger (e) { debugger }
})
</script>
10.watchEffect
<script setup>
import { watchEffect } from 'vue'
watchEffect(() => {
console.log(userInfo.name)
})
watchEffect(() => {...}, {
flush: 'pre',
onTrack (e) { debugger }
onTrigger (e) { debugger }
})
watchEffect(onInvalidate => {
console.log('沐华')
onInvalidate(() => {
console.log(2222)
})
})
</script>
11.computed
<script setup>
import { computed } from 'vue'
const props = defineProps(['visible', 'type'])
const emit = defineEmits(["myClick"])
const isFirst = computed(() => props.type === 1)
const status = computed({
get () { return props.visible },
set (val) { emit('myClick', val) }
})
const hehe = computed(参数一上面两种都可, {
onTrack (e) { debugger }
onTrigger (e) { debugger }
})
</script>
12.nextTick
<script setup>
import { nextTick} from 'vue'
const handleClick = async () => {
await nextTick()
console.log('沐华')
}
nextTick(() => {
console.log('沐华')
})
nextTick().then(() => {
console.log('沐华')
})
</script>
13.mixins 和 hooks
expport const getData = () => {}
export default function unInstance () {
...
return {...}
}
import unInstance, { getData } from 'xx.js'
const { ... } = unInstance()
onMounted(() => {
getData()
})
14.多个v-model
<template>
<child v-model:name="name" v-model:age="age" />
</template>
<script setup>
import { ref } from "vue"
const name = ref('沐华')
const age = ref(18)
</script>
<script setup>
const emit = defineEmits(['update:name', 'update:age'])
const handleClick = () => {
console.log('点击了')
emit('update:name', '这是新的名字')
}
</script>
15.路由使用
// 需要用到路由的 .vue 文件里
<script setup>
import { useRoute, useRouter } from "vue-router"
const route = useRoute()
const router = useRouter()
</script>
16.样式穿透
<style lang="scss" scoped>
.el-form {
.el-form-item { ... }
}
/deep/ .el-form {
.el-form-item { ... }
}
:deep(.el-form) {
.el-form-item { ... }
}
</style>
17.css添加变量
<template>
<div class="name">沐华</div>
</template>
<script setup>
import { ref } from "vue"
const str = ref('#f00')
</script>
<style scoped lang="scss">
.name {
background-color: v-bind(str); // JS 中的色值变量 #f00 就赋值到这来了
}
</style>
二.Vue3.2.47+TS 使用指南
1.值ref
const initCode = ref('200');
const initCode = ref<string | number>('200');
2.模版ref
<template>
<div ref="el"></div>
</template>
<script setup lang="ts">
import { ref } from 'vue';
const el = ref<HTMLImageElement | null>(null);
</script>
3.组件ref
<template>
<HelloWorld ref="helloworld" />
</template>
<script setup lang="ts">
import { ref, onMounted } from 'vue';
import HelloWorld from '@/components/HelloWorld.vue';
const helloworld = ref<InstanceType<typeof HelloWorld> | null>(null);
onMounted(() => {
helloworld.value?.handleClick();
});
</script>
4.reactive
<script setup lang="ts">
import { reactive } from 'vue';
interface User {
name: string;
age: number;
}
const user: User = reactive({
name: 'zhangsan',
age: 20,
});
</script>
5.computed
const age = computed<number>(() => {
return 2
})
6.defineProps
<template>
<div>
<div>{{ msg }}</div>
<div>{{ address }}</div>
<div>{{ user.name }}--{{ user.age }}</div>
</div>
</template>
<script setup lang="ts">
import { PropType } from 'vue';
interface User {
name: string;
age: number;
}
const props = defineProps({
msg: {
type: String,
default: 'hello',
},
address: {
type: [String, Number],
default: 2,
},
user: {
type: Object as PropType<User>,
default: () => ({
name: 'zhangsan',
age: 12,
}),
},
});
console.log(props.msg);
console.log(props.user.name);
</script>
使用泛型
<template>
<div>{{ name }}</div>
</template>
<script setup lang="ts">
interface User {
name?: string;
age?: number;
}
const props = defineProps<User>();
console.log(props.name);
</script>
6.withDefaults
设置默认值
<script setup lang="ts">
interface User {
name: string
age: number
}
const props = withDefaults(defineProps<User>(), {
name: 'hello',
age: 10,
})
</script>
7.defineEmits
<template>
<div>
<HelloWorld @change="handleChange" />
</div>
</template>
<script setup lang="ts">
import HelloWorld from '@/components/HelloWorld.vue';
import type { User } from '@/types/user';
const handleChange = (value: User) => {
console.log(value);
};
</script>
<template>
<div>
<button @click="handleClick">按钮</button>
</div>
</template>
<script setup lang="ts">
const emit = defineEmits(['change']);
const handleClick = () => {
emit('change', { name: '2', age: 21 });
};
</script>
<template>
<div>
<button @click="handleClick">按钮</button>
</div>
</template>
<script setup lang="ts">
import type { User } from '@/types/user';
const emit = defineEmits<{ (e: 'change', value: User): void }>();
const handleClick = () => {
emit('change', { name: '2', age: 21 });
};
</script>
8.defineExpose
<template>
<div></div>
</template>
<script setup lang="ts">
const handleClick = () => {
console.log('子组件方法');
};
defineExpose({ handleClick });
</script>
9.provide/inject
import type { InjectionKey } from 'vue';
export const key = Symbol() as InjectionKey<string>;
<script setup lang="ts">
import { ref, provide } from 'vue';
const state = ref(0);
const handlerState = () => {
state.value = 1;
};
provide('info', state);
provide('func', handlerState);
</script>
<script setup lang="ts">
import { inject } from 'vue';
const state = inject<number>('info');
const func = inject<() => void>('func');
</script>
undefined问题
const state = inject<number>('info', 20);
const state = inject('info') as number;
10.事件类型
<template>
<input type="text" @change="handleChange" />
</template>
<script setup lang="ts">
const handleChange = (evt: Event) => {
console.log((evt.target as HTMLInputElement).value);
};
</script>
<template>
<button @click="handleClick">按钮</button>
</template>
<script setup lang="ts">
const handleClick = (evt: Event) => {
console.log((evt.target as HTMLButtonElement).style);
};
</script>
11.HTML标签映射关系
interface HTMLElementTagNameMap {
"a": HTMLAnchorElement;
"abbr": HTMLElement;
"address": HTMLElement;
"applet": HTMLAppletElement;
"area": HTMLAreaElement;
"article": HTMLElement;
"aside": HTMLElement;
"audio": HTMLAudioElement;
"b": HTMLElement;
"base": HTMLBaseElement;
"basefont": HTMLBaseFontElement;
"bdi": HTMLElement;
"bdo": HTMLElement;
"blockquote": HTMLQuoteElement;
"body": HTMLBodyElement;
"br": HTMLBRElement;
"button": HTMLButtonElement;
"canvas": HTMLCanvasElement;
"caption": HTMLTableCaptionElement;
"cite": HTMLElement;
"code": HTMLElement;
"col": HTMLTableColElement;
"colgroup": HTMLTableColElement;
"data": HTMLDataElement;
"datalist": HTMLDataListElement;
"dd": HTMLElement;
"del": HTMLModElement;
"details": HTMLDetailsElement;
"dfn": HTMLElement;
"dialog": HTMLDialogElement;
"dir": HTMLDirectoryElement;
"div": HTMLDivElement;
"dl": HTMLDListElement;
"dt": HTMLElement;
"em": HTMLElement;
"embed": HTMLEmbedElement;
"fieldset": HTMLFieldSetElement;
"figcaption": HTMLElement;
"figure": HTMLElement;
"font": HTMLFontElement;
"footer": HTMLElement;
"form": HTMLFormElement;
"frame": HTMLFrameElement;
"frameset": HTMLFrameSetElement;
"h1": HTMLHeadingElement;
"h2": HTMLHeadingElement;
"h3": HTMLHeadingElement;
"h4": HTMLHeadingElement;
"h5": HTMLHeadingElement;
"h6": HTMLHeadingElement;
"head": HTMLHeadElement;
"header": HTMLElement;
"hgroup": HTMLElement;
"hr": HTMLHRElement;
"html": HTMLHtmlElement;
"i": HTMLElement;
"iframe": HTMLIFrameElement;
"img": HTMLImageElement;
"input": HTMLInputElement;
"ins": HTMLModElement;
"kbd": HTMLElement;
"label": HTMLLabelElement;
"legend": HTMLLegendElement;
"li": HTMLLIElement;
"link": HTMLLinkElement;
"main": HTMLElement;
"map": HTMLMapElement;
"mark": HTMLElement;
"marquee": HTMLMarqueeElement;
"menu": HTMLMenuElement;
"meta": HTMLMetaElement;
"meter": HTMLMeterElement;
"nav": HTMLElement;
"noscript": HTMLElement;
"object": HTMLObjectElement;
"ol": HTMLOListElement;
"optgroup": HTMLOptGroupElement;
"option": HTMLOptionElement;
"output": HTMLOutputElement;
"p": HTMLParagraphElement;
"param": HTMLParamElement;
"picture": HTMLPictureElement;
"pre": HTMLPreElement;
"progress": HTMLProgressElement;
"q": HTMLQuoteElement;
"rp": HTMLElement;
"rt": HTMLElement;
"ruby": HTMLElement;
"s": HTMLElement;
"samp": HTMLElement;
"script": HTMLScriptElement;
"section": HTMLElement;
"select": HTMLSelectElement;
"slot": HTMLSlotElement;
"small": HTMLElement;
"source": HTMLSourceElement;
"span": HTMLSpanElement;
"strong": HTMLElement;
"style": HTMLStyleElement;
"sub": HTMLElement;
"summary": HTMLElement;
"sup": HTMLElement;
"table": HTMLTableElement;
"tbody": HTMLTableSectionElement;
"td": HTMLTableDataCellElement;
"template": HTMLTemplateElement;
"textarea": HTMLTextAreaElement;
"tfoot": HTMLTableSectionElement;
"th": HTMLTableHeaderCellElement;
"thead": HTMLTableSectionElement;
"time": HTMLTimeElement;
"title": HTMLTitleElement;
"tr": HTMLTableRowElement;
"track": HTMLTrackElement;
"u": HTMLElement;
"ul": HTMLUListElement;
"var": HTMLElement;
"video": HTMLVideoElement;
"wbr": HTMLElement;
}