suspense标签全局异步的处理
在 script setup 语法里面,全局是异步的,在顶级有一个全局的 async,看下面的代码
<template>
<div>{{ todos.name }}</div>
</template>
<script setup>
import axios from 'axios'
import { ref, onMounted } from 'vue'
const todos = ref([])
todos.value = await axios.get('http://127.0.0.1:3006/profile').then(res => {
return res.data
})
</script>
<style lang="scss" scoped>
</style>
- 这段代码在运行时,浏览器控制台并没有报错,但是模板里面的内容,什么内容都不会被渲染
- 通过给组件包裹一个 suspense 标签,也就是说只有的异步完成的时候,才会去渲染模板里面的内容
<template>
<div>
<suspense>
<layout />
</suspense>
</div>
</template>
-
在使用 suspense标签的时候,他提供了两个插槽,一个是默认的插槽 template #default 另一个是 template #fallback
- <template #default>,使用这个插槽,没有什么太大的区别,但是这个插槽里面必须有根元素的存在。
- <template #fallback>,在发送网络请求的时候,有的时候请求的时间过长,页面没有任何的数据,这时候这个插槽就会起到作用,也就是说在网络请求等待的时间过长的时候,这了插槽里面显示的内容,会显示在页面上,一般会在这个插槽中放一个 loading 加载的动画
<template>
<div>
<suspense>
<template #default>
<div>
<layout />
</div>
</template>
<template #fallback>loading....</template>
</suspense>
</div>
</template>
组件样式的优化
- 在vue单文件中, style标签有一个scoped属性,设置这个属性的作用就是让组件的样式只生效到当前组件上,并且他会生成一个随机的属性,css通过去属性选择器去查找这个属性,并且设置样式,当时使用css属性选择器的时候,他的查找速度会比使用类、id查找的方式会慢很多倍,如果考虑到性能的问题,建议不要使用scoped
- 还有一点就是当父组件里面引入了某一个子组件,父组件设置样式,这个样式会被继承到子组件的根元素上,可能有时候你不想继承父组件里面的样式,所以不继承的方式有两种
- 第一种:就是给子组件内部的根元素再加上一个元素去包裹,这样继承的样式会放在根元素上,不影响。
- 第二种:就是不使用scoped属性,给元素设置class这样他就不会产生这些随机的属性,即能优化css查找的速度,还能避免样式的继承
// 父组件 第二种方式
<template>
<div class="todos">
<Home />
</div>
</template>
<script setup>
import Home from './Home.vue'
</script>
<style lang="scss">
div.todos {
display: flex;
flex-direction: column;
}
</style>
// 子组件
<template>
<div class="item">
<span>测试:</span>
<input type="text" />
</div>
</template>
<style lang="scss">
div.item {
display: flex;
}
</style>
- 使用scoped之后
- 给元素加class后
nextTick
- nextTick的作用,官网:将回调推迟到下一个 DOM 更新周期之后执行。在更改了一些数据以等待 DOM 更新后立即使用它
- 在开发移动端时,可能会用到第三方的库,ly-tab、better-scroll,一些实现页面滚动的插件,他们会需要获取页面的高度,如果直接获取元素的高度可能会获取不到,会使这些插件失效,不能完成滚动,这时nextTick排上用处,在里面获取元素的高度,完成功能。
import { nextTick } from 'vue'
nextTick(() => {
// 代码块
})
useRouter or useRoue
全局路由对象与当前路由信息对象,在vue2.x 里面,通过 this访问router与route两个对象,但在vue3.x里,由于setup语法内部的代码执行的时机要在组件挂载之前执行的,所以不能通过this,获取,是拿不到的,setup语法执行的时机相当于在vue2.x 中的created生命周期钩子函数执行的时机,so在setup获取这两个对象,需要从vue 中拿到 useRouter && useRoue
import { useRouter,useRoute } from 'vue';
const route = useRoute()
const router = useRouter()
console.log(router)
console.log(route)
useStore
- useStoreAPI,用来操作Store里保存的状态值,也是在vue2.x 中通过 $store去操作状态值,但是还是那个问题就是说setup语法里面不能使用this,所以需要引入这个API
import { useStore } from 'vuex'
import { computed } from 'vue'
const store = useStore()
1. 获取store里面的state
const data = computed({
get() {
// 如果要是按照模块的方式使用的就需要
// store.state.模块名.tabsData
return store.state.tabsData
},
set(newValue) {
/* 如果你不需要设置state,那么这个set与get不用直接写,
直接在计算属性里面将获取的值return出去*/
}
})
2. 通过提交mutations去改变state的状态
store.commit('某个mutations名',传递的值)
2. 触发actions
store.dispatch('某个actions名', 参数)
- 在书写store我比较喜欢把mutations 和 actions的名字单独定义成常量,放在一个单独的文件进行管理,可能到时候我要改比较方便
defineEmits or defineProps
import { defineEmits , defineProps } from 'vue'
const emit = defineEmits(['事件1','事件2'])
const { 值1 } = defineProps({
值1:{
type: 类型
}
})
1. 推荐使用解构去拿组件传递的props值,因为在一个组件里面可能会有很多来自父组件
传递的数据,方便调用,就可以不用通过props.调用
其实在现在的版本里面是可以不需要对他们进行引入就可以使用的,所以在使用的时候直接使用即可,无需引入
递归组件
- 递归组件设置的方式一
<template>
<el-menu-item-group /> // element-plus
</template>
<script>
import { defineComponent } from 'vue'
export default defineComponent({ name: 'ElMenuItemGroup' })
</script>
- 递归组件设置的方式二
import { FooBar as FooBarChild } from './components'
- 递归组件设置的方式三,就是在设置另一个script组件
<script>
export default {
name: 'FooBarChild'
}
</script>
<script setup></script>