vue3+typescript

121 阅读1分钟

vue3的变化

1:v-if和v-for的优先级被更改,但还是不推荐一起使用

2:组件的事件要在emits选项中声名

3:destroyed生命周期(销毁)重命名为unmounted

4:自定义指令的apl已经更改与生命周期一致

5:新增三个组件:Fragment支持多个根节点,Suspense可以在组件渲染之前的等待时间显示指定内容,Teleport可以让子组件能够在视觉上跳出父组件

6:新增v-memo,可以换成html模板,比如v-for列表不会变化就缓存,(内存换时间)

7:用proxy代替object.defineProperty,可以监听数组下的变化,以及对象新增属性

8:重构虚拟DOM,在编译时会将事件缓存,将slot编译为lazy,保存静态节点直接复用,以及添加静态标记,Diff算法使用最长递增子序列优化对比流程,使得虚拟DOM生成速度变快

9:在里使用v-bind,给css绑定js变量(如color:v-bind(str))

10:新增Composition API(组合式API)可以更好的逻辑复用和代码组织

11:全局函数set和delete以及实例方法setset和delete移除

12:onon,off,$once实例方法被移除,组件实例不再实现事件触发接口

模板的引入

<template>
  <Cjy></Cjy>
</template>

<script setup lang="ts">
import Cjy from './components/Cjy.vue'
</script>

响应式数据

ref()和reactive()

直接 let x=20 这样的数据不是响应式的,必须用ref包装一下

ref()和reactive()的区别 ref多用于基础数据类型 reactive多用于复杂数据类型

<template>
  <div>
    TSY组件{{num}}
    <p>{{objref.x}}</p>
    <button @click="num++">++</button>
    <button @click="hdclick">++</button>
    <button @click="hdclickobj">++</button>
    <p ref="op">asd</p>
    <p>{{obj2re.y}}</p>
  </div>
</template>

<script lang="ts">
import { nextTick,defineComponent,ref,Ref,reactive,toRefs} from 'vue'
export default defineComponent({
    setup(){
        // ref响应式
        //let num = 20;这样子定义的数据不是响应式数据(做不到双向数据绑定)
        let num:Ref<number>= ref(20);//用ref包起来,这个num是vue内部封装的一个响应式数据
        // num是给包装过后的对象,num.value才能拿到20这个数据
        // 所以要操作这个响应式数据需要使用 .value
        //模板是还是继续使用{{num}}
        const hdclick=()=>{
            num.value++
        }

        // 对复杂数据的响应式
        // ref()和reactive()的区别;ref要 .value.值 ,reactive直接 .值
        // 应用场景  ref()多用于基础数据类型,reactive用于复杂数据类型
        let obj={
            x:0
        }
        let objref=ref(obj)
        const hdclickobj=()=>{
            objref.value.x++
        }

        let obj2={
            y:1
        }
        let obj2re=reactive(obj2)
        console.log(obj2re.y);
        // 解构:toRefs的作用就是reactive的对象解构从响应式数据
        let {y}=toRefs(obj2re)
        console.log(y);        
        
        // 获取DOM
        let op =ref();
        // onMounted(()=>{
        //     console.log(op.value);
        // })
        nextTick(()=>{
            console.log(op.value);
        })

        return{
            // 定义的方法和数据向外暴露,否则模板是访问不到
            num,
            objref,
            hdclick,
            hdclickobj,
            op,
            obj2re
        }
    },
})
</script>

数据监听wacth,watchEffect

// 基础数据类型
let x=ref(0);
watch(x,(oldvla,newval)=>{
    console.log(oldvla);
    console.log(newval);
})

//复杂数据类型
let obj={
    num:0
}
let {num}=toRefs(reactive(obj));
watch(num,(oldvla,newval)=>{
    console.log(oldvla);
    console.log(newval);
})

/ num是解构出来的的可以这样监听,如果没有解构出来呢
// 方式一
watch(()=>objerf.num,(oldvla,newval)=>{
    console.log(oldvla);
    console.log(newval);
})
// 方式二
watch([()=>objerf.num],(oldvla,newval)=>{
    console.log(oldvla);
    console.log(newval);
})

// watchEffect,在页面刷新时就触发,立即触发
watchEffect(()=>{
    // 凡是写在这里的数据,只要发送变化,就会被立即监听
    console.log(num.value);
    console.log(x.value);
    console.log(objerf.num);
})

计算属性

计算属性分为只读的和可写的

import {toRefs,ref,computed,reactive} from "vue"
 
// 计算属性
let num=ref(20)
//创建一个只读的计算属性
let numx=computed(()=>{
    return num.value*2
})

let obj={
    x:0
}
let {x}=toRefs(reactive(obj)) 
let objx=computed(()=>{
    return x.value*3
})

//可写计算属性
const refx = computed({
    get:():number=>{
        // ! ! ! 注意get一定要有返回值
        return x.value
    },
    set:(val)=>{
        x.value=val;
    }
})
// 访问触发get
refx.value
// 改值,触发set
refx.value=5;
console.log(x.value);//5
 

父子组件通信

父传子

父组件

<template>
    <h1>父组件</h1>
    <!-- 父传子,直接通过自定义属性传值 -->
    <Son :num="num"></Son>
</template>

<script setup lang="ts">
import Son from "./Son.vue"
import {ref} from "vue"
let num = ref(10)
</script>

子组件

<template>
    <h1>子组件{{ num }}</h1>
</template>

<script setup lang="ts">
import { ref, defineProps } from "vue";

let x=ref(0)
//用defineProps接收
defineProps({
    num:{
        type:Number,//类型
        default:30//默认值
    }
})
</script>

子传父 子组件

<template>
    <h1>子组件</h1>
    <button @click="getdata"></button>
</template>

<script setup lang="ts">
import { ref} from "vue";
let x=ref(20);

// 先定义事件
const emit=defineEmits<{
    (event:'getfun',id:number):void
}>()

const getdata=()=>{
    // 之前是$emit('自定义事件',参数)
    emit('getfun',x.value)
}
</script>

父组件

<template>
    <h1>父组件</h1>
    <Son @getfun="getdata"></Son>
</template>

<script setup lang="ts">
import Son from "./Son.vue"

// 接收
const getdata=(id:number)=>{
    console.log(id);
}
</script>