- 路由的变化
- 路由的使用
- 路由的history
- createMemoryHistory
- createWebHashHistory
- createWebHistory
- 组件的变化
- 异步组件
- render函数
- 异步页面
- 内置Teleport组件
- 异步组件
路由的变化
- 安装
# 在Vue3要安装路由时使用
npm i vue-router@next
yarn add vue-router@next
路由的使用
Vue2中使用路由的方法如下:
Vue3中使用路由的方法如下: ```javascript // src/router/index.js import {createRouter} from ‘vue-router’import VueRouter from 'vue-router'
// main.js import router from ‘./router’ createApp(App).use(router).mount(‘#app’)
<a name="cbi2T"></a>
#### 路由的history
在原来Vue2中,路由中原来模式的用法
```javascript
const router = new VueRouter({
mode: 'history', // hash
routes: [...]
})
而在Vue3的路由中则新增了三个函数
- createMemoryHistory
- createWebHashHistory
- createWebHistory
import { createRouter, createWebHistory } from 'vue-router'
export default createRouter({
history: createWebHistory(),
routes: [...]
})
组件的变化
在Vue3中使用异步组件的方法和Vue2有所不同。Vue3中新增了一个defineAsyncComponent
方法来返回一个异步组件。
基本用法。将回调函数传入
defineAsyncComponent
方法,并返回一个import
语句。import { defineAsyncComponent} from 'vue'
const Block = defineAsyncComponent(() => import('../components/Block.vue')) // Block就是一个异步的组件
这里回调函数返回的是一个Promise对象。
对于进阶用法。
defineAsyncComponent
也可以接受一个对象(具体见官方文档)。defineAsyncComponent({
loader: () => import(path),
loadingComponent: Loading,
errorComponent: MyError
})
其中,loader是一个函数,返回一个通过import导入组件的对象。
loadingComponent是加载时要显示的组件。
errorComponent是当抛出错误时要显示的组件。
这里看另一种写法:
defineAsyncComponent({
loader: () => import(path),
loadingComponent: Loading,
errorComponent: {
render(h) {
return h(Comp, 'error')
}
}
})
在Vue2中,render函数会有h的形参。但是在Vue3中,则将h函数从参数中去除,而是通过import {h} from 'vue'
导入并使用。所以上述代码会报错,正确的使用应该如下
import { defineAsyncComponent, h } from 'vue'
defineAsyncComponent({
loader: () => import(path),
loadingComponent: Loading,
errorComponent: {
render() {
return h(Comp, 'error')
}
}
})
一个组件可以进行异步加载,那么页面是否也可以异步加载呢?这是可以的,页面其实也是组件。但是在router中,页面的组件是这样使用的。
import Home from '../views/Home.vue'
import About from '../views/About.vue'
const routes = [
{
path: '/',
component: Home
},
{
path: '/about',
component: About
},
]
这样的页面组件还是同步的,在这段代码中,先将需要的组件import,然后将其放到router中。那么既然异步组件是通过defineAsyncComponent
包装后变为异步组件,那么页面组件也同样使用同样的方法包装后成为异步的页面组件。
const Home = getAsyncPage('../views/Home.vue')
const About = getAsyncPage('../views/About.vue')
这里getAsyncPage(path)
是一个封装好的方法,接受一个path(组件路径)并返回一个包装好的异步组件。这样就将页面组件也转为了异步的页面组件。
/**
* 生产异步页面
* @param {String} path 组件路径
*/
export function getAsyncPage (path) {
return defineAsyncComponent({
loader: async () => {
NPorgress.start()
await delay(500)
const comp = await import(path)
NPorgress.done()
return comp
},
loadingComponent: Loading, // 当Promise在pendding时显示的组件。
})
}
Teleport组件
在日常模态框的功能中,模态框组件一般都是和模态框相关的逻辑放在一起。但是这就造成了在HTML结构中,模态框相关的节点是放在相应的节点周围。
但是在模态框在HTML结构中,应该作为body的直接子元素。在Vue3中提供了一个内置组件Teleport,提供了一个to属性。to属性接受一个css选择器(如#app,body,.class)。
<Teleport to="body">
<Modal></Modal>
</Teleport>
将Modal组件包裹在Teleport中,通过to指定body,就达到了尽管在vue组件中modal和相关逻辑在一起,但是在最终HTML结构中,modal放在了body的子结点上。