nuxt3问题记录

1、安装nuxt3报错:Error: Failed to download template from registry: fetch failed 

(1)以管理员身份打开cmd

(2)进入hosts所在目录,默认是在C:\Windows\System32\drivers\etc下:

cd C:\Windows\System32\drivers\etc

(3)用记事本打开hosts文件:

notepad hosts

(4)在最下面添加:

185.199.108.133 raw.githubusercontent.com

(5)保存后退出就可以了 

2、已安装对应模块,报错无法找到模块“xxx”的声明文件

安装了某个模块,报错:

无法找到模块“postcss-pxtorem”的声明文件。“d:/soft/node_modules/postcss-pxtorem/index.js”隐式拥有 "any" 类型。
尝试使用 `npm i --save-dev @types/postcss-pxtorem` (如果存在),或者添加一个包含 `declare module 'postcss-pxtorem';` 的新声明(.d.ts)文件ts(7016)

nuxt3在根目录下(如果是vue3则是在src目录下)新建 type.d.ts 文件

在 type.d.ts 写上:declare module 'xxx',xxx就是你安装的模块

declare module 'postcss-pxtorem'

3、Nuxt使用document 或 window

在 nuxt 中直接使用 window 或 document 会报 ReferenceError: window is not defined。

原因: 由于 nuxt 是服务端渲染,它会预渲染页面后生成 HTML,然后再将其发送给客户端,而document 和 window 是浏览器环境特有的全局对象,在服务器端渲染期间是不可用的。 

因此要使用 document  或 window 时,要先判断是否是浏览器环境,判断方法:

(1)process.client 为 true

4、Nuxt3引入swiper并使用

(1)安装

npm install nuxt-swiper

(2)nuxt.config.ts(Nuxt 配置

export default defineNuxtConfig({
    modules: [['nuxt-swiper', {
        // Swiper options
    }]],
})

(3)在页面中使用:

<template>
  <div>
    <Swiper
      :height="300"
      :modules="[SwiperAutoplay, SwiperEffectCreative]"
      :slides-per-view="1"
      :loop="true"
      :effect="'creative'"
      :autoplay="{
        delay: 8000,
        disableOnInteraction: true,
      }"
      :creative-effect="{
        prev: {
          shadow: false,
          translate: ['-20%', 0, -1],
        },
        next: {
          translate: ['100%', 0, 0],
        },
      }"
    >
      <SwiperSlide
        v-for="(slide, idx) in slides"
        :key="idx"
        :style="`background-color: ${slide.bg}; color: ${slide.color}`"
      >
        {{ idx }}
      </SwiperSlide>
    </Swiper>
  </div>
</template>
 
<script setup lang="ts">
const slides = ref(
  Array.from({ length: 10 }, () => {
    const r = Math.floor(Math.random() * 256)
    const g = Math.floor(Math.random() * 256)
    const b = Math.floor(Math.random() * 256)
    // Figure out contrast color for font
    const contrast = r * 0.299 + g * 0.587 + b * 0.114 > 186 ? 'black' : 'white'

    return { bg: `rgb(${r}, ${g}, ${b})`, color: contrast }
  })
)
</script>

<style scoped>
.swiper-slide {
  display: flex;
  justify-content: center;
  align-items: center;
  font-size: 18px;
  height: 20vh;
  font-size: 4rem;
  font-weight: bold;
  font-family: 'Roboto', sans-serif;
}
.swiper-wrapper {
  min-width: 100vh;
  width: 100vh;
}
</style>

5、Nuxt3使用百度地图 

1)在这里注册一个账号:百度地图开放平台 | 百度地图API SDK | 地图开发

2)创建应用:

 

 

创建完之后会得到AK:

3) 引入:(全局引入写在app.vue里)

<script setup lang="ts">
useHead({
  script: [
    {
      src: 'https://api.map.baidu.com/api?v=3.0&ak=你的密钥',
      id: 'LA_COLLECT',
    },
  ],
})
</script>

4)使用:

 4.1 创建一个的容器

<div id="container" style="width: 660px;height: 400px"></div>

4.2  创建地图

<script setup lang="ts">
import positionfrom '../assets/img/position.png'
onMounted(() => {
	var map = new BMap.Map('container')// 创建Map实例
	var point = new BMap.Point(113.00696,21.66523) // 经度,纬度
	map.centerAndZoom(point, 15)  // 初始化地图,设置中心点坐标和地图级别
	map.enableScrollWheelZoom(true) // 开启鼠标滚轮缩放
	var myIcon = new BMap.Icon(position, new BMap.Size(31, 64))
	var marker = new BMap.Marker(point, { icon: myIcon }); // 创建标注
	map.addOverlay(marker); // 将标注添加到地图中
})
</script>

参考: 

https://lbsyun.baidu.com/index.php?title=jspopular3.0/guide/getkey

6、Nuxt部署时报错

报错1: 

0|NuxtAppN | [Vue Router warn]: No match found for location with path "xxx"

这个是由于没有error.vue页面,在根目录下加error.vue文件,写点东西就可以

报错2:

0|NuxtAppN | [Vue warn]:Component <Anonymous> is missing template or render function

这个可能是部署时的node版本太低,例如开发时使用的node版本是20.9.0,而部署时使用的是16.13.0,就会出现这个错误

7、Nuxt伪静态

静态就是我们常说的HTML文件,后缀是.html或.htm

什么是伪静态文件?
伪静态文件是指在不改变网站动态页面的情况下,通过服务器配置对页面的链接进行重写,使得页面的链接看起来像静态页面的链接。这样可以提高网站的访问速度和搜索引擎的抓取效果。伪静态文件一般采用URL重写或URL映射的方式实现。

为什么要配置伪静态文件?
相比动态页面,静态页面具有更快的加载速度和更好的用户体验。伪静态文件可以将动态页面的链接转化为静态页面的链接,减少页面的加载时间,并提高页面的响应速度。此外,伪静态文件还可以提高搜索引擎的抓取效果,有利于网站的SEO优化。

nuxt2写法:

nuxt.config.js 加入这段:

router: {
  extendRoutes(routes, resolve) {
    routes.push({
      name: 'user-id-html',
      path: '/user/:id.html',
      component: resolve(__dirname, 'pages/user/_id.vue')
    },{
      name: 'user-html',
      path: '/user.html',
      component: resolve(__dirname, 'pages/user/index.vue')
    });
  }
},

pages/index.vue 代码:

<template>
  <div>
    <button @click="$router.push(`/user.html`)">跳转至user</button>
    <button @click="$router.push(`/user/1.html`)">跳转至user下的动态id页面</button>
  </div>
</template>

pages/user/index.vue 代码:

<template>
	<div>
		user
	</div>
</template>

 pages/user/_id.vue 代码:

<template>
	<div>
		id = 1
	</div>
</template>

nuxt3写法: 

参考:自定义路由 · Nuxt Advanced

nuxt.config.js 加入这段:

hooks: {
    'pages:extend'(pages) {
        // 添加一个路由
        pages.push({
            name: 'user',
            path: '/user.html',
            file: '~/pages/user/index.vue'
        })
    }
}

 pages/index.vue 代码:

<template>
  <div>
    <button @click="$router.push(`/user.html`)">跳转至user</button>
    <button @click="$router.push(`/user/1.html`)">跳转至user下的动态id页面</button>
  </div>
</template>

用 navigateTo({ path: /user.html })  等其他的路由跳转方式都是可以的

pages/user/index.vue 代码:

<template>
	<div>
		user
	</div>
</template>

 pages/user/[id].vue 代码:

<template>
	<div>
		id = 1
	</div>
</template>

8、 首屏加载及路由跳转时执行loading动画

1)编写 loading 页面

项目根目录下创建 components/Loading.vue 

<template>
  <div class="loading-spinner">
    <div class="sk-chase">
      <div class="sk-chase-dot"></div>
      <div class="sk-chase-dot"></div>
      <div class="sk-chase-dot"></div>
      <div class="sk-chase-dot"></div>
      <div class="sk-chase-dot"></div>
      <div class="sk-chase-dot"></div>
    </div>
  </div>
</template>
 
<script setup></script>
 
<style lang="scss" scoped>
.loading-spinner {
  width: 100%;
  height: 100%;
  position: fixed;
  left: 0;
  top: 0;
  right: 0;
  bottom: 0;
  background: rgba(0, 0, 0);
  opacity: .7;
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 99999999999;
}
 
.sk-chase {
  width: 60px;
  height: 60px;
  position: relative;
  animation: sk-chase 2.5s infinite linear both;
}
 
.sk-chase-dot {
  width: 100%;
  height: 100%;
  position: absolute;
  left: 0;
  top: 0;
  animation: sk-chase-dot 2.0s infinite ease-in-out both;
}
 
.sk-chase-dot:before {
  content: '';
  display: block;
  width: 30%;
  height: 30%;
  background-color: #407e03;
  border-radius: 100%;
  animation: sk-chase-dot-before 2.0s infinite ease-in-out both;
}
 
.sk-chase-dot:nth-child(1) {
  animation-delay: -1.1s;
}
 
.sk-chase-dot:nth-child(2) {
  animation-delay: -1.0s;
}
 
.sk-chase-dot:nth-child(3) {
  animation-delay: -0.9s;
}
 
.sk-chase-dot:nth-child(4) {
  animation-delay: -0.8s;
}
 
.sk-chase-dot:nth-child(5) {
  animation-delay: -0.7s;
}
 
.sk-chase-dot:nth-child(6) {
  animation-delay: -0.6s;
}
 
.sk-chase-dot:nth-child(1):before {
  animation-delay: -1.1s;
}
 
.sk-chase-dot:nth-child(2):before {
  animation-delay: -1.0s;
}
 
.sk-chase-dot:nth-child(3):before {
  animation-delay: -0.9s;
}
 
.sk-chase-dot:nth-child(4):before {
  animation-delay: -0.8s;
}
 
.sk-chase-dot:nth-child(5):before {
  animation-delay: -0.7s;
}
 
.sk-chase-dot:nth-child(6):before {
  animation-delay: -0.6s;
}
 
@keyframes sk-chase {
  100% {
    transform: rotate(360deg);
  }
}
 
@keyframes sk-chase-dot {
 
  80%,
  100% {
    transform: rotate(360deg);
  }
}
 
@keyframes sk-chase-dot-before {
  50% {
    transform: scale(0.4);
  }
 
  100%,
  0% {
    transform: scale(1.0);
  }
}
 
.spinner {
  width: 40px;
  height: 40px;
  background-color: #033779;
  margin: 100px auto;
  -webkit-animation: sk-rotateplane 1.2s infinite ease-in-out;
  animation: sk-rotateplane 1.2s infinite ease-in-out;
}
 
@-webkit-keyframes sk-rotateplane {
  0% {
    -webkit-transform: perspective(120px)
  }
 
  50% {
    -webkit-transform: perspective(120px) rotateY(180deg)
  }
 
  100% {
    -webkit-transform: perspective(120px) rotateY(180deg) rotateX(180deg)
  }
}
 
@keyframes sk-rotateplane {
  0% {
    transform: perspective(120px) rotateX(0deg) rotateY(0deg);
    -webkit-transform: perspective(120px) rotateX(0deg) rotateY(0deg)
  }
 
  50% {
    transform: perspective(120px) rotateX(-180.1deg) rotateY(0deg);
    -webkit-transform: perspective(120px) rotateX(-180.1deg) rotateY(0deg)
  }
 
  100% {
    transform: perspective(120px) rotateX(-180deg) rotateY(-179.9deg);
    -webkit-transform: perspective(120px) rotateX(-180deg) rotateY(-179.9deg);
  }
}</style>

2)在store(pinia)中存储 loading 变量

store/useStore.js 

import { defineStore } from 'pinia'

export const useLoading = defineStore('loading', {
	state: () => ({
		value: true // loading初始化为true
	}),
	actions: {
		changeLoading(prop: boolean){
			this.value = prop
		}
	},
})

3)新增 loading 插件,通过 Nuxt 的生命周期钩子来控制 loading 的改变

plugins/loading.ts

import { useLoading } from '~/store/useStore'

export default defineNuxtPlugin((nuxtApp) => {
	const loading = useLoading();
	// hook函数用于在特定点上的渲染生命周期中添加自定义逻辑。当创建Nuxt插件时,通常使用hook函数
	// 查看钩子:https://www.nuxt.com.cn/docs/api/advanced/hooks#app-hooks-runtime
	nuxtApp.hooks.hook('page:start', () => {
	  loading.changeLoading(true)
	});

	nuxtApp.hooks.hook('page:finish', () => {
        setTimeout(() => {
		    loading.changeLoading(false)
        },500);
	});
});

4)在 app.vue 中使用 loading 组件

<template>
  <div id="app">
    <NuxtLayout>
      <Loading v-if="loading" />
      <NuxtPage  />
    </NuxtLayout>
  </div>
</template>

<script setup lang="ts">
import { useLoading } from '~/store/useStore'

const _loading = useLoading()

let loading = computed(() => {
  return _loading.value;
})
</script>

  • 5
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值