基于nuxt3创建vue3 ssr项目知识和问题汇总


一、问题汇总

1.控制台中报错 Hydration node mismatch: - Client vnode: div - Server rendered DOM

该问题其实是由于在开发阶段本地服务器的代码与浏览器的代码不一致导致的问题,可以执行一次 build 命令,可以解决该问题,实际到部署之后并未复现该问题。

2.Nuxt3+Vue3 + Element-plus 打包后报错 @popperjs/core

问题:

更新 Element-plus 后,运行时需要安装 @popperjs/core 依赖。
如果正常执行 npm install @popperjs/core ,那么,打包时,就会出现下面报错。

解决:

node_modules 删除,在 package.json@popperjs/core 版本号改为 "@popperjs/core": "npm:@sxzz/popperjs-es@^2.11.7"(esm 的包)重新 npm install,即可。

参考 element-plus/package.json

3.npm i 报错

PS C:\Users\Administrator\Desktop\nuxt3-blog> npm i @nuxtjs/composition-api@0.34.0
npm error code ERESOLVE
npm error ERESOLVE unable to resolve dependency tree
npm error
npm error While resolving: nuxt-app@1.0.0
npm error Found: nuxt@3.15.4
npm error node_modules/nuxt
npm error   dev nuxt@"^3.15.4" from the root project
npm error
npm error Could not resolve dependency:
npm error peer nuxt@"^2.17.3" from @nuxtjs/composition-api@0.34.0
npm error node_modules/@nuxtjs/composition-api
npm error   @nuxtjs/composition-api@"0.34.0" from the root project
npm error
npm error Fix the upstream dependency conflict, or retry
npm error this command with --force or --legacy-peer-deps
npm error to accept an incorrect (and potentially broken) dependency resolution.

原因:
这个错误是由于你正在尝试安装的 @nuxtjs/composition-api@0.34.0 版本与当前的 nuxt@3.15.4 版本不兼容。@nuxtjs/composition-api 需要 nuxt@^2.17.3,而你使用的是 Nuxt 3

要解决这个问题,你有以下几种选择:

  1. 升级到 Nuxt 3Composition APINuxt 3 已经内置了 Composition API,因此不需要单独安装 @nuxtjs/composition-api。你可以直接使用 Nuxt 3Composition API 功能。

  2. 降级 Nuxt 版本:如果你必须使用 @nuxtjs/composition-api,你可以考虑将 Nuxt 降级到 2.x 版本,但这可能不适合你的项目。

4.控制台中报错 Deprecation Warning [import]: Sass @import rules are deprecated and will be removed in Dart Sass 3.0.0.

20 │ @import "./global.scss";
   │         ^^^^^^^^^^^^^^^
   ╵
    src\assets\css\theme\common.scss 20:9  @import
    src\assets\css\global-common.scss 23:9        @use
    src\components\outline.vue 1:1         root stylesheet
Deprecation Warning [import]: Sass @import rules are deprecated and will be removed in Dart Sass 3.0.0.
More info and automated migrator: https://sass-lang.com/d/import

这个警告是由于你在使用 Sass 时使用了 @import 语句,而 @importDart Sass 3.0.0 中将被弃用。建议你使用 @use@forward 来替代 @import。这样可以提升代码的模块化和可维护性。

以下是如何进行迁移的基本步骤:

  1. 使用 @use 替代 @import

如果你有一个文件 global.scss,你可以在需要引入的地方使用 @use 语句。例如:

// 原来的写法
@import "./global.scss";

// 替换为
@use "./global.scss";
  1. 调整命名空间

使用 @use 时,所有引入的样式都会被放入一个命名空间中。你可以通过指定命名空间来使用这些样式。例如:

// 使用命名空间
@use "./global.scss" as *; // 将所有样式引入当前作用域
  1. 更新引用

如果你的 global.scss 文件中有变量、混合宏或函数等,你需要在使用它们时加上命名空间,除非你使用 as *

  1. 检查项目中的所有 @import

确保你的项目中没有其他地方使用 @import,并将其全部替换为 @use@forward

warning:@use rules must be written before any other rules. 使用@use 时,所有的@use 规则必须写在其他规则之前。

更多关于如何迁移的信息可以参考 Sass 官方文档。这样可以确保你的代码在未来的版本中不会因为弃用而出现问题。

5.解决 navigator.mediaDevices 报错问题

背景:
项目中使用电脑摄像头拍照,调用 navigator.mediaDevices 方法,报错。
原因:

navigator.mediaDevices 在目前以下情况中可以正常获取到

  1. 地址为 localhost://访问
  2. 协议为 https
  3. 为文件访问 file://

测试环境和生产环境使用的都是 http 协议,因此无法调用
解决方法:

  1. 本地使用localhost:// 访问
  2. 线上采用 https 方案

6.提示new dependencies optimized

具体如下:

下午7:01:09 [vite] ✨ new dependencies optimized: element-plus/es/components/message-box/style/index
下午7:01:09 [vite] ✨ optimized dependencies changed. reloading
下午7:01:23 [vite] ✨ new dependencies optimized: element-plus/es/components/form/style/index
下午7:03:57 [vite] vite.config.ts changed, restarting server...

new dependencies optimized信息通常出现在使用 Vite 进行项目开发时,表示 Vite 正在优化新的依赖项。‌

背景信息:

Vite 是一个现代化的前端构建工具,它利用浏览器原生支持的 ES 模块功能,实现了快速的冷启动和即时模块热更新。Vite 通过按需加载模块,避免了传统构建工具如 Webpack在启动时需要加载所有模块的缺点,从而提高了开发效率。然而,按需加载也带来了一些问题,例如在开发过程中可能会看到大量的依赖项被优化,导致页面频繁重新加载 ‌

具体表现:

在开发过程中,当Vite检测到新的依赖项时,会在控制台输出new dependencies optimized的信息。例如,当使用Element-Plus组件库时,Vite会优化这些依赖项,并在控制台显示相关信息,如new dependencies optimized: element-plus/es/components/divider/style/css。这些信息表明Vite正在处理新的依赖项,并进行优化 ‌

优化方法:

为了减少new dependencies optimized信息的出现频率,可以尝试以下优化方法:

  1. 全局加载组件:在开发环境下,可以暂时全局加载组件,避免按需加载带来的频繁重新加载问题。在打包时再执行按需加载。

  2. 优化 Vite 配置:可以通过修改 vite.config.ts 文件,包含更多的依赖项路径,减少优化时的重新加载次数。例如,可以通过 fs 模块遍历 node_modules/element-plus/es/components 目录,将所有相关的依赖项包含进优化配置中。

具体代码如下:

// vite.config.ts
// 需要引入fs

import { defineConfig, loadEnv } from "vite";
import { resolve } from "path";
import fs from "fs";

export default ({ mode }) => {
  process.env = { ...process.env, ...loadEnv(mode, process.cwd()) }; //生成包括自定义的环境变量
  //解决optimized dependencies changed. reloading
  const optimizeDepsElementPlusIncludes: Array<string> = ["element-plus/es"];
  if (process.env.VITE_ENV === "development") {
    fs.readdirSync("node_modules/element-plus/es/components").map((dirname) => {
      fs.access(
        `node_modules/element-plus/es/components/${dirname}/style/css.mjs`,
        (err) => {
          if (!err) {
            optimizeDepsElementPlusIncludes.push(
              `element-plus/es/components/${dirname}/style/css`
            );
          }
        }
      );
    });
  }

  return defineConfig({
    optimizeDeps: {
      include: optimizeDepsElementPlusIncludes,
      // exclude: ["element-plus"],//反向使用,更简单
    },
  });
};

更多查看:

7.linux 修改环境变量后需要重启吗

Linux 系统中,修改环境变量通常不需要重启。环境变量是一种用于存储系统配置信息的变量,它们控制着系统的行为和应用程序的执行方式。当你修改了环境变量,系统会立即生效,无需重启。

当你修改环境变量时,系统会在当前会话中立即使用新的值。这意味着你可以立即在终端中使用新的环境变量设置,而不需要重新启动系统。

需要注意的是,修改环境变量只会在当前会话中生效。如果你希望新的环境变量设置在所有会话中都生效,你需要将其添加到适当的配置文件中。
在大多数 Linux 发行版中,常见的配置文件是~/.bashrc~/.bash_profile(对于个人用户)以及/etc/profile 或/etc/environment(对于系统级用户)。你可以使用文本编辑器打开这些文件,并在其中添加或修改环境变量的设置。

在修改配置文件后,你需要重新加载配置文件或重新启动终端,以使新的环境变量设置生效。你可以使用以下命令来重新加载配置文件:

#修改profile
source /etc/profile

#修改.bashrc
source ~/.bashrc
#或者使用以下命令重新启动终端:
exec bash

这样,新的环境变量设置将在所有终端会话中生效。

二、知识汇总

1.vite build 和 preview 区别

Vite 是一个现代化的前端构建工具,它提供了快速的开发服务器和热更新功能,以及高效的生产环境构建。在 Vite 中,vite buildvite preview 是两个常用的命令,它们各自有不同的功能和用途。

1.vite build

vite build 命令用于为生产环境构建项目。当你准备好将你的项目部署到生产环境时,你会使用这个命令。它会执行以下操作:

编译和优化:Vite 会使用 Esbuild 或其他工具来编译和优化你的代码,包括 JavaScriptCSS、图片等资源。
生成输出:编译后的文件会被输出到一个指定的目录(通常是 /dist),这些文件是优化过的,适合在生产环境中使用。
代码分割:Vite 会根据你的代码依赖关系进行代码分割,以减少初始加载时间并提高性能。

2.vite preview

vite preview 命令用于本地预览生产构建产物。在你使用 vite build 命令生成了生产环境的构建产物后,你可以使用 vite preview 命令来启动一个本地服务器,该服务器会从 /dist 目录提供预览服务。这允许你在将项目部署到生产环境之前,在本地预览构建后的效果。

使用 vite preview 的好处包括:

快速预览:无需将构建产物上传到远程服务器,即可在本地快速预览。
模拟生产环境:由于 vite preview 使用的是生产环境的构建产物,因此它可以模拟生产环境的加载速度和性能。
方便调试:在预览过程中,如果发现任何问题或需要调整的地方,你可以立即回到开发环境进行修改,然后重新构建和预览。

3.总结

vite build:用于为生产环境构建项目,生成优化后的代码和资源。
vite preview:用于本地预览生产构建产物,允许在部署前在本地查看构建后的效果。
在使用这两个命令时,请确保你已经安装了 Vite 并正确配置了项目。同时,注意在生产环境中部署时,可能需要额外的配置和步骤来确保项目的安全和性能。

2.SSR 模式下存在 2 种打包方式

nuxt.jsvue SSR 框架。SSR 给前端带来的主要受益在于更快的首页加载和 SEO 友好。

Nuxt.js 支持 SPA ,但主要以 SSR 模式为主。

SSR 模式下存在 2 种打包方式,分别是 npm run buildnpm run generate。那这 2 种打包有何区别?

1.build

一般情况下,build 打包用的更多。build 打包生成的 .nuxt 文件,发布时,需要拷贝 node_modules 等文件/文件夹,一般使用 node.js 环境下的 pm2 运行发布。

需要注意:

  • build 模式下发包发布,发布时需要将 .nuxtstaticnode_modules 等文件夹,以及 package.jsonnuxt.config.js 等文件拷贝出来,使用 pm2 启动运行发布。

2.generate

generate 打包用于将首页静态化(首页的 nuxt-link 也会被静态化),打包后生成 dist 文件夹(类似于 vue 一般性打包)。发布时,只需要将 dist 文件夹发布即可(同 vue 项目发布)。

需要注意:

  • 当首页内容发生变化时,需要重新 generate 打包发布
  • 打包生成的文件仍需要容器(如 Nginx)部署方可正常访问
  • 打包过程中需要访问 API 后台获取数据

3.sass 和 node-sass 的区别

sassnode-sass 都是用于编译 Sass(一种流行的 CSS 预处理器)到 CSS 的库,但它们有一些关键区别。

1. 实现

  • node-sass:
    • node-sass 是 LibSass(SassC/C++ 实现)的 Node.js 绑定。
    • 因为是用 C/C++ 编写的,所以通常编译和运行速度都很快。
    • 可能会遇到平台相关的问题,特别是在安装和构建时。
  • sass(也称为 Dart Sass):
    • Dart SassSass 的官方 Dart 实现。
    • node-sass 切换到 Dart Sass 通常只需改变安装的包名。
    • Dart Sass 的目的是完全符合 Sass 的原始语法,并成为所有未来开发的首选版本。

2. 兼容性

  • node-sass:
    • 可能不会总是与 Sass 的最新特性保持同步。
    • 在某些系统上可能会遇到编译问题。
  • sass:
    • 由于它是官方维护的版本,所以通常会更快地支持新特性和修复错误。
    • 作为纯 JavaScript 包,兼容性通常更好。

3. 维护状态

  • node-sass:
    • 自 2020 年后,node-sass的维护已逐渐减少。
    • 社区可能会继续支持,但官方推荐使用 Dart Sass
  • sass:
    • 作为官方版本,持续得到维护和更新。

4.总结

如果你正在开始一个新项目或考虑迁移现有项目,推荐使用 sassDart Sass),因为它是官方维护的版本,并且在兼容性和未来特性支持方面可能会更可靠。如果你的项目已经使用了 node-sass 并且没有遇到问题,那么迁移可能不是必需的,但仍然值得考虑,特别是如果你想要利用 Sass 的最新特性。

sass-loader: 这是一个 Webpack 加载器,用于将 Sass 语言编写的样式文件编译成 CSS 文件。

Nuxt 会按照约定,带有 .client 后缀的文件,会被设置成在客户端渲染。比如 elment-plus.tselement-plus.client.ts

Nuxt3 默认首屏 SSR,由服务端渲染,可以通过配置 ssr:false 来取消服务端渲染。

// nuxt.config.ts
export default defineNuxtConfig({
  devtools: { enabled: true },
  // ssr:false, //页面全部为客户端渲染
  routerRules: {
    // 指定路由页面为客户端渲染
    "/home": {
      ssr: false,
    },
  },
});

根据 vue 的声明周期,只有 setupbeforeCreateCreated 里的内容会在服务端执行,所以如果是首屏服务端渲染时,需要将获取数据方法写到这几个生命周期之中

Nuxt3 有封装好的 $fetch 方法做数据请求,可以不需要引入第三方 axios 或者 fetch 做数据请求,否则可能会出现多个请求数据混乱问题。

4.使用字体

将本地字体文件放在 ~/public/ 目录中,例如~/public/fonts。然后可以在样式表中使用 url() 引用它们。

@font-face {
  font-family: "FarAwayGalaxy";
  src: url("/fonts/FarAwayGalaxy.woff") format("woff");
  font-weight: normal;
  font-style: normal;
  font-display: swap;
}

项目中使用@keyframes无效的问题,
样式本身是行内模式,即不是display: block;inline-blockdisplay: flex;
或是给父盒子添加一个一个display: flex;

nuxt3 里不能直接用 windowdocument 这种客户端api,在使用前,要用 process.client||process.server 来判断环境,否则会报错。

if (process.client) {
  window.localStorage.getItem("test");
}

5.前端开发中的页面渲染与页面水合有何不同

页面渲染页面水合是前端开发中的两个重要概念,它们在实现页面的动态性和交互性上有一定的区别。

页面渲染是指将 HTMLCSSJavaScript 代码转换为可见的网页的过程。在这个过程中,浏览器接收到服务器发送的 HTML 文件后,会解析并执行其中的 JavaScript 代码,同时应用 CSS 样式,最终生成用户可以看到的页面。这个过程是由浏览器完成的,因此也被称为客户端渲染Client-side Rendering,CSR)。

页面水合(也称为页面 hydration)则是指将服务器端渲染(Server-side Rendering,SSR)的 HTML 发送到客户端后,通过 JavaScript 代码将静态的 HTML 转换为具有交互性动态性的页面的过程。在这个过程中,客户端接收到服务器发送的 HTML 文件后,会通过 JavaScript 代码注入到页面中,从而添加交互性和其他动态功能。这个过程是由 JavaScript 代码完成的,因此也被称为页面水合。

总的来说,页面渲染和页面水合的主要区别在于:页面渲染是由浏览器解析 HTMLCSSJavaScript 代码并生成可见的页面,而页面水合是由 JavaScript 代码将静态的 HTML 转换为具有交互性和动态性的页面。

6.useFetch

1.参数

  • URL:要获取的 URL。

  • Options(扩展自 unjs/ofetch 选项和 AsyncDataOptions):

    • method:请求方法。
    • query:使用ufo将查询搜索参数添加到 URL。
    • paramsquery的别名。
    • body:请求体 - 自动转换为字符串(如果传递的是对象)。
    • headers:请求头。
    • baseURL:请求的基本 URL。

所有的 fetch 选项都可以给定computedref值。如果它们被更新,将自动进行新的请求。

  • Options(来自 useAsyncData ):
    • key:一个唯一的键,用于确保数据获取可以在请求之间正确去重。如果未提供,将根据使用useAsyncData的静态代码位置生成。
    • server:是否在服务器上获取数据(默认为true)。
    • lazy:是否在加载路由后解析异步函数,而不是阻止客户端导航(默认为false)。
    • immediate:如果设置为false,将阻止立即发出请求(默认为true)。
    • default:一个工厂函数,用于设置data的默认值,在异步函数解析之前使用 - 与lazy: trueimmediate: false选项一起使用。
    • transform:在解析后可以用于更改handler函数结果的函数。
    • pick:仅从handler函数结果中选择指定的键。
    • watch:监听一组响应式源,并在它们发生变化时自动刷新获取的结果。默认情况下,会监听 fetch 选项和 URL。您可以通过使用watch: false来完全忽略响应式源。结合immediate: false,可以实现完全手动的useFetch
    • deep:以深层 ref 对象的形式返回数据(默认为true)。可以将其设置为false,以在浅层 ref 对象中返回数据,如果您的数据不需要深层响应,则可以提高性能。

如果您将函数或 ref 作为url参数,或者如果您将函数作为options参数的参数传递给useFetch调用,即使选项似乎相同,该调用也不会与代码库中的其他useFetch调用匹配。如果您希望强制匹配,可以在options中提供自己的键。

2.返回值

  • data:传入的异步函数的结果。
  • pending:一个布尔值,指示数据是否仍在获取中。
  • refresh/execute:一个可以用于刷新handler函数返回的数据的函数。
  • error:如果数据获取失败,则为错误对象。
  • status:表示数据请求的状态的字符串(”idle”、”pending”、”success”、”error”)。

默认情况下,Nuxt 会等待refresh完成后才能再次执行。

如果您没有在服务器上获取数据(例如,使用server: false),那么直到水合完成之前,数据将不会被获取。这意味着即使在客户端上等待useFetchdata也将在<script setup>中保持为 null。

7.http 中 body、query 和 params 的区别

在路由中,参数可以通过不同的方式传递,包括 bodyqueryparams。这些参数在使用时有一些区别:

  • @Body Body 参数是通过请求的主体部分传递的数据。通常用于传递较大的数据,例如 JSONXML 格式的数据。在 HTTP 请求中,Body 参数通常与 POSTPUT 方法一起使用。
  • @Query Query 参数是通过 URL 的查询字符串传递的数据。查询字符串是 URL 中问号后面的部分,包含了键值对的形式。例如,对于 URL http://example.com/search?keyword=apple ,查询参数是 keyword=appleQuery 参数通常用于传递较小的数据,例如搜索关键字、过滤条件等。
  • @Params Params 参数是通过 URL 路径的一部分传递的数据。通常用于标识资源的唯一性或层级关系。例如,对于 URL http://example.com/users/123 ,其中的 123 就是一个 Params 参数,用于标识用户 ID123 的用户。Params 参数通常用于 RESTful 风格的 API 中。

8.vue3 中 markRaw 的使用

作用:将一个对象标记为不可以被转化为代理对象。返回该对象本身。

应用场景:

  1. 有些值不应被设置成响应式时,例如复杂的第三方类库等
  2. 当渲染具有不可变数据源的大列表时,跳过响应式转换可以提高性能
  3. 在动态渲染组件的时候我们就可以使用 markRaw 包裹。

9.definePageMeta

1.参数

definePageMeta(meta: PageMeta) => void

interface PageMeta {
    validate?: (route: RouteLocationNormalized) => boolean | Promise<boolean> | Partial<NuxtError> | Promise<Partial<NuxtError>>
    redirect?: RouteRecordRedirectOption
    name?: string
    path?: string
    alias?: string | string[]
    pageTransition?: boolean | TransitionProps
    layoutTransition?: boolean | TransitionProps
    key?: false | string | ((route: RouteLocationNormalizedLoaded) => string)
    keepalive?: boolean | KeepAliveProps
    layout?: false | LayoutKey | Ref<LayoutKey> | ComputedRef<LayoutKey>
    middleware?: MiddlewareKey | NavigationGuard | Array<MiddlewareKey | NavigationGuard>
    scrollToTop?: boolean | ((to: RouteLocationNormalizedLoaded, from: RouteLocationNormalizedLoaded) => boolean)
    [key: string]: unknown
}

2.元数据的对象

  • meta:类型 PageMeta,接受以下页面元数据的对象:
    • name:类型 string
      • 你可以为此页面的路由定义一个名称。默认情况下,名称是根据pages/目录内的路径生成的。
    • path:类型 string
      • 如果你有一个比文件名更复杂的模式,你可以定义一个路径匹配器。
    • alias:类型 string | string[]
      • 记录的别名。允许定义额外的路径,这些路径将像记录的副本一样工作。允许使用类似/users/:id/u/:id的路径简写。所有的aliaspath值必须共享相同的参数。
    • keepalive:类型 boolean| KeepAliveProps
      • 在切换路由或使用KeepAliveProps时,设置为true以保留页面状态,或进行精细控制。
    • key:类型 false | string | ((route: RouteLocationNormalizedLoaded) => string)
      • 当你需要更多地控制何时重新渲染``组件时,设置key值。
    • layout:类型 false | LayoutKey | Ref | ComputedRef
      • 为每个路由设置静态或动态布局的名称。如果需要禁用默认布局,可以将其设置为false
    • layoutTransition:类型 boolean | TransitionProps
      • 设置当前布局应用的过渡名称。你也可以将此值设置为false以禁用布局过渡。
    • middleware:类型 MiddlewareKey | NavigationGuard | Array
      • definePageMeta内直接定义匿名或命名中间件。了解更多关于路由中间件的信息。
    • pageTransition:类型boolean | TransitionProps
      • 设置当前页面应用的过渡名称。你也可以将此值设置为false以禁用页面过渡。
    • redirect:类型RouteRecordRedirectOption
      • 如果直接匹配路由,将重定向到何处。重定向发生在任何导航守卫之前,并触发以新目标位置进行的新导航。
    • validate:类型 (route: RouteLocationNormalized) => boolean | Promise | Partial | Promise>
      • 验证给定的路由是否可以使用此页面有效地呈现。如果有效,则返回true,否则返回false。如果找不到其他匹配,这将意味着 404。你还可以直接返回一个带有statusCode/statusMessage的对象,以立即以错误响应(不会检查其他匹配)。
    • scrollToTop:类型 boolean | (to: RouteLocationNormalized, from: RouteLocationNormalized) => boolean
      • 告诉 Nuxt 在渲染页面之前是否滚动到顶部。如果你想覆盖 Nuxt 的默认滚动行为,可以在~/app/router.options.ts中进行设置(参见文档)。
    • [key: string]:类型 any
      • 除了上述属性外,你还可以设置自定义元数据。你可能希望以类型安全的方式通过扩充meta对象的类型来实现。

10.navigateTo 源码解析

export const navigateTo = (to, options) => {
  if (!to) {
    to = "/";
  }
  const toPath =
    typeof to === "string"
      ? to
      : withQuery(to.path || "/", to.query || {}) + (to.hash || "");
  if (options?.open) {
    if (import.meta.client) {
      const { target = "_blank", windowFeatures = {} } = options.open;
      const features = Object.entries(windowFeatures)
        .filter(([_, value]) => value !== void 0)
        .map(([feature, value]) => `${feature.toLowerCase()}=${value}`)
        .join(", ");
      open(toPath, target, features);
    }
    return Promise.resolve();
  }
  const isExternal =
    options?.external || hasProtocol(toPath, { acceptRelative: true });
  if (isExternal) {
    if (!options?.external) {
      throw new Error(
        "Navigating to an external URL is not allowed by default. Use `navigateTo(url, { external: true })`."
      );
    }
    const protocol = parseURL(toPath).protocol;
    if (protocol && isScriptProtocol(protocol)) {
      throw new Error(`Cannot navigate to a URL with '${protocol}' protocol.`);
    }
  }
  const inMiddleware = isProcessingMiddleware();
  if (import.meta.client && !isExternal && inMiddleware) {
    return to;
  }
  const router = useRouter();
  const nuxtApp = useNuxtApp();
  if (import.meta.server) {
    if (nuxtApp.ssrContext) {
      const fullPath =
        typeof to === "string" || isExternal
          ? toPath
          : router.resolve(to).fullPath || "/";
      const location2 = isExternal
        ? toPath
        : joinURL(useRuntimeConfig().app.baseURL, fullPath);
      const redirect = async function (response) {
        await nuxtApp.callHook("app:redirected");
        const encodedLoc = location2.replace(/"/g, "%22");
        nuxtApp.ssrContext._renderResponse = {
          statusCode: sanitizeStatusCode(options?.redirectCode || 302, 302),
          body: `<!DOCTYPE html><html><head><meta http-equiv="refresh" content="0; url=${encodedLoc}"></head></html>`,
          headers: { location: location2 },
        };
        return response;
      };
      if (!isExternal && inMiddleware) {
        router.afterEach((final) =>
          final.fullPath === fullPath ? redirect(false) : void 0
        );
        return to;
      }
      return redirect(
        !inMiddleware ? void 0 : /* abort route navigation */ false
      );
    }
  }
  if (isExternal) {
    nuxtApp._scope.stop();
    if (options?.replace) {
      location.replace(toPath);
    } else {
      location.href = toPath;
    }
    if (inMiddleware) {
      if (!nuxtApp.isHydrating) {
        return false;
      }
      return new Promise(() => {});
    }
    return Promise.resolve();
  }
  return options?.replace ? router.replace(to) : router.push(to);
};

可以看出,navigateTo 最终还是使用了 router进行处理

<NuxtLink>Vue Router<RouterLink> 组件和 HTML 的 <a> 标签的替代品。它能智能地确定链接是内部链接还是外部链接,并根据可用的优化(预加载、默认属性等)进行渲染。

11.export * from 用法

// a.js
export const x = 1;
export const y = 2;
export const z = 3;
// b.js
export * from "./a.js";

// c.js or c.vue
import { x, y, z } from "b.js";
console.log(x + y + z); // 6

.prettierrc文件 配置

{
  "printWidth": 100, //每行最多多少个字符换行
  "tabWidth": 4, //格式化时tab缩进大小,默认为2
  "useTabs": false, //格式化时使用tab缩进,默认false
  "semi": false, //格式化时不加分号,默认true
  "singleQuote": true, //用单引号替换双引号,默认false(在jsx中配置无效, 默认都是双引号)
  //对象后面默认添加逗号,默认none,可选 none|es5|all
  //es5 包括es5中的数组、对象
  //all 包括函数对象等所有可选
  "trailingComma": "all",
  //箭头函数参数括号 默认avoid 可选 avoid| always
  //avoid 能省略括号的时候就省略 例如x => x
  //always 总是有括号
  "arrowParens": "avoid"
}

12.控制台样式

console.log(
  `%c页面加载耗时:1111ms | Theme By Dream `,
  "color:#fff; background: linear-gradient(270deg, #986fee, #8695e6, #68b7dd, #18d7d3); padding: 8px 15px; border-radius: 0 15px 0 15px"
);

console.log(
  "%c 页面加载耗时:" + Math.round(e) + " ms",
  "padding: 6px 8px;color:#fff;background:linear-gradient(270deg, #4edb21, #f15206);border-radius: 3px;"
);

13.简单的 css 弹性布局小游戏-小青蛙

Flexbox Froggy

14.简单的 css 网格布局小游戏

Grid Garden

15.简单的 css 网格布局代码生成器

CSS Grid Generator

更多查看:


文章作者: 弈心
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 弈心 !
评论
  目录