纸上得来终觉浅,Vue3 新语法练起来
搜集资源
Vue3 入门指南与实战案例
Vue在线演练场
Vue3.0中Ref与Reactive的区别是什么
Composition API RFC
Vue.js 中使用defineAsyncComponent 延迟加载组件
2022年必会Vue3.0学习 (强烈建议)
10.useSlots用法
父组件
<template> <!-- 子组件 -->
<ChildTSX>
<!-- 默认插槽 -->
<p>I am a default slot from TSX.</p>
<!-- 命名插槽 -->
<template #msg>
<p>I am a msg slot from TSX.</p>
</template>
</ChildTSX>
</template>
<script setup lang="ts">
import ChildTSX from '@cp/context/Child.tsx'
</script>
子组件
<script lang="ts" setup>// 注意:这是一个 .tsx 文件
import { useSlots } from 'vue'
const slots = useSlots()
const ChildTSX = ()=>{
// 渲染组件
return () => (
<div>
{/* 渲染默认插槽 */}
<p>{ slots.default ? slots.default() : '' }</p>
{/* 渲染命名插槽 */}
<p>{ slots.msg ? slots.msg() : '' }</p>
</div>
)
}
}
export default ChildTSX
</script>
9.jsx语法,要借助插件@vitejs/plugin-vue-jsx
<script lang="tsx" setup>const jsxNode = () => {
return <div>text</div>;
};
</script>
<template>
<jsxNode />
</template>
8. 动态class的设置方法
<script setup>import { ref } from 'vue'
const msg = ref('Hello World!')
</script>
<template>
<h1 :class="[`red ${msg === 'Hello World!' ? 'green':''}`]">{{ msg }}</h1>
<input v-model="msg">
</template>
<style scoped>
.red{
color:red;
}
.green{
color:green
}
</style>
7.父子组件通信 props/emit方式
父组件
<template> <Child
ref="child"
title="用户信息"
:index="1"
:u
:user-name="userInfo.name"
@update-age="updateAge"
/>
</template>
<script lang="ts" setup>
import { ref, onMounted } from 'vue'
import Child from '@cp/Child.vue'
interface Member {
id: number,
name: string
}
const child = ref<typeof Child | null>(null)
const userInfo: Member = {
id: 1,
name: 'Petter'
}
onMounted(() => child?.value?.childMethod)
const updateAge = (age: number) => {
console.log(age);
}
</script>
子组件
<template> <p>标题:{{ title }}</p>
<p>索引:{{ index }}</p>
<p>用户id:{{ uid }}</p>
<p>用户名:{{ userName }}</p>
</template>
<script lang="ts" setup>
import { withDefaults, defineProps, defineEmits, toRefs, defineExpose } from 'vue';
const props = withDefaults(defineProps<{
title: string;
index: number;
uid: number;
userName: string;
}>(), { userName: 'zhangsan' });
const { title, index, uid, userName } = toRefs(props);
const emit = defineEmits(['update-age']);
setTimeout(() => {
emit('update-age', 22);
}, 2000);
const childMethod = () => {
console.log('我是子组件的方法')
}
defineExpose({ childMethod })
</script>
6.使用ref操作dom
<template> <!-- 挂载DOM元素 -->
<p ref="msg">留意该节点,有一个ref属性</p>
<!-- 挂载DOM元素 -->
</template>
<script lang="ts" setup>
import { onMounted, ref } from "vue";
// 定义挂载节点,声明的类型详见下方附表
const msg = ref<HTMLElement | null>(null);
// 请保证视图渲染完毕后再执行节点操作 e.g. onMounted / nextTick
onMounted(() => {
// 比如获取DOM的文本
console.log(msg?.value?.innerText);
});
</script>
5.props用法
<script lang="ts" setup> import {withDefaults,defineProps} from 'vue';
const props = withDefaults(defineProps<{
btnName: string;
noBtn?: boolean;
doAction: () => void;
classStyle?: string;
}>(),{
noBtn:true, // 设置默认值
classStyle:''
});
const mActionClass=`m-action ${props.classStyle}`;
<script>
4.生命周期函数
vue2和vue3生命周期对比
beforeCreate -> 使用 setup()created -> 使用 setup()
beforeMount -> onBeforeMount
mounted -> onMounted
beforeUpdate -> onBeforeUpdate
updated -> onUpdated
beforeDestroy -> onBeforeUnmount
destroyed -> onUnmounted
errorCaptured -> onErrorCaptured
<template> <div class="home">
<p>{{ count }}</p>
<p>{{ state.a }}</p>
<button @click="add">加1</button>
</div>
</template>
<script lang="ts" setup>
import {
ref,
reactive,
onBeforeMount,
onMounted,
onBeforeUpdate,
onUpdated,
onBeforeUnmount,
onUnmounted,
onErrorCaptured,
onRenderTracked,
onRenderTriggered,
onActivated,
onDeactivated,
} from "vue";
const count = ref(1);
const state = reactive({ a: 10 });
const add = () => {
count.value += 1;
state.a = state.a + 1;
};
onBeforeMount(() => {
console.log("onBeforeMount");
});
onMounted(() => {
console.log("onMounted");
});
onBeforeUpdate(() => {
console.log("onBeforeUpdate");
});
onUpdated(() => {
console.log("onUpdated");
});
onBeforeUnmount(() => {
console.log("onBeforeUnmount");
});
onUnmounted(() => {
console.log("onUnmounted");
});
onErrorCaptured((evt) => {
console.log("onErrorCaptured", evt);
});
// 只执行一次,有几个响应式api,执行几次
onRenderTracked((evt) => {
console.log("onRenderTracked", evt);
});
// 行为如同onUpdated,每次有数据更新都会执行
onRenderTriggered((evt) => {
console.log("onRenderTriggered", evt);
});
onActivated(() => {
console.log("onActivated");
});
onDeactivated(() => {
console.log("onDeactivated");
});
</script>
4. shallowReactive, shallowRef, readonly,shallowReadonly,toRaw,markRaw函数区别
shallowReactive、shallowRef的之间的区别
shallowReactive:浅监视shallowRef:不做监视
readonly和shallowReadonly
readonly:只读属性的数据,深度只读const state2 = readonly(state)
shallowReadonly:只读的数据,浅只读的
toRaw和markRaw
toRaw将代理对象变成普通对象,数据变化,界面不会进行更新const user = toRaw(state);
markRaw标记的对象数据,从此以后都不能在成为代理对象了
const likes = ['吃',‘喝’]
state.likes = markRaw(likes)
<template> <h4>
<button @click="triggerShallowReactiveRender">
改变第一层才会渲染
</button>
</h4>
<p>{{ shallowReactiveState.a }}</p>
<h4>
<button @click="triggerShallowRefRender">
失去响应式
</button>
</h4>
<p>{{ shallowRefState.a }}</p>
</template>
<script setup>
import { readonly,reactive, shallowReactive, shallowRef, toRaw } from "vue";
// shallowRef 与shallowReactive
// shallowRef 与shallowReactive创建的是非递归的响应对象,shallowReactive创建的数据第一层数据改变会重新渲染dom
const shallowReactiveState = shallowReactive({
a: "initShallowReactiveState",
b: {
c: "c",
},
});
//如果不改变第一层 只改变其他的数据 页面不会重新渲染,例如:
shallowReactiveState.b.c = 2;
//改变第一层的数据会导致页面重新渲染
const triggerShallowReactiveRender=()=>{
shallowReactiveState.a = "changeShallowReactiveState";
}
// shallowRef创建的对象没有响应式特性
const shallowRefState = shallowRef({
a: "initShallowRefState",
b: {
c: "c",
},
});
const triggerShallowRefRender=()=>{
//失去响应式--除非对整个对象重新赋值或者使用triggerRef(shallowRefState)触发页面更新
shallowRefState.a = "changeShallowRefState";
}
// toRaw ---只修改数据不渲染页面
var obj = { name: "test" };
var toRawState = reactive(obj);
var raw = toRaw(toRawState);
//并不会引起页面的渲染,而obj.name,toRawState.name的值均已改变
setTimeout(()=>raw.name = "zs",2000);
// 不允许修改对象的值
const readonlyState = readonly({a:1,b:2});
// 赋值会引起警告
readonlyState.a=2;
</script>
3. toRefs和toRef的用途
借助toRefs可以在template部分,直接使用结构后的对象单个键值,写法简洁,却不失响应式。
toRef是转换reactive对象的单个值
<template> <ul class="user-info">
<li class="item">
<span class="key">ID:</span>
<span class="value">{{ id }}</span>
</li>
<li class="item">
<span class="key">name:</span>
<span class="value">{{ name }}</span>
</li>
<li class="item">
<span class="key">age:</span>
<span class="value">{{ age }}</span>
</li>
<li class="item">
<span class="key">gender:</span>
<span class="value">{{ gender }}</span>
</li>
</ul>
</template>
<script lang="ts" setup>
import { reactive, toRef, toRefs } from "vue";
interface Member {
id: number;
name: string;
age: number;
gender: string;
}
// 定义一个reactive对象
const userInfo: Member = reactive({
id: 1,
name: "Petter",
age: 18,
gender: "male",
});
// 结构reactive对象,它的字段全部是ref变量
const { id, age, gender } = toRefs(userInfo);
const name: string = toRef(userInfo, 'name');
// 2s后更新userInfo
setTimeout(() => {
userInfo.id = 2;
userInfo.name = "Tom";
userInfo.age = 20;
}, 2000);
</script>
2. 响应式数据
ref可以定义任何类型的数据,但是定义数据和对象时,在script部分使用时,赋值和取值,不如reactive方便
reactive只能用于数组,对象类型。
ref的本质是通过reactive创建的,Ref(10)=>Reactive({value:10});
reactive的本质是将每一层的数都解析成proxy对象,reactive 的响应式默认都是递归的,改变某一层的值都会递归的调用一遍,重新渲染dom。
<template> <p>{{count}}</p>
<button @click="add">加1</button>
<p>{{info.name}}</p>
<button @click="changeName">改姓名</button>
</template>
<script lang="ts" setup>
import { reactive, ref } from 'vue';
interface Info{
name:string;
age:number;
}
// 响应式基本类型用ref
const count = ref<number>(0);
// 响应式引用类型用reactive
const info:Info = reactive({ age: 100,name:'zhangsan' });
const add = () => {
// 基本类型赋值时,是赋值给value属性
count.value += 1;
};
const changeName = () => {
info.name="lisi";
};
</script>
1.路由取值和跳转
<script lang="ts" setup>import { useRoute, useRouter } from 'vue-router';
const route = useRoute();
const router = useRouter();
// 获取路由信息
console.log(route.query.id);
// 编程式路由跳转
const jump = ()=> {
router.push({ path: `/about` , query:{id:'xxx}});
};
</script>
以上是 纸上得来终觉浅,Vue3 新语法练起来 的全部内容, 来源链接: utcz.com/z/379536.html