Code前端首页关于Code前端联系我们

一、vue router里的is,到底是什么?

terry 2小时前 阅读数 4 #Vue
文章标签 vue router;is

不少刚接触Vue Router的同学,会疑惑「vue router is是什么?」,其实它和Vue的动态组件机制密切相关,在路由场景下能解决组件渲染、结构限制等实际问题,接下来咱们一步步拆解,从概念到用法再到避坑,把这个知识点吃透~

首先得明确:is不是Vue Router独有的API,它是Vue核心语法里「动态组件」的关键属性,在Vue中,我们用标签配合:is属性,能动态决定渲染哪个组件;而当这个逻辑和Vue Router结合时,就延伸出路由场景下的灵活用法。

举个直观例子:假设你做一个页面,要根据用户点击的导航切换不同组件,同时这些组件的切换要和路由状态关联(比如刷新页面后组件状态不变),这时候 + Vue Router的参数传递,就能完美解决。

is还有个冷门但重要的作用——突破HTML标签的结构限制,比如在

标签里,浏览器只允许、
这类标签作为子元素,如果你直接写,浏览器会把它当无效标签,导致布局乱套,这时候用,Vue就能正确识别并渲染组件,同时保证HTML结构合法。

is在vue router场景下的核心作用

理解概念后,得搞清楚它能解决哪些实际问题,下面这三类场景,是项目里最常用到的:

解决HTML结构“不兼容”问题

里做个自定义的表格单元格组件,直接写会被浏览器解析成错误结构,这时候用
,既能让Vue渲染组件,又能满足HTML的语法规则。

路由内动态切换组件

很多项目有“同一页面,不同状态渲染不同组件”的需求,比如电商的商品页,普通商品和秒杀商品结构差异大,却要复用同一个路由(/product),这时候可以用路由参数(type=seckill),再配合动态加载对应组件,不用为每种商品类型单独配路由。

结合异步组件优化性能

Vue Router支持路由懒加载,is也能和「异步组件」无缝配合,比如用:is="defineAsyncComponent(() => import('./SeckillComp.vue'))",既能动态切换组件,又能把组件代码拆分成单独的chunk,用户访问时才加载,减少首屏体积。

手把手教你用is结合vue router写代码

光说不练假把式,咱们分场景写两个实战案例,你跟着敲一遍就懂了~

案例1:路由内动态切换组件(商品页场景)

步骤1:配置路由(router.js)
先给商品页配路由,用query参数区分商品类型:

import { createRouter, createWebHistory } from 'vue-router'
const router = createRouter({
  history: createWebHistory(),
  routes: [
    {
      path: '/product',
      name: 'ProductPage',
      component: () => import('./views/ProductPage.vue'),
      // 把路由参数传给组件
      props: route => ({ type: route.query.type })
    }
  ]
})
export default router

步骤2:写ProductPage.vue
在页面里根据type参数,用is动态渲染组件:

<template>
  <div class="product-page">
    <!-- 动态组件核心:<component :is="xxx" /> -->
    <component :is="currentComp" />
  </div>
</template>
<script setup>
import { computed } from 'vue'
import { useRoute } from 'vue-router'
// 导入不同商品类型的组件
import NormalProduct from './components/NormalProduct.vue'
import SeckillProduct from './components/SeckillProduct.vue'
const route = useRoute()
// 计算属性:根据type返回对应组件
const currentComp = computed(() => {
  const type = route.query.type
  return type === 'seckill' ? SeckillProduct : NormalProduct
})
</script>

这样,当用户访问/product?type=seckill时,页面会渲染SeckillProduct;访问/product则渲染NormalProduct,路由和组件切换完美绑定~

案例2:突破HTML结构限制(表格场景)

假设要在

里用自定义组件做单元格,直接写会报错,这时候用is:

步骤1:写TableCell组件(TableCell.vue)

<template>
  <div class="table-cell">
    <p>我是自定义表格单元格,内容可以很灵活~</p>
  </div>
</template>
<style scoped>
.table-cell {
  background: #f5f5f5;
  padding: 10px;
}
</style>

步骤2:在页面里用is渲染

<template>
  <table border="1">
    <tr>
      <!-- 关键:用<td is="TableCell" /> 代替 <my-cell> -->
      <td is="TableCell"></td>
    </tr>
  </table>
</template>
<script setup>
import TableCell from './components/TableCell.vue'
</script>

这样写,浏览器会把

识别为自定义组件,既保证HTML结构合法,又能渲染组件内容和样式~

用is时容易踩的坑,怎么避?

新手用is时,这几个问题很常见,提前避坑能省不少debug时间:

组件“找不到”:未注册或导入

如果控制台报Failed to resolve component: xxx,先检查两点:

  • 组件有没有import进来?
  • 里的xxx,是不是真的指向组件(比如别写成字符串'xxx',除非组件在全局注册过)?

解决:确保组件在当前脚本里import,is绑定的是组件对象(不是字符串,除非用全局注册+字符串匹配)。

路由参数变了,组件却没刷新

比如路由从/product?type=normal跳到/product?type=seckill,但组件还是原来的,这是因为Vue Router的同一路由组件复用机制,导致组件实例没销毁重建,computed也没触发更新?

解决:用watch监听路由变化,或者把路由参数通过props传给组件,再用watch监听props变化,前面案例里用computed绑定route.query.type,其实已经是响应式的,只要路由参数变,computed会自动重新计算,组件也会刷新~

样式“不听话”:scoped导致的布局问题

如果自定义组件用了<style scoped>,在

里可能出现样式不生效(比如组件内的margin、padding被父级table样式覆盖)。

解决:可以给组件加个唯一class,用深度选择器(比如>>>/deep/)穿透scoped;或者把公共样式放到全局样式文件里。

异步组件加载失败:白屏或报错

如果用is结合异步组件(比如defineAsyncComponent),网络差时可能加载失败,页面直接白屏。

解决:给异步组件加错误处理,

import { defineAsyncComponent } from 'vue'
const AsyncComp = defineAsyncComponent({
  loader: () => import('./AsyncComp.vue'),
  errorComponent: () => import('./ErrorComp.vue'), // 加载失败时显示的组件
  timeout: 3000 // 3秒没加载完就算失败
})

这样即使加载失败,也能给用户友好提示~

实际项目里的高阶玩法

掌握基础后,这些进阶技巧能让你更“丝滑”地用is+Vue Router:

结合缓存组件状态

如果动态切换的组件需要保留状态(比如表单输入内容),可以用包裹

<template>
  <keep-alive>
    <component :is="currentComp" />
  </keep-alive>
</template>

这样切换组件时,组件实例不会销毁,状态就能保留~

路由守卫里控制组件渲染

比如某些页面需要权限,没权限时用is渲染“权限不足”组件,可以在beforeRouteEnter守卫里判断:

// 在组件内写导航守卫
import { onBeforeRouteEnter } from 'vue-router'
onBeforeRouteEnter((to, from, next) => {
  const hasPermission = checkPermission() // 自定义权限检查函数
  if (hasPermission) {
    next(vm => {
      vm.currentComp = NormalComp // 有权限渲染正常组件
    })
  } else {
    next(vm => {
      vm.currentComp = NoPermissionComp // 没权限渲染提示组件
    })
  }
})

动态组件+路由元信息(meta)

在路由配置里加meta字段,标记该路由该渲染哪个组件:

routes: [
  {
    path: '/admin',
    name: 'Admin',
    component: AdminLayout,
    meta: { targetComp: 'AdminDashboard' } // 标记要渲染的组件名
  }
]

然后在AdminLayout里用is动态渲染:

<template>
  <component :is="metaComp" />
</template>
<script setup>
import { useRoute } from 'vue-router'
import AdminDashboard from './AdminDashboard.vue'
const route = useRoute()
const metaComp = route.meta.targetComp === 'AdminDashboard' ? AdminDashboard : DefaultComp
</script>

这种方式让路由配置和组件渲染逻辑解耦,维护更方便~

看完这些,你应该对“vue router里的is”从概念到用法都有了清晰认知,简单总结下:is是Vue动态组件的“开关”,和Vue Router结合后,能解决组件动态渲染、HTML结构限制、性能优化等问题,实际项目里多练几个场景(比如动态tab、权限控制页),就能彻底掌握这个实用技巧~如果还有疑问,评论区留言,咱们继续唠~

版权声明

本文仅代表作者观点,不代表Code前端网立场。
本文系作者Code前端网发表,如需转载,请注明页面地址。

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

热门