1. 新建项目
vue create vue-study
2. 运行
yarn serve
语法
1. setup函数
可以取代data和method,相较于vue2,如果需要在template中使用的话,setup函数需要return。不需要再界面上暴露的变量就不需要return,精确控制导出的变量和方法
```javaScript
setup() {
const girls = ref(["大脚", "刘英", "晓红"]);
const selectGirl = ref("");
// 使用ref,在script中使用/获取变量值需要加上value
const selectGirlFun = (index: number) => {
selectGirl.value = girls.value[index];
};
//因为在模板中这些变量和方法都需要调用,所以需要return出去。
return {
girls,
selectGirl,
selectGirlFun,
};
}
```
2. ref函数
使用的话,需要引入`import { ref } from "vue";`,然后`ref(["大脚", "刘英", "晓红"])`
ref函数接收一个内部值,返回一个可响应且可变的对象,**在setup中,使用ref,要改变和读取一个值的时候,还要加上value**
3. reactive函数
是一个接收Object(对象)参数的函数,用于优化上述使用ref函数之后,改变和读取变量需要加上value的情况
和ref()函数一样,都是生成响应式对象的方法
```HTML
<button
v-for="(item, index) in data.girls"
v-bind:key="index"
@click="data.selectGirlFun(index)"
>
{{ index }} : {{ item }}
</button>
<!-- 需要加上data.来调用 -->
<div>你选择了【{{ data.selectGirl }}】为你服务</div>
```
```JavaScript
// 记得加上类型注解
interface DataProps {
girls: string[];
selectGirl: string;
selectGirlFun: (index: number) => void;
}
const data: DataProps = reactive({
girls: ["大脚", "刘英", "晓红"],
selectGirl: '',
selectGirlFun: (index: number) => {
// 修改值不需要加value了
data.selectGirl = data.girls[index]
}
});
// 只需要返回一个data
return {
data,
};
```
4. toRefs()函数
使用reactive函数后,现在template中,每次输出变量前面都要加一个data,可以使用toRefs来优化
Vue3 的一个新函数toRefs(),引入后就可以对data进行包装,把 data 变成refData,这样就可以使用扩展运算符的方式了,否则直接使用扩展运算符会导致变量不可响应
```HTML
<button
v-for="(item, index) in girls"
v-bind:key="index"
@click="selectGirlFun(index)"
>
{{ index }} : {{ item }}
</button>
<div>你选择了【{{ selectGirl }}】为你服务</div>
```
```JavaScript
setup() {
// const girls = ref(["大脚", "刘英", "晓红"]);
// const selectGirl = ref("");
// const selectGirlFun = (index: number) => {
// selectGirl.value = girls.value[index];
// };
const data: DataProps = reactive({
girls: ["大脚", "刘英", "晓红"],
selectGirl: "",
selectGirlFun: (index: number) => {
data.selectGirl = data.girls[index];
},
});
const refData = toRefs(data);
return {
...refData,
};
},
```
5. 生命周期
1. setup函数 -> 开始创建组件之前,在`beforeCreate`和`created`之前,创建的是data和method。
可以使用setup函数来代替beforeCreate
和created
2. onBeforeMount -> 组件挂载到节点之前
3. onMounted -> 组件挂载到节点之后
4. onBeforeUpdate => 组件更新之前
5. onUpdated -> 组件更新之后
6. onBeforeUnmount -> 组件卸载之前
7. onUnmounted -> 组件卸载之后
8. onActivated -> 激活<keep-alive>组件时
9. onDeactivated -> 离开<keep-alive>组件时
10. onErrorCaptured -> 当捕获一个来自子孙组件的异常时激活钩子函数
在使用钩子函数之前,需要引入
```JavaScript
import {
reactive,
toRefs,
onMounted,
onBeforeMount,
onBeforeUpdate,
onUpdated,
} from "vue";
// 注意:vue3的这些钩子函数写在setup函数里面
setup() {
console.log("1-开始创建组件-----setup()");
const data: DataProps = reactive({
girls: ["大脚", "刘英", "晓红"],
selectGirl: "",
selectGirlFun: (index: number) => {
data.selectGirl = data.girls[index];
},
});
onBeforeMount(() => {
console.log("2-组件挂载到页面之前执行-----onBeforeMount()");
});
onMounted(() => {
console.log("3-组件挂载到页面之后执行-----onMounted()");
});
onBeforeUpdate(() => {
console.log("4-组件更新之前-----onBeforeUpdate()");
});
onUpdated(() => {
c onsole.log("5-组件更新之后-----onUpdated()");
});
const refData = toRefs(data);
return {
...refData,
};
},
```
Vue2的生命周期函数依然可以使用,可以写在setup函数后面
```JavaScript
setup() {
...
}
beforeCreate() {
console.log("1-组件创建之前-----beforeCreate()");
},
beforeMount() {
console.log("2-组件挂载到页面之前执行-----BeforeMount()");
},
mounted() {
console.log("3-组件挂载到页面之后执行-----Mounted()");
},
beforeUpdate() {
console.log("4-组件更新之前-----BeforeUpdate()");
},
updated() {
console.log("5-组件更新之后-----Updated()");
},
// 以下是两个版本生命周期的对比
// 除了beforeDestroy -> onBeforeUnmount、destroyed -> onUnmounted,其他只是加了on
Vue2--------------vue3
beforeCreate -> setup()
created -> setup()
beforeMount -> onBeforeMount
mounted -> onMounted
beforeUpdate -> onBeforeUpdate
updated -> onUpdated
beforeDestroy -> onBeforeUnmount
destroyed -> onUnmounted
activated -> onActivated
deactivated -> onDeactivated
errorCaptured -> onErrorCaptured
````
6. onRenderTracked()和onRenderTrigger()函数
用来调试使用的两个钩子函数。使用前需要引入
`import { onRenderTriggered ,onRenderTracked,} from "vue";`
onRenderTracked函数——状态追踪
它会追踪页面上**所有**响应式变量和方法的状态,即我们在setup中return出去的值,一旦页面有更新,他都会进行追踪,然后生成一个event对象,我们通过event对象来查找程序的问题所在
onRenderTriggered函数——状态触发
它不像onRenderTracked函数,这个函数不会跟踪所有值的变化,而是给你变化值的信息,并且新值和旧值都会给你明确的展示出来
```JavaScript
onRenderTracked((event) => {
console.log("状态跟踪组件----------->");
console.log(event);
});
onRenderTriggered((event) => {
console.log("状态跟踪组件----------->");
console.log(event);
});
```
其中`event`对象属性:
```
- key 那边变量发生了变化
- newValue 更新后变量的值
- oldValue 更新前变量的值
- target 目前页面中的响应变量和函数
```
7. watch函数
使用之前需要先导入 `import {... , watch} from "vue"`
以下是监听一个数和多个数的使用方式
```JavaScript
watch(overText, (newValue, oldValue) => {
document.title = newValue;
});
// 注意:
// 当我们想监听data.selectGirl这个reactive里边的值时,可以使用一个函数来解决,() => data.selectGirl
// 监听多个数的变化,返回的newValue也是一个数组
watch([overText, () => data.selectGirl], (newValue, oldValue) => {
console.log(`new--->${newValue}`);
console.log(`old--->${oldValue}`);
document.title = newValue[0]; // 返回的newValue也是一个数组
});
```
8. Vue3模块化
如果需要将一个功能进行模块化和复用化,可以在src目录下,新建一个文件夹hooks(所有抽离出来的功能模块都可以放到这个文件夹里),然后再新建一个文件useNowTime.ts,这里使用use开头是一个使用习惯,代表是一个抽离出来的模块。
```JavaScript
// 注意需要引入ref
import { ref } from "vue";
const nowTime = ref("00:00:00");
const getNowTime = () => {
const now = new Date();
const hour = now.getHours() < 10 ? "0" + now.getHours() : 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
export { nowTime, getNowTime }
// 引入和使用
import { nowTime, getNowTime } from "./hooks/useNowTime";
// 注意: 需要在setup中return,才可以在template中使用
setup() {
return {nowTime,getNowTime};
}
```
远程调用API组件也可以这样子封装
9. Teleport瞬间移动组件的使用
它可以把你写的组件挂载到任何你想挂载的DOM上,在vue2中,所有dom都是挂载在#app下的,如果想改变节点这是非常的困难的。vue3的Teleport组件可以帮助解决这个问题。
Teleport方法,可以把Dialog组件渲染到你任意想渲染的外部Dom上,不必嵌套再#app里了,这样就不会互相干扰了。可以把Teleport看成一个传送门,把你的组件传送到你需要的地方。 teleport组件和其它组件没有任何其它的差异,用起来都是一样的。
使用方法如下:
```JavaScript
// Model.vue,自定义组件
// 将编写的组件用<teleport>标签进行包裹,在组件上有一个to属性,这个就是要写你需要渲染的DOMID了。
<template>
<teleport to="#modal">
<div id="center">
<h2>JSPang11</h2>
</div>
</teleport>
</template>
// /public/index.html,在其中增加一个#model节点
<div id="app"></div>
<div id="modal"></div>
// App.vue,正常使用即可
<Modal></Modal>
```
这时候在浏览器中预览,就会发现,现在组件已经挂载到model节点上了,这就是teleport组件的使用了。
10. 初识Suspense组件
在Vue2.x时代,判断异步请求的状态是一件必须的事情,但是这些状态都要自己处理,根据请求是否完毕展示不同的界面,Vue3提供了Suspense组件来解决异步请求,页面渲染的问题
Suspense提供两个template的位置,一个是没有请求回来时显示的内容,一个是全部请求完毕的内容。这样进行异步内容的渲染就会非常简单。
**注意点:如果你要使用Suspense的话,要返回一个promise对象,而不是原来的那种JSON对象。**
以下为使用办法:
```JavaScript
// AsyncShow.vue,异步请求组件
// 2s之后页面出现JSPang文字
<template>
<h1>{{ result }}</h1>
</template>
<script lang="ts">
import { defineComponent } from "vue";
// defineComponent是用来解决TypeScript情况下,传统的Vue.extends无法对组件给出正确的参数类型推断的。也就是说在TypeScript环境中如果参数类型推断不正常时,用defineComponent()组件来进行包装函数。
export default defineComponent({
setup() {
return new Promise((resolve, reject) => {
setTimeout(() => {
return resolve({ result: "JSPang" });
}, 2000);
});
},
});
</script>
// App.vue
// 可以看到Suspense是有两个template插槽的,第一个default代表异步请求完成后,显示的模板内容。fallback代表在加载中时,显示的模板内容。
<template>
<div>
<Suspense>
<template #default>
<AsyncShow />
</template>
<template #fallback>
<h1>Loading...</h1>
</template>
</Suspense>
</div>
</template>
```
运行之后,如果一切正常,你可以看到,当我们打开页面时,首先显示的是Loading,然后才会显示JSPang。也就是promise返回的结果
- 在编写异步请求组件的时候,还可以通过 `async...await`的写法,它是`promise`的语法糖
```JavaScript
// AsyncShow.vue,异步请求组件
export default defineComponent({
async setup() { //promise 语法糖 返回之后也是promise对象
const rawData = await axios.get('https://apiblog.jspang.com/default/getGirl')
return {result:rawData.data}
}
})
```
Suspense组件加载多个异步组件的场景:
```JavaScript
<Suspense>
<template #default>
// 警告:是一个实验性的特性,它的API很可能会改变slots,除非只有一个根节点
// 直接在Suspense组件下写两个异步组件会导致页面不显示
<AsyncShow></AsyncShow>
<AsyncShow2></AsyncShow2>
</template>
<template #fallback>
<div>
Loading... ---- 异步加载中
</div>
</template>
</Suspense>
// 解决办法
<template #default>
// 使用一个根节点包裹住,扩展一下,在<transition-group>组件中也是可以这样子解决
<div>
<AsyncShow></AsyncShow>
<AsyncShow2></AsyncShow2>
</div>
</template>
```
11. 处理异步请求错误
在异步请求中必须要作的一件事情,就是要捕获错误,因为我们没办法后端给我们返回的结果,也有可能服务不通,所以一定要进行捕获异常和进行处理。
在vue3.x的版本中,可以使用onErrorCaptured这个钩子函数来捕获异常。在使用这个钩子函数前,需要先进行引入
import { onErrorCaptured} from "vue";
有了onErrorCaptured就可以直接在setup()函数中直接使用了。钩子函数要求我们返回一个布尔值,代表错误是否向上传递,我们这里返回了true。
const app = {
name: "App",
components: { AsyncShow, GirlShow },
setup() {
onErrorCaptured((error) => {
console.log(`error====>`,error)
return true
})
return {};
},
};