NUXT3项目实践总结

目录

一、NUXT3实现黑夜白天模式切换

需求

实现

效果

二、scrollreveal插件实现动画效果

需求

实现

封装

使用

文档

效果

三、useSeoMeta的使用

作用

使用

效果

四、NUXT3开启代理

使用

注意

[五、fetch、useFetch 、useAsyncData的区别](#五、fetch、useFetch 、useAsyncData的区别)

六、错误页面处理

使用

代码

效果


网站地址:https://www.itihey.com/

一、NUXT3实现黑夜白天模式切换

需求

实现对网页颜色的整体控制,适配夜晚模式或者其他风格的页面用于迎合更多用户的页面样式多样化的需求。

实现

index.js

javascript 复制代码
import theme from '@/utils/theme'
// 选择主题
const themeChange = (val: boolean) => {
  localStorage.setItem('theme', String(val))
  isDark.value = val
  if (val) {
    currentSkinName.value = 'defaultTheme'
    switchTheme(currentSkinName.value)
  } else {
    currentSkinName.value = 'darkTheme'
    switchTheme(currentSkinName.value)
  }
}
const switchTheme = (type?: string) => {
  type = type || 'darkTheme'
  const colorObj: ColorObject = (theme as { [key: string]: ColorObject })[type];
  Object.keys(colorObj).map(item => {
    document.documentElement.style.setProperty(item, colorObj[item])
  })
}

theme.js

javascript 复制代码
export default {
  // 默认主题
  'defaultTheme': {
    // 主题色
    '--color-primary': '#2966df',
    '--el-color-primary': '#409eff',
    '--el-color-white': '#ffffff',//基础白色,
    // 导航条背景色
    '--navbar-bg': '#ffffff00',
    // 主体背景色
    '--background-color': '#ffffff',
    // banner背景色
    '--banner-bg': '#ffffff00',
    // 主要文字色
    '--text-color': '#000000',
    // 次要文字色
    '--text-color-secondary': '#909399',
    // 最次要文字色
    '--text-color-th': 'rgba(0, 0, 0, 0.3)',
    // 边框色
    '--border-color': '#e3e3e3',
    // 浅边框阴影
    '--border-shadow-shallow': 'rgb(0, 0, 0, 0.2)',
    // 深边框阴影
    '--border-shadow-deep': 'rgb(0, 0, 0, 0.5)',
    '--card-color': '#F8FBFE',
    '--el-color-primary-light-1': '#53a8ff',
    '--el-color-primary-light-2': '#66b1ff',
    '--el-color-primary-light-3': '#79bbff',
    '--el-color-primary-light-4': '#8cc5ff',
    '--el-color-primary-light-5': '#a0cfff',
    '--el-color-primary-light-6': '#b3d8ff',
    '--el-color-primary-light-7': '#c6e2ff',
    '--el-color-primary-light-8': '#d9ecff',
    '--el-color-primary-light-9': '#ecf5ff',

  },
  'darkTheme': {
    '--color-primary': '#2966df',
    '--el-color-primary': '#409eff',
    "--el-color-white": "#ffffff", // 基础白色
    // 导航条背景色
    '--navbar-bg': '#00000000',
    // banner背景色
    '--banner-bg': '#00000070',
    // 主体背景色
    '--background-color': '#262727',
    // 主要文字色
    '--text-color': '#ffffff',
    // 次要文字色
    '--text-color-secondary': 'rgba(255, 255, 255, 0.8)',
    // 最次要文字颜色
    '--text-color-th': 'rgba(255, 255, 255, 0.5)',
    // 边框色
    '--border-color': '#e3e3e3',

    '--card-color': '#011522',
    // 浅边框阴影
    '--border-shadow-shallow': 'rgb(255, 255, 255, 0.2)',
    // 深边框阴影
    '--border-shadow-deep': 'rgb(255, 255, 255, 0.5)',
  }
}

整个代码的核心在于 document.documentElement.style.setProperty 的这个js方法。

  1. 'document' 是JavaScript中表示当前文档的对象。
  2. 'document.documentElement' 是文档对象模型中表示HTML文档根元素的对象。
  3. '.style' 获取根元素的样式属性对象。
  4. '.setProperty(item, colorObj[item])' 是设置根元素样式属性的方法。item 是一个变量,表示要设置的CSS属性名称,而 colorObj[item] 是相应属性的值。

当然你也可以通过设置更多的主题来达到主题切换的效果。

效果

二、scrollreveal插件实现动画效果

需求

网站想要高大上,动画必不可少,如何实现优雅的动画就成了关键。实现的方式有很多比如animate.css + wow.js 实现。又或者使用scrollreveal插件来实现。这里我们来通过scrollreveal插件来实现动画效果。

实现

第一步,在src下创建plugins文件夹,写入名为scrollreveal.client.ts的文件。

javascript 复制代码
import { defineNuxtPlugin } from "#app";
import scrollReveal from 'scrollreveal'
 
export default defineNuxtPlugin((nuxtApp) => {
    let data = scrollReveal();
      return {
        provide: {
            scrollReveal: data,
        },
      }
});

封装

在components文件夹下创建名为RevealAnimation.vue的文件

TypeScript 复制代码
<template>
    <div :id="ID" className="load-hidden">
        <slot></slot>
    </div>
</template>
  
<script setup lang="ts">
import { ref, onMounted } from 'vue';
const props = defineProps({
    options: {
        type: Object,
        default: () => ({
            // 动画的时长
            duration: 800,
            // 延迟时间
            delay: 100,
            // 动画开始的位置,'bottom', 'left', 'top', 'right'
            origin: 'bottom',
            // 回滚的时候是否再次触发动画
            reset: false,
            // 延时执行方式(always(一直延时执行),once(只延时执行一次),onload(只在加载时延时执行))
            useDelay: 'onload',
            // 在移动端是否使用动画
            mobile: true,
            // 滚动的距离,单位可以用%,rem等
            distance: '5rem',
            // 其他可用的动画效果
            opacity: 0.01,
            // 执行速度 线性函数啥的
            easing: 'ease-in-out',
            // 执行方式(缩放)
            scale: 0.9,
        }),
    },
    ID: {
        type: String,
        default: 'reveal',
    },
});
const { $scrollReveal } = useNuxtApp()


onMounted(() => {
    if (process.client) {
        retScroll($scrollReveal);
    }
});

const retScroll = (data: any) => {
    data.reveal(`#${props.ID}`, { ...props.options })
};
</script>
  
<style scoped>
.load-hidden {
    visibility: hidden;
}
</style>
  

另外我们再封装一个自动生成options配置项的工具,这里我只把几个关键的配置项写上了,需要更多配置项自己手动添加就可以。

TypeScript 复制代码
export const createAnimationOptions = (origin: string, duration: number, scale: number) => {
    return {
        // 动画的时长
        duration: duration || 800,
        // 延迟时间
        delay: 100,
        // 动画开始的位置,'bottom', 'left', 'top', 'right'
        origin: origin || 'bottom',
        // 回滚的时候是否再次触发动画
        reset: false,
        // 延时执行方式(always(一直延时执行),once(只延时执行一次),onload(只在加载时延时执行))
        useDelay: 'always',
        // 在移动端是否使用动画
        // mobile: true,
        // 滚动的距离,单位可以用%,rem等
        distance: '5rem',
        // 其他可用的动画效果
        opacity: 0.01,
        // 执行速度 线性函数啥的
        easing: 'ease-in-out',
        // 执行方式(缩放)
        scale: scale || 0.9,
    };
}

使用

TypeScript 复制代码
<template>     
 <RevealAnimation :ID="'web'" :options="createAnimationOptions('top', 300, .9)">
        <div class="title">
          <h1>题海·网页搜题</h1>
          <h2>Questions · Web search questions</h2>
        </div>
        <div class="center">
          <div class="contentImage">
            <img :src="Webimg" alt="">
            <ComBotton :title="'开始搜题'" @onclick="handleRoute('web')"/>
          </div>
          <ContentCard v-for=" (val, key) in getContent('web')" :ID="`web_card_${key}`"
            :options="createAnimationOptions('left', 800 + key * 300, .5)" :content="val" :key="key" />
        </div>
      </RevealAnimation>
</template>



<script setup lang="ts">
import { createAnimationOptions } from "@/utils/tool";
</script>

文档

nullhttps://scrollrevealjs.org/api/reveal.html更多方法API详见官方文档

效果

三、useSeoMeta的使用

作用

useSeoMeta组合函数能够以完全支持TypeScript的形式将你网站的SEO元标签定义为一个扁平对象。里面包含了许多的属性,比如:

"ogDescription" 通常是指 Open Graph 描述,也是 Open Graph 协议的一部分。这是一个用于指定在社交媒体分享时显示的描述文本的元数据。

"Open Graph" 是一种用于社交媒体分享的元数据协议。Open Graph 协议是由 Facebook 提出的一种协议,用于在分享链接时显示更富有信息的预览内容,包括标题、描述和图像。

更多详细属性请参阅官方文档

useSeoMeta · Nuxt ComposablesuseSeoMeta组合函数能够以完全支持TypeScript的形式将你网站的SEO元标签定义为一个扁平对象。https://nuxt.com.cn/docs/api/composables/use-seo-meta

使用

TypeScript 复制代码
<script setup lang="ts">

import {useSeoMeta} from "unhead";

const data = res.value as QuestionData[]  
  useSeoMeta({
    title: data[0].question + ' - 题海',
    description,
    ogTitle: data[0].question,
    ogSiteName: '题海',
    ogType: "website",
    ogDescription: description
  })
}


</script>

只需要在setup中调用该方法即可使用。

效果

四、NUXT3开启代理

使用

找到根目录下的nuxt.config.ts 文件即可。

TypeScript 复制代码
// https://nuxt.com/docs/api/configuration/nuxt-config
export default defineNuxtConfig({
    routeRules: {
        '/question/**': {swr: true},
        "/web-service/**": {
            proxy: "http://app.******.com/web-service/**",
        },
        "/sso-service/**": {
            proxy: "http://app.******.com/sso-service/**",
        },
        "/payService/**": {
            proxy: "http://app.******.com/payService/**",
        }
    },
})

注意

NUTXT的代理和普通的VUE和REACT项目的代理不太一样,一般来说正常的项目代理只需要拼接域名端口号就行,但是NUXT需要把要代理的路由地址也填写上。这里需要特别注意一下。

五、$fetch、useFetch 、useAsyncData的区别

  1. $fetch:

    • 用法 :在页面组件中,你可以通过在 asyncDatafetch 钩子中调用 $fetch 来触发数据的获取。
    • 作用$fetch 用于在服务端渲染时获取数据,或者在客户端导航时获取数据。它允许你在组件级别发起数据请求。
    复制代码
  2. useFetch:

    • 用法useFetch 是 Nuxt.js 提供的一个插件,允许你在组件中使用 Composition API 风格的 fetch 钩子,而不是使用传统的生命周期钩子。
    • 作用 :与 $fetch 类似,useFetch 也用于在组件级别发起数据请求,但它更适用于使用 Composition API 风格的组件。
    复制代码
  3. useAsyncData:

    • 用法useAsyncData 用于将异步数据加载到 Nuxt.js 页面中。它被设计用于在服务端渲染和客户端导航之间共享数据。
    • 作用useAsyncData 主要用于在页面组件中预取数据,以便在服务端渲染时提供页面所需的数据。

总体而言,这些方法提供了不同的方式来处理数据获取,你可以根据具体的需求选择适合的方法。$fetchuseFetch 更加灵活,适用于各种场景,而 useAsyncData 更专注于服务端渲染时的数据获取。

具体请参阅官方文档:

数据获取 · 快速入门 NuxtNuxt 提供了组合函数来处理应用程序中的数据获取。https://nuxt.com.cn/docs/getting-started/data-fetching

六、错误页面处理

使用

在src下创建 error.vue页面即可。

代码

TypeScript 复制代码
<template>
  <div class="container">
    <img :src="noFound" alt="">
    <div class="info">
      <p>The Page not Found-找不到你要访问的页面</p>
      <div class="sub">
        <a href="/">Back</a>
      </div>
    </div>
  </div>
</template>
<script setup>
import noFound from '@/assets/svg/404error.svg'
</script>
<style scoped lang="scss">
.container {
  width: 100vw;
  height: 100vh;
  --color: #E1E1E1;
  background-color: #F3F3F3;
  background-image: linear-gradient(0deg, transparent 24%, var(--color) 25%, var(--color) 26%, transparent 27%, transparent 74%, var(--color) 75%, var(--color) 76%, transparent 77%, transparent),
  linear-gradient(90deg, transparent 24%, var(--color) 25%, var(--color) 26%, transparent 27%, transparent 74%, var(--color) 75%, var(--color) 76%, transparent 77%, transparent);
  background-size: 55px 55px;
  position: relative;

  img {
    position: absolute;
    top: 40%;
    left: 50%;
    transform: translate(-50%, -50%);
    width: 600px;
    height: 600px;
  }

  .info {
    position: absolute;
    top: 75%;
    left: 50%;
    transform: translate(-50%, -50%);
    text-align: center;

    p {
      font-size: 24px;
      color: #666;
    }

    .sub {
      margin-top: 30px;

      a {
        color: #fff;
        font-size: 16px;
        padding: 6px 10px;
        border-radius: 10px;
        border: 1px solid #666;
        background-color: var(--color-primary);
      }
    }
  }
}</style>

效果

相关推荐
也无晴也无风雨1 小时前
深入剖析输入URL按下回车,浏览器做了什么
前端·后端·计算机网络
Martin -Tang1 小时前
Vue 3 中,ref 和 reactive的区别
前端·javascript·vue.js
FakeOccupational3 小时前
nodejs 020: React语法规则 props和state
前端·javascript·react.js
放逐者-保持本心,方可放逐3 小时前
react 组件应用
开发语言·前端·javascript·react.js·前端框架
曹天骄4 小时前
next中服务端组件共享接口数据
前端·javascript·react.js
阮少年、4 小时前
java后台生成模拟聊天截图并返回给前端
java·开发语言·前端
郝晨妤6 小时前
鸿蒙ArkTS和TS有什么区别?
前端·javascript·typescript·鸿蒙
AvatarGiser6 小时前
《ElementPlus 与 ElementUI 差异集合》Icon 图标 More 差异说明
前端·vue.js·elementui
喝旺仔la6 小时前
vue的样式知识点
前端·javascript·vue.js
别忘了微笑_cuicui6 小时前
elementUI中2个日期组件实现开始时间、结束时间(禁用日期面板、控制开始时间不能超过结束时间的时分秒)实现方案
前端·javascript·elementui