由于还不会jsx,先使用
vue3+typescript+template模式
网上还有一种tsx+vue模式 以下代码都使用vue3语法(vue3也可以使用vue2语法)
1、项目创建
- 官网需要vue-cli4+版本才能创建
- 官网
- 选择vue3+typescript就可以
2、生命周期
- 与vue2对比,把beforCreate与created合并成了setUp(在他两之前执行)
vue2-------------vue3
//创建组件前后
beforeCreate -> setup()
created -> setup()
//组件挂载到dom前后
beforeMount -> onBeforeMount
mounted -> onMounted
//组件更新前后
beforeUpdate -> onBeforeUpdate
updated -> onUpdated
//组件销毁/删除前后
beforeDestroy -> onBeforeUnmount
destroyed -> onUnmounted -- 定时器,监听器 事件销毁写在此函数内
- 上代码
<script lang="ts">
import { //现在使用的方法都要按需引入
onBeforeMount,
onMounted,
onBeforeUpdate,
onUpdated,
onBeforeUnmount,
onUnmounted
} from 'vue'
export default {
name: "生命周期",
setup() {
console.log('1---setup,组件创建之前')
onBeforeMount(()=>{
console.log('2---onBeforeMount,组件挂载到dom前')
})
onMounted(()=>{
console.log('3---onMounted,组件挂载到dom后')
})
//组件更新前后--比如数据更新后,会触发组件更新
onBeforeUpdate(()=>{
console.log('4---onBeforeUpdate,组件更新前')
})
onUpdated(()=>{
console.log('5---onUpdated,组件更新后')
})
//组件销毁前后 节点删除或替换会触发
onBeforeUnmount(()=>{
console.log('6---onBeforeUnmount,卸载组件前')
})
onUnmounted(()=>{
console.log('7---onBeforeUnmount,卸载组件后')
})
}
}
</script>
- 结果
3、响应式
3.1 ref
一般使用于基本类型 ,数组也推荐。。修改时需要加上.value
const refCount = ref<number>(0)
refCount.value = 2 //修改时需要加上.value
3.2 reactive
一般使用于对象格式的
-
我们来实现一个标题点击选中的代码,效果如下
-
代码
template
<template>
<div class="life-cycle">
<span v-for="(i,index) in tabTitle.list"
:key="i"
@click="tabTitle.titleClick(index)"
:class="i===tabTitle.currentTitle?'active':''"
>
{{i}}
</span>
<div>当前选中的标题:{{tabTitle.currentTitle}}</div>
</div>
</template>
script
<script lang="ts">
import {
ref,
reactive
} from 'vue'
//定义接口
interface TabTitleProps {
list: string[],
currentTitle: string,
titleClick: (index: number) => void
}
export default {
setup() {
const tabTitle = reactive<TabTitleProps>({
list: ['标题A', '标题B', '标题C'],
currentTitle: '',
titleClick: (index:number)=>{
tabTitle.currentTitle = tabTitle.list[index]
}
})
//可以理解为vue2中的data(){return{}}
return {
tabTitle
}
}
}
</script>
4、template
- 可以这么玩了
<template>
<div></div>
<div></div>
<template>
5、watch
- 以下代码都在
setup方法内执行,要引入watch
5.1 监听单个值(ref)
//watch
/**
* refCount:监听的值, refCount 新的值, prevRefCount 旧的值
*/
const refCount = ref<number>(1)
watch(refCountTwo, (newVal:number, oldVal:number):void=>{
console.log('new值', newVal) // 2
console.log('old值', oldVal) // 1
console.log('-------------')
})
setTimeout(()=>{
refCount.value++
}, 2000)
5.2 监听多个值 (ref)
const refCount = ref<number>(1)
const refCountTwo = ref<number>(100)
//watch 多个
/**
* refCount:监听的值, refCount 新的值, prevRefCount 旧的值
*/
watch([refCount, refCountTwo], (newVal:number, oldVal:number):void=>{
console.log('new值', newVal) //[2, 101]
console.log('old值', oldVal) //[1, 100]
console.log('-------------')
})
setTimeout(()=>{
refCount.value++
refCountTwo.value++
}, 2000)
5.3 深度监听 (reactive)
cosnt person = {
name: 'lfz',
age: 11
}
- 例如要监听
person内的age属性
setup(){
watch(() => personA.age, (newVal: number, oldVal: number): void => {
console.log('new值', newVal)
console.log('old值', oldVal)
console.log('-------------')
})
setTimeout(()=>{
personA.age++
},1000)
}
5.4 立即执行
watch(\
() => props.name,\
(newValue, oldValue) => {\
console.log(newValue+‘------------’+oldValue);\
},{**immediate : true**}
6、watchEffect
- 这个直接监听了所有值变化的问题
- 感觉这个比
watch好用
//改变person.age后就执行
watchEffect(()=>{
console.log(36, personA.age)
})
7、computed
7-1 只读
- template
<template>
<div>
<div>a:{{a}}</div>
<div>b:{{b}}</div>
<div>a+b={{addVal}}</div>
</div>
</template>
- script
<script lang="ts">
import {ref, computed} from 'vue'
export default {
name: "computed",
setup(){
const a = ref<number>(1)
const b = ref<number>(1)
const addVal:number = computed(():number=> a.value+b.value)
return {
addVal,
a,
b
}
}
}
</script>
7-2 可修改
- script
const innerVisible = computed({
get() {
return props.dialogVisible
},
set(value: boolean) {
emit('update:dialogVisible', value)
}
})
8.1、全局挂载-方法一
- 我们在
vue2中直接用prototype直接进行挂载。 vue3挂载方法 在main.ts中
//挂载全局实例
app.config.globalProperties.$test = 'test'
在组件中使用
import {getCurrentInstance } from 'vue'
setup() {
// ts proxy 使用
const { proxy }: any = getCurrentInstance()
console.log(36, proxy.$test)//test
return {}
}
9、ref,dom
html
<span ref="domTest">我是dom</span>
script
improt {ref, onMounted} from 'vue'
export default {
setup() {
const domTest = ref(null) //声明对象
onMounted(()=>{
console.log(43, domTest.value)//输出dom对象
console.log('3---onMounted,组件挂载到dom后')
})
retrun {
domTest//一定要返回
}
}
}
10、toRefs
- 可以用来为源响应式对象上的 property 性创建一个 ref。然后可以将 ref 传递出去,从而保持对其源 property 的响应式连接。(官话)
- 就是你要解构对象,还要保持响应的功能,这时候就可以用到
- 下面看demo
import {ref, reactive, toRefs} from 'vue'
setUp() {
/**********************reactive***********************/
interface Person {
name: string,
gender: string
}
let person = reactive<Person>({
name: 'aaa',
gender: 'male'
})
console.log(33, person) //Proxy{name: 'lufangzhou', gender:'male'}
//person.name = 'bbb'
setTimeout(_=>{
person.name = 'bbb'
})
//解构
//toRefs , 原本是proxy({name: 'lufangzhou', gender:'male'})
//可以用来为源响应式对象上的 property 性创建一个 ref。然后可以将 ref 传递出去,从而保持对其源 property 的响应式连接。
const {name, gender} = toRefs(person)
return {
name,
gender
}
}
11、useRouter
1、 在setup内
import { useRouter } from 'vue-router'
const router = useRouter() // 等于this.$router, $route也是一样
2、不在setup内,若在hooks内
// import { useRoute, useRouter } from "vue-router"
import Vrouter from "@/router"
// const router = useRouter();
// const route = useRoute();
const route = Vrouter.currentRoute.value
const router = Vrouter
// 监测
watch(() => Vrouter.currentRoute.value.query,
(query) => {
ListParams.value = Object.assign(params,query)
res.value = handleParams()
})
12、unref
unref():是 val = isRef(val) ? val.value : val 的语法糖。
const valueRef = ref('');
const value = unref(valueRef);
if (!value) {
console.warning('请输入要拷贝的内容!');
return;
}
13、内敛语法中获取slot
const slotContent = useSlots().default?.()[0].children