扩展
扩展
1. 全局变量的定义
// main.js
const app = createApp(App)
app.config.globalProperties.$test = 'test'
除了setup()需要先获得实例,其他地方可以直接通过$test使用:
<tempalte>
<div>{{ $test }}</div>
</tempalte>
<script>
import { getCurrentInstance } from 'vue'
export default {
setup() {
const test = getCurrentInstance()?.appContext.config.globalProperties.$test
console.log('test===')
console.log(test)
},
}
</script>
2. teleport
组件的作用主要用来将模板内的 DOM 元素移动到其他位置。
可以应用到像 Modal,toast 等这样的元素
eg:toast
index.html
中
<div id="app"></div>
+ <div id="teleport-target"></div>
src/components/HelloWorld.vue
中,添加如下,留意 to
属性跟上面的 id
选择器一致
<button @click="showToast" class="btn">打开 toast</button>
<!-- to 属性就是目标位置 -->
<teleport to="#teleport-target">
<div v-if="visible" class="toast-wrap">
<div class="toast-msg">我是一个 Toast 文案</div>
</div>
</teleport>
import { ref } from 'vue';
export default {
setup() {
// toast 的封装
const visible = ref(false);
let timer;
const showToast = () => {
visible.value = true;
clearTimeout(timer);
timer = setTimeout(() => {
visible.value = false;
}, 2000);
}
return {
visible,
showToast
}
}
}

可以看到,使用 teleport 组件,通过 to 属性,指定该组件渲染的位置与 <div id="app"></div>
同级,也就是在 body 下,但是 teleport 的状态 visible 又是完全由内部 Vue 组件控制
3. v-model
非兼容:用于自定义组件时,v-model prop 和事件默认名称已更改:
- prop:value -> modelValue;
- event:input -> update:modelValue;
非兼容:v-bind 的 .sync 修饰符和组件的 model 选项已移除,可用 v-model 作为代替;
新增:现在可以在同一个组件上使用多个 v-model 进行双向绑定;
新增:现在可以自定义 v-model 修饰符。
在 3.x 中,自定义组件上的 v-model 相当于传递了 modelValue prop 并接收抛出的 update:modelValue 事件:
<ChildComponent v-model="pageTitle" />
<!-- 简写: -->
<ChildComponent
:modelValue="pageTitle"
@update:modelValue="pageTitle = $event"
/>
父组件
<test v-model:foo="a" v-model:bar="b"></test>
子组件
<template>
<div>
<input type="text" :value="foo" @input="$emit('update:foo',$event.target.value)" />
<input type="text" :value="bar" @input="$emit('update:bar',$event.target.value)" />
</div>
</template>
<script>
export default {
props: {
foo: String,
bar: String,
},
emits: ["update:foo", "update:bar"],
setup(props) {
return {};
},
};
</script>
4. v-slot
新指令v-slot统一slot和slot-scope指令语法
父组件
<child>
<template v-slot:one>
<div><span>菜单</span></div>
</template>
<template v-slot="user">
<ul>
<li v-for="(item, index) in user.data" :key="index">{{ item }}</li>
</ul>
</template>
<template v-slot:two="user">
<div>{{ user.data }}</div>
</template>
</child>
子组件
<div class="child">
<h3>具名插槽</h3>
<slot name="one" />
<h3>作用域插槽</h3>
<slot :data="list" />
<h3>具名作用域插槽</h3>
<slot name="two" :data="list" />
</div>
5. suspense
允许我们的应用程序在等待异步组件时渲染一些后备内容
使用场景
- 在页面加载之前显示加载动画
- 显示占位符内容
- 处理延迟加载的图像
setup生命周期函数调用了异步请求,组件标签的外部必须使用Suspense标签进行嵌套以等待异步方法的结束 => 可以进行页面的加载中的展示。同时也可以进行错误信息的页面处理
父组件
<template>
<div id="app">
<div v-if="error">{{ error }}</div>
<Suspense v-else>
<template #default>
<User />
</template>
<template #fallback>
Loading...
</template>
</Suspense>
</div>
</template>
<script>
import User from "../components/User";
import { onErrorCaptured, ref } from "vue";
export default {
components: {
User
},
setup() {
const error = ref(null);
// 捕获子组件异常时触发的函数
onErrorCaptured(e => {
error.value = e;
// 不对错误进行拦截
return true;
});
return { error };
}
};
</script>
子组件
<template>
<div>
<h1>{{ user.name }}</h1>
<h1>{{ user.age }}</h1>
</div>
</template>
<script>
export default {
async setup() {
const fetchUser = () => {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve({ name: "Carlo", age: "20" });
//reject("获取信息失败!");
}, 3000);
});
};
const user = await fetchUser();
return { user };
}
};
</script>
若子组件中有多个异步请求,则会等待所有异步方法结束,进行页面内容的加载
async setup() {
const fetchUser = () => {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve({ name: "Carlo", age: "20" });
}, 3000);
});
};
const fetchObj = () => {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve({ sex: "1" });
}, 4000);
});
};
const user = await fetchUser();
const obj = await fetchObj();
return { user, obj };
}
若页面中有多个子组件在一个suspense内
<Suspense>
<template #default>
<User />
<User1 />
</template>
<template #fallback>
Loading...
</template>
</Suspense>
控制台 会给出警告 它的API很可能会改变slots,除非只有一个根节点
- 稳定性不够根据vue-cli版本的不同会有不同的使用方式
解决方法 :增加一个跟节点
<Suspense>
<template #default>
<div>
<User />
<User1 />
</div>
</template>
<template #fallback>
Loading...
</template>
</Suspense>