稀土掘金 稀土掘金

Nuxt3入门日记(二)

上次我们讲到了为什么使用nuxt,以及nuxt的路由如何配置,nuxt相关的几个路由组件和路由相关hook的使用。
今天我们继续对路由部分做一下补充,在加入上次提到的其它文件夹中的部分内容的配置以及使用。

路由使用

接下来我将会对nuxt路由的知识点做补充,包括编程式路由,路由中间件,以及路由守卫的介绍。同时在这里将会引出nuxt的middleware相关知识,以及对前文所说的服务端渲染和客户端渲染内容做一下回忆。

编程导航式路由

上次我们在讲路由的基本配置的时候提到了使用<nuxt-link></nuxt-link> 组件进行路由传参,以及如何传入 query参数或者params参数,同时我们了解如何使用useRoute()这个hook来获取传递过来的参数。

那么大家很容易想到可以用useRouter()这个hook获取路由器实例来和vue-router一样实现编程式路由。

  <div @click="handleRouterPush" class="info">test</div>
  <script lang="ts" setup>
    const router = useRouter();
    const handleRouterPush = () => {
      router.push("/details/1");
    };
</script>

这里关于如何使用路由器实例router 去实现传参等内容就不一一赘述了,都是vue-router的相关知识。

我们发现在Nuxt里面直接使用router.push确实可以实现路由的切换,传参等操作和普通的vue项目基本没有区别,其实如果拿Nuxt做客户端渲染的话使用router 实例的方式完成项目开发。

但是Nuxt实际上给我们提供了一个编程式路由的API navigateTo 我们先来看一下该API的用法。


   <div class="cursor-pointer" @click="handleMoreRoute">更多内容无参</div>
    <div class="cursor-pointer" @click="handleMoreRoutePath">更多内容路径参</div>
    <div class="cursor-pointer" @click="handleMoreRoutePathQuery">更多内容路径参query</div>
    <div class="cursor-pointer" @click="handleMoreRouteName('content')">更多内容name content</div>
  <script lang="ts" setup>
      const handleMoreRoute = () => {
      navigateTo("/more");
    };
    const handleMoreRoutePath = () => {
      navigateTo("/more/1");
    };
    const handleMoreRoutePathQuery = () => {
      navigateTo("/more/?id=1&age=18");
    };
    const handleMoreRouteName = (name:string) => {
      navigateTo({ name ,query:{id:1,age:18}});
    };
  </script>

我们发现它和router.push的使用完全一致,那么为什么nuxt要多此一举提供这样一个API,问题就回到我们前文说的服务端渲染和客户端渲染上来了,router示例只能在客户端渲染使用,而navigateTo确实可以在服务端和客户端都使用的。而在我们的开发过程中,什么时候在做服务端渲染?

setup 中加入打印语句,会发现控制台有两次输出,第一次输出前显示‘ssr’,表明此时处于服务端渲染阶段。。

new.gif

如果我们去查看编辑器的终端

image.png 同样可以看见内容的输出,这是服务端渲染时打印的内容。

Nuxt里面我们如何判断区别是服务端渲染阶段还是客户端渲染阶段呢?

主要使用的方法有两个,一个是直接 通过import.meta

    if (import.meta.server) {
      console.log("Server side");
    } else {
      console.log("client side");
    }
      if (import.meta.client) {
      console.log("client side");
    } else {
      console.log("Server side");
    }

另一种是nuxt配置文件里面 Nuxt 配置中有一个运行时配置 runtimeConfig 可用于对外暴露值

//nuxt.config,ts
export default defineNuxtConfig({
  devtools: { enabled: true },
  runtimeConfig: {
    secretKey: 11111111,
    public: {
      apiBase: process.env.NUXT_PUBLIC_API_BASE
    }
  },
  })
 //index.vue
 const runtimeConfig = useRuntimeConfig();//使用 useRuntimeConfig 获取配置里面的值
 console.log(runtimeConfig.secretKey, "secretKey");
 console.log(runtimeConfig.public.apiBase, "apiBase");

配置完成之后我们打印一下配置信息 image.png

我们可以看到在ssr阶段我们可以拿到两个值,而在客户端渲染的阶段我们只能获取到public的值,所以我们可以直接根据能否拿到public以外的值来判断当前是什么端。

回到我们刚刚使用的navigateTo API ,如果按照下方代码,我们会发现router.push并不会执行,因为在服务端渲染阶段router是不存在,但是将其换成navigateTo 就可以正常实现页面路由的更新,同样在客户端渲染阶段,将下方的navigateTo注释解除,也可以实现跳转。

if (import.meta.server) {
  console.log("Server side");
    router.push("/details/1");
} else {
  // navigateTo("/more");
  console.log("client side");
}

更多情况下使用navigateTo Api是用户打开外部链接的

// 默认禁止打开外部,需设置'external'参数为'true',不然会报错
// await navigateTo('https://nuxt.com', {
//   external: true
// })

那么关于navigateTo就提及到这里,关于更多属性与方法比如open 就由大家自己根据需要查阅官方文档使用。

路由常用的部分还剩下最后一个知识点也就是我们在Vue里面常用的路由守卫,在vue里面我们可以通过beforeEach 添加前置路由守卫,或者其它的方法添加全局解析守卫或者后置守卫。但是在Nuxt里面实现前置守卫我们需要引入一个新的知识也就是中间件。

middleware和路由中间件

Nuxt 提供了中间件来在导航到特定路线之前运行代码,我们可以通过定义中间件来实现对特定或者全局页面之前需要运行的代码。

那么接下来我会告诉大家在 nuxt 里面如何定义一个中间件以及如何使用中间件。

首先我们可以在页面直接定义中间件并使用,我们可以在下方代码的funtion里面写任意你想在进入该路由之前执行的代码。

//index.vue
definePageMeta({
  middleware: [
    function (to) {
      console.log("middleware", to.path);
    }
  ]
})

或者我们可以在nuxt 的约定文件夹middleware下面定义

image.png

然后我们可以选择在需要使用的页面里面设置该中间件

//content.vue
definePageMeta({
  middleware: ['test']
});

如果希望设置全局的中间件而不是一个个引入,我们只需要在给中间件取名称的时候加上global就是全局中间件

middleware/
--- once.global.ts

这样中间件就会在全部路由都生效了。

大致了解了如何设置中间件以及在对于页面设置中间件接下来就来看下如何如何在中间件中实现路由守卫吧

通过middleware实现路由守卫

通常我们在项目中设置路由守卫的目的都是为了区分用户,比如登录用户和未登录用户,登录用户里面又有普通用户、vip用户、管理员用户等等。

下面我带大家实现一个简单的中间件守卫

// once.global.ts
export default defineNuxtRouteMiddleware((to, from) => {
  // 假设存储 token 的地方
  const token = useCookie('token');
  const userRole = useCookie('userRole');

  // 白名单路由,不需要 token 即可访问
  const whiteList = ['/login', '/register'];

  if (whiteList.includes(to.path)) {
    // 如果是白名单路由,直接放行
    return;
  }

  if (!token.value) {
    // 没有 token,重定向到登录页面
    return navigateTo('/login');
  }

  if (userRole.value === 'admin') {
    // 管理员权限,可以访问特定的管理页面
    if (to.path.startsWith('/admin')) {
      return;
    } else {
      // 非管理页面,重定向到管理员首页
      return navigateTo('/admin/dashboard');
    }
  } else if (userRole.value === 'user') {
    // 普通用户权限,不能访问管理页面
    if (!to.path.startsWith('/admin')) {
      return;
    } else {
      // 尝试访问管理页面,重定向到用户首页
      return navigateTo('/user/dashboard');
    }
  }
});

具体的权限设计可以根据业务场景来,比如设置在definePageMeta 里或者保存在 pinia 这种全局状态管理器里面。

nuxt其它约定配置的介绍

上文以及前文已经提到了Nuxt文件目录里面的pagesmiddleware,想必大家看过之后已经能够学会使用Nuxt路由的配置和客户端中间件的使用了接下来我们继续对其它的约定文件夹做介绍

nuxt自动导入

说完路由相关信息我们就回到组件化开发下内容,在介绍Nuxt组件化开发之前,我们先来说一下Nuxt的自动导入,我们在Vue的页面中使用组件需要导入组件,或者在全局挂载组件才可以使用。

但是Vue只要在components文件夹下面定义好组件就可以直接在任意页面和组件使用,不需要再做导入操作,不仅仅是自定义组件,Nuxt特有的组件,vue特有的api,以及路径/composables 路径/utils等等。

参照前文的目录结构图,比如上面提到的middleware内部定义的内容基本都是会被Nuxt做自动导入的,下面我们来看如何使用自定义导入来做自定义组件的使用

自定义组件

组件化开发是我们使用vue这类框架的核心,我们看一下在Vue里面如何实现自定义组件。前面提及了我们需要把组件放到components文件夹下

components/
--- Header.vue 

创建完成后,开始组件内容的编写

image.png 定义完成Header组件后可以在任意页面或者任意组件内容直接使用它

image.png

我们来看一下页面效果

image.png

组件的定义和使用方式就是如上所述。

组件的命名约定

如果我们不是在components 的根目录文件下定义内容的话,而是存在着嵌套关系比如下方所示

--| top/ 
----| full/
------| Tip.vue

那么组件名称将会基于路径和文件名以大驼峰方式连起来,比如上面的top/full/Button.vue注册名称将会是TopFullTip,使用如下:

image.png

布局系统

nuxt针对页面结构的复用性还提供了layout配置,前文的layouts文件夹就是用来完成该项配置的,我们在layouts文件夹下面新建default.vue文件作为默认layout配置。

layouts/
--- default.vue 
--- none.vue

当然你可以取任何名字,但是当使用其它命名layout时需要在页面做相应的配置。

/*default.vue*/
<template>
  <div>
    <header>头部</header>
    <nav>导航栏</nav>
    <slot />
    <footer>底部</footer>
  </div>
</template>

/*none.vue*/
<template>
  <div>
    <slot />
  </div>
</template>

我们查看页面

image.png

进入其它路由

image.png

发现layout已经发挥作用,上文提到了设置其它命名layout,只需要在对应的路由页面配置definePageMeta设置其layout为你定义的其它layout

上面我定义的none.vuelayout就是一个空白的layout,大家可以根据内容定义不同的layout在不同页面阶段,双端应用区分移动和pc的不同layout等等。

definePageMeta({
  title: 'content',
  layout: 'none' //配置你的layout文件名称
})

今天跟大家的讲解内容就到这里了,下一次文章我会告诉大家如何在Nuxt项目里面引入UI库,以及引入Tailwindcss,并展开对Nuxt请求数据方法做介绍。

玻璃钢生产厂家厦门找玻璃钢孔子雕塑丽水公园玻璃钢雕塑制作湖北创意玻璃钢雕塑市场沈阳标杆商场商业美陈方案商场的美陈一般是谁负责的兴安盟玻璃钢雕塑公司温州玻璃钢雕塑定做荆门玻璃钢雕塑造型贴金镂空校园玻璃钢雕塑定做厂家深圳走廊商场美陈价钱河南装饰商场美陈怎么样南昌玻璃钢雕塑报价济南商场美陈研发公司广东玻璃钢仿真雕塑吉林环保玻璃钢雕塑生产厂家江门玻璃钢雕塑有哪些河南肖像玻璃钢彩绘雕塑定制玻璃钢佛像雕塑怎么做玻璃钢金属雕塑企业商场玻璃钢花盆定制江门玻璃钢透光雕塑现货批发玻璃钢雕塑择优推荐包头玻璃钢雕塑出租永济玻璃钢十二生肖雕塑家装美陈玻璃钢雕塑玻璃钢雕塑哪里产的好天津多彩玻璃钢雕塑优势玻璃钢校园雕塑多少钱小品玻璃钢人物雕塑手工制作河南玻璃钢人物雕塑价格香港通过《维护国家安全条例》两大学生合买彩票中奖一人不认账让美丽中国“从细节出发”19岁小伙救下5人后溺亡 多方发声单亲妈妈陷入热恋 14岁儿子报警汪小菲曝离婚始末遭遇山火的松茸之乡雅江山火三名扑火人员牺牲系谣言何赛飞追着代拍打萧美琴窜访捷克 外交部回应卫健委通报少年有偿捐血浆16次猝死手机成瘾是影响睡眠质量重要因素高校汽车撞人致3死16伤 司机系学生315晚会后胖东来又人满为患了小米汽车超级工厂正式揭幕中国拥有亿元资产的家庭达13.3万户周杰伦一审败诉网易男孩8年未见母亲被告知被遗忘许家印被限制高消费饲养员用铁锨驱打大熊猫被辞退男子被猫抓伤后确诊“猫抓病”特朗普无法缴纳4.54亿美元罚金倪萍分享减重40斤方法联合利华开始重组张家界的山上“长”满了韩国人?张立群任西安交通大学校长杨倩无缘巴黎奥运“重生之我在北大当嫡校长”黑马情侣提车了专访95后高颜值猪保姆考生莫言也上北大硕士复试名单了网友洛杉矶偶遇贾玲专家建议不必谈骨泥色变沉迷短剧的人就像掉进了杀猪盘奥巴马现身唐宁街 黑色着装引猜测七年后宇文玥被薅头发捞上岸事业单位女子向同事水杯投不明物质凯特王妃现身!外出购物视频曝光河南驻马店通报西平中学跳楼事件王树国卸任西安交大校长 师生送别恒大被罚41.75亿到底怎么缴男子被流浪猫绊倒 投喂者赔24万房客欠租失踪 房东直发愁西双版纳热带植物园回应蜉蝣大爆发钱人豪晒法院裁定实锤抄袭外国人感慨凌晨的中国很安全胖东来员工每周单休无小长假白宫:哈马斯三号人物被杀测试车高速逃费 小米:已补缴老人退休金被冒领16年 金额超20万

玻璃钢生产厂家 XML地图 TXT地图 虚拟主机 SEO 网站制作 网站优化