持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第2天,点击查看活动详情
Vue3+TypeScript学习笔记第二篇,上一篇点【传送门】。本文是在学习技术胖的课程后写下的学习笔记,方便以后查阅。好记性不如烂笔头,写过笔记印象深刻很多。这是基础入门篇,不喜轻喷。
第一至第七点(回顾上一篇)
八. Vue3中watch的使用和注意事项
监听单个值,引入后编写watch函数,它接受两个参数,第一个是要监听的值,这里是course,然后是一个回调函数。在函数中你可以获得到新值和旧值。
<template>
<div>当前课程:{{ course }}</div>
<button @click="changeCourseState">修改课程状态</button>
</template>
<script lang="ts">
import { defineComponent, ref, watch } from "vue";
export default defineComponent({
name: "HomeView",
setup() {
const course = ref("Javascript");
const changeCourseState = () => {
course.value = course.value + "学习完成|";
};
watch(course, (newValue, oldValue) => {
//使用watch监听course变化,在回调函数中获取新旧值
console.log(`new--->${newValue}`);
console.log(`old--->${oldValue}`);
});
return {
course,
changeCourseState,
};
},
});
</script>
监听多个值,当你要监听多个值的时候,不是写多个watch函数,而是要传入数组的形式。
<script lang="ts">
import { defineComponent, ref, reactive, toRefs, watch } from "vue";
export default defineComponent({
name: "HomeView",
setup() {
interface DataProps {
//给data增加类型注解
courseList: string[];
selectCourse: string;
selectCourseFun: (index: number) => void;
}
const data: DataProps = reactive({
courseList: ["vue3初识", "Node.js进阶", "css世界"],
selectCourse: "vue3初识",
selectCourseFun: (index: number) => {
data.selectCourse = data.courseList[index];
},
});
const course = ref("Javascript");
const changeCourseState = () => {
course.value = course.value + "学习完成|";
};
////不是直接data.selectCourse,因为watch不能监听没有getter/effect方法。可以使用箭头函数直接返回。
watch([course, () => data.selectCourse], (newValue, oldValue) => {
console.log(`new--->${newValue}`);
console.log(`old--->${oldValue}`);
});
return {
...toRefs(data),
course,
changeCourseState,
};
},
});
</script>
可以看到监听多个值时候,新旧值会以逗号隔开。
九. Vue3中模块化介绍
//模块 useNowTime.ts
import { ref } from 'vue'
const nowTime = ref("00:00:00");
const getNowTime = () => {
const now = new Date();
const hour = now.getHours() < 10 ? String(now.getHours()).padStart(2, "0") : now.getHours();
const minu = now.getMinutes() < 10 ? "0" + now.getMinutes() : now.getMinutes();
const sec = now.getSeconds() < 10 ? "0" + now.getSeconds() : now.getSeconds();
nowTime.value = hour + ":" + minu + ":" + sec;
setTimeout(getNowTime, 1000); //每一秒执行一次这个方法
}
export { nowTime, getNowTime } //导出
<template>
<div>{{ nowTime }}</div>
<div><button @click="getNowTime">显示时间</button></div>
</template>
<script lang="ts">
import { defineComponent } from "vue";
import { nowTime, getNowTime } from "../hooks/useNowTime"; //引入模块
export default defineComponent({
name: "HomeView",
setup() {
return {
nowTime,
getNowTime,
};
},
});
</script>
使用axios获取图片
// 模块useUrlAxios.js
import { ref } from 'vue'
import axios from 'axios' //需要先安装依赖 yarn add axios 或 cnpm i axios -S
function useUrlAxios(url: string) {
const result = ref(null)
const loading = ref(true)
const loaded = ref(false)
const error = ref(null)
axios.get(url).then((res) => {
loading.value = false;
loaded.value = true;
result.value = res.data;
}).catch(e => {
error.value = e;
loading.value = false;
})
return {
result,
loading,
loaded,
error
}
}
export default useUrlAxios
<template>
<div>
<div v-if="loading">Loading.....</div>
<img v-if="loaded" :src="result.message" />
</div>
</template>
<script lang="ts">
import { defineComponent } from "vue";
import useUrlAxios from "../hooks/useUrlAxios"; //引入模块
export default defineComponent({
name: "HomeView",
setup() {
const { result, loading, loaded } = useUrlAxios(
"https://dog.ceo/api/breeds/image/random"
);
return { result, loading, loaded };
},
});
</script>
十. Teleport瞬间移动函数的使用(独立函数)
Teleport在国内大部分都翻译成了瞬间移动组件,个人觉得不太好理解。我把这个函数叫独立组件,它可以把你写的组件挂载到任何你想挂载的DOM上,所以说是很自由很独立的。 在使用Vue2的时候是作不到的。
// 新建组件 newDialog.vue
<template>
<teleport to="#modal">
//组件挂载在modal节点上
<h2>自定义Dialog组件</h2>
</teleport>
</template>
// 在public/index.html增加一个Modal节点
<div id="app"></div> <div id="modal"></div>
<template>
<div>
//组件挂载在app节点上
<h2>原节点</h2>
</div>
<new-dialog></new-dialog>
</template>
<script lang="ts">
import newDialog from "@/components/newDialog.vue"; //引入组件
const app = {
name: "HomeView",
components: {
newDialog,
},
};
export default app;
</script>
Teleport方法,可以把Dialog组件渲染到你任意想渲染的外部Dom上,不必嵌套再#app里了,这样就不会互相干扰了。你可以把Teleport看成一个传送门,把你的组件传送到你需要的地方。 teleport组件和其它组件没有任何其它的差异,用起来都是一样的。
十一. Suspense 初识异步请求组件
在Vue2.x时代,判断异步请求的状态是一件必须的事情,但是这些状态都要自己处理,根据请求是否完毕展示不同的界面。尤大神深知民间饥苦,在Vue3.x中给我们提供了Suspense组件。
<suspense> 组件有两个插槽。它们都只接收一个直接子节点。default 插槽里的节点会尽可能展示出来。如果不能,则展示 fallback 插槽里的节点。
Demo1
//新建组件 AsyncShow.vue
<template>
<h1>{{ result }}</h1>
</template>
<script lang="ts">
import { defineComponent } from "vue";
export default defineComponent({
setup() {
return new Promise((resolve, reject) => {
//模拟异步请求数据
setTimeout(() => {
return resolve({ result: "已经延迟两秒了,我要出来了" });
}, 2000);
});
},
});
</script>
<template>
<div>
<Suspense>
<template #default>
<AsyncShow></AsyncShow>
</template>
<template #fallback>
<h1>loading....</h1>
</template>
</Suspense>
</div>
</template>
<script lang="ts">
import AsyncShow from "@/components/AsyncShow.vue"; //引入组件
export default {
name: "HomeView",
components: { AsyncShow },
setup() {
return {};
},
};
</script>
Demo2
//新建组件 DogShow.vue
<template>
<img :src="result" alt="" />
</template>
<script lang="ts">
import axios from "axios";
import { defineComponent } from "vue";
export default defineComponent({
async setup() {
//使用async await代替promise
const rowData = await axios.get("https://dog.ceo/api/breeds/image/random");
return { result: rowData.data.message };
},
});
</script>
<template>
<div>
<Suspense>
<template #default>
<DogShow></DogShow>
</template>
<template #fallback>
<h1>loading....</h1>
</template>
</Suspense>
</div>
</template>
<script lang="ts">
import DogShow from "@/components/DogShow.vue"; //引入组件
export default {
name: "HomeView",
components: { DogShow },
setup() {
return {};
},
};
</script>
onErrorCaptured钩子函数
在捕获一个来自后代组件的错误时被调用。此钩子会收到三个参数:错误对象、发生错误的组件实例以及一个包含错误来源信息的字符串。此钩子可以返回 false 以阻止该错误继续向上传播。【传送门】
Demo2 组件DogShow.vue稍微修改一下,故意把接口写错"dog.ceo/api/breeds/…" 。
<template>
<div>
<Suspense>
<template #default>
<DogShow></DogShow>
</template>
<template #fallback>
<h1>{{ currentState }}</h1>
</template>
</Suspense>
</div>
</template>
<script lang="ts">
import { ref, onErrorCaptured } from "vue";
import DogShow from "@/components/DogShow.vue";
export default {
name: "HomeView",
components: { DogShow },
setup() {
const currentState = ref("loading....");
//捕获后代组件报错信息
onErrorCaptured((error, instance, info) => {
console.log(`error====>`, error);
console.log(`instance====>`, instance);
console.log(`info====>`, info);
currentState.value = "异步数据请求失败!";
return true;
});
return {
currentState,
};
},
};
</script>
后续会再Vue3学习笔记第③篇。