详解Vite创建Vue3项目router-less-scss-pinia-持久化

news/2024/9/20 5:39:36 标签: 前端, vue.js, chrome, less, typescript, scss
前言

Vite 和 Webpack 都是现代化的前端构建工具,它们可以帮助开发者优化前端项目的构建和性能。虽然它们的目标是相似的,但它们在设计和实现方面有许多不同之处。webpack可以看我的上一篇文章

一、准备工作安装工具 

这里我们简单介绍一下文章中使用到的工具,使用这些工具可以提高我们开发效率。
当然了只有nodejs 是必须要安装的,nvm 、Vite 、NRM 这些都不是必须的, 

如果已经有了node npm 忽略以上,没有则看卸载node,nvm的详细使用方法-CSDN博客 

二、创建Vue3项目

兼容注意:Vite需要Node.js的版本14.18+,16+

然而,有些模板需要依赖更高的 Node 版本才能正常运行,当你的包管理器发出警告时,请注意升级你的 Node 版本。

1-使用 NPM

npm create vite@latest

使用 Yarn:

yarn create vite@latest

使用 PNPM:

pnpm create vite@latest

2-输入vue项目名称,我们这里就叫vite-project,默认就是这个

 

3-选择使用哪种框架,这里我们当然是选择Vue 了(Vite 不仅仅支持Vue 框架,还支持React、Vanilla、Lit 等前端主流框架)

 

4-选择Javascript 和TypeScript(Vue3 已经全面拥抱TypeScript,所以这里我们就选TypeScript)

 

5-到此我们就创建完成了,是不是很简单了

 

6-启动Vue 项目

// 启动项目
npm run dev

当控制台看到如下所示,说明启动成功了
 

注意点:

我们如果之前都是用vue2写之前开发项目时候,我们这里突然转换用vue3开发,在使用Vscode的代码工具时候,vue3需要禁用了以前的vue2,为了兼容代码规范,代码高亮显示的一款插件安装插件Vetur不然代码会提示报错报红。再建议安装Prettier - Code formatter插件【该插件主要用于格式化代码】,为了高效快捷开发,再提供一款插件方便寻找路径和提示Path-intellisens

三、项目结构和特殊页面介绍

 

2- 特殊页面介绍

(1)index.html

首页文件的初始代码如下:

<!doctype html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <link rel="icon" type="image/svg+xml" href="/vite.svg" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Vite + Vue + TS</title>
  </head>
  <body>
    <div id="app"></div>
    <script type="module" src="/src/main.ts"></script>
  </body>
</html>

看似这个是普通的html文件,让它与众不同的是

加了id=“app”
整个项目只有这一个 html 文件,所以 这是一个 单页面应用,当我们打开这个应用,表面上可以有很多页面,实际上它们都只不过在一个 div 中 

(2) App.vue

该文件称为“父组件”,所有组件都是这个组件的儿子组件

.vue 文件是vue 中自定义的文件类型,我们把它看作成html即可,可以在里面写标签元素、css样式、js/ts代码

我们来看看其初始化的代码

<script setup lang="ts">
import HelloWorld from './components/HelloWorld.vue'
</script>

<template>
  <div>
    <a href="https://vitejs.dev" target="_blank">
      <img src="/vite.svg" class="logo" alt="Vite logo" />
    </a>
    <a href="https://vuejs.org/" target="_blank">
      <img src="./assets/vue.svg" class="logo vue" alt="Vue logo" />
    </a>
  </div>
  <HelloWorld msg="Vite + Vue" />
</template>

<style scoped>
.logo {
  height: 6em;
  padding: 1.5em;
  will-change: filter;
  transition: filter 300ms;
}
.logo:hover {
  filter: drop-shadow(0 0 2em #646cffaa);
}
.logo.vue:hover {
  filter: drop-shadow(0 0 2em #42b883aa);
}
</style>

(3)main.ts

main.ts 通常是应用程序的入口文件, App.vue就是通过这个文件和 index.html 里的

产生联系的

import { createApp } from 'vue'
import './style.css'
import App from './App.vue'

createApp(App).mount('#app')

  • import { createApp } from ‘vue’ 导入了 Vue 的 createApp 函数,用于创建一个 Vue 应用实例。
  • import ‘./style.css’ 导入了一个 CSS 文件,这里可以忽略
  • import App from ‘./App.vue’ 导入了根组件 App ,而App又包含了所有子组件
  • createApp(App).mount(‘#app’) 创建了一个 Vue 应用实例,并将根组件 App 挂载到具有 id 为 app 的 DOM 元素上。

(4)package.json 文件
package.json 主要是项目依赖配置。 

{
  "name": "vite-project", //指定项目的名称为 “vite-project”
  "private": true,
  "version": "0.0.0", //指定项目的版本号,这是一个初始版本号
  "type": "module",
  "scripts": { //定义了一些脚本命令,用于开发、构建和预览项目
    "dev": "vite", //启动开发服务器,用于在开发环境下运行项目。 我们前面通过npm run dev就是这里
    "build": "vue-tsc && vite build",//我们使用TypeScript ,需要将 TypeScript 代码编译为js
    "preview": "vite preview"
  },
  "dependencies": { //列出了项目的生产环境依赖项。
    "vue": "^3.3.11"
  },
  "devDependencies": { //列出了项目的开发环境依赖项。
    "@vitejs/plugin-vue": "^4.5.2",
    "typescript": "^5.2.2",
    "vite": "^5.0.8",
    "vue-tsc": "^1.8.25"
  }
}

四、项目出现报红,但可以运行,如何解决

1.创建vite-env.d.ts

declare module "*.vue" {
  import { DefineComponent } from "vue"
  const component: DefineComponent<{}, {}, any>
  export default component
}

2. 删除Vetur插件,安装更适合的Volar

五、安装路由以及配置文件

1-安装Typescript依赖

npm install @types/node --save-dev

2-修改vite.config.ts配置文件代码

import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import { resolve } from 'path'

export default defineConfig({
  plugins: [vue()],
  //解决“vite use `--host` to expose”
  base: './',	//不加打包后白屏
  server: {             
    host: '0.0.0.0',	
    // port: 8080,      
    open: true
  },
  resolve:{   
    //别名配置,引用src路径下的东西可以通过@如:import Layout from '@/layout/index.vue'
    alias:[   
      {
        find:'@',
        replacement:resolve(__dirname,'src') 
      }
    ]
  }
})

3-安装路由

npm install vue-router@4

在src目录下新建router文件夹,在router里创建index.ts文件 

import { createRouter, createWebHistory, RouteRecordRaw } from 'vue-router'
import Layout from '../components/HelloWorld.vue'

const routes: Array<RouteRecordRaw> = [
  {
  //路由初始指向
    path: '/',
    name: 'HelloWorld',
    component:()=>import('../components/HelloWorld.vue'),
  }
]

const router = createRouter({
  history: createWebHistory(),
  routes
})

export default router

4- main.ts中导入挂载路由

import { createApp } from 'vue'
import './style.css'
import App from './App.vue'
import router from './router'

const app = createApp(App);
app.use(router).mount('#app')

5- 修改App.vue管理路由

<script setup lang="ts">
</script>
<template>
  <router-view></router-view>
</template>

<style>

</style>

6- 修改HelloWorld组件

<template>
  <h1>HelloWorld</h1>
</template>

<script setup lang="ts">
</script>

<style scoped>
.read-the-docs {
  color: #888;
}
</style>

HelloWorld

五、安装less/scss

 由于是使用vite,它提供了对 .scss.sass.less.styl 和 .stylus 文件的内置支持,但必须安装相应的预处理器依赖;

国内一般只使用 lessscss,所以我只写这两个安装

 npm add -D less 
 npm add -D sass 
安装后可以直接使用less了  ,当然,也可以使用scss,一般只下一个就够了,我比较推荐scss

使用CSS 嵌套可能会有嵌套报错,这时可以按下面的方法解决

第一步下载
npm i postcss-nesting
 
第二步在vite.config.ts
import postcssNesting from 'postcss-nesting' //引入进来
export default defineConfig({
  css: {
    postcss: {
      plugins: [
        postcssNesting
      ],
    },
  },
  ......
});

六、自动导入

这个是我非常非常非常推荐的两个插件,不过用过element、naiveui等的人一般也会知道,尤大推荐 

npm install -D unplugin-vue-components unplugin-auto-import
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import { resolve } from "path";
// 自动导入vue中hook reactive ref等
import AutoImport from "unplugin-auto-import/vite"
//自动导入ui-组件 比如说ant-design-vue  element-plus等
import Components from 'unplugin-vue-components/vite';
 
// https://vitejs.dev/config/
export default defineConfig({
	plugins: [
		vue(),
		AutoImport({
			//安装两行后你会发现在组件中不用再导入ref,reactive等
			imports: ['vue', 'vue-router'],
            //存放的位置
			dts: "src/auto-import.d.ts",
		}),
		Components({
			// 引入组件的,包括自定义组件
            // 存放的位置
            dts: "src/components.d.ts",
		}),
	],
 
})

七、安装pinia 

因为是vue3+ts,安装pinia更好点,vuex拥抱ts没有pinia好,定义一个 Store | Pinia 中文文档

 npm install pinia 
/*
 * @Author: hukai huzhengen@gmail.com
 * @Date: 2024-09-18 11:23:48
 * @LastEditors: hukai huzhengen@gmail.com
 * @LastEditTime: 2024-09-18 14:43:47
 * @FilePath: \vite\vite-project\src\main.ts
 * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
 */
import { createApp } from 'vue'
import './style.css'
import App from './App.vue'
import router from './router'
import { createPinia } from 'pinia'
const pinia = createPinia()

const app = createApp(App);
app.use(pinia)
app.use(router).mount('#app')

在src下创建一个 store 文件夹,再创建一个 home.ts 文件

其它名也可以,因为pinia它有一个根文件,会把 defineStore 第一个参数当id值,相当于vuex中的 module 自动引入,也会在Vue.js devtools 插件中以第一个参数名展示(下面展示)

注意:defineStore第一个参数很重要,而且是唯一值。它的命名在devtools 插件能方便找到这个文件的数据,方便调试

/*
 * @Author: hukai huzhengen@gmail.com
 * @Date: 2024-09-18 14:48:26
 * @LastEditors: hukai huzhengen@gmail.com
 * @LastEditTime: 2024-09-18 14:48:57
 * @FilePath: \vite\vite-project\src\store\index.ts
 * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
 */
import { defineStore } from 'pinia'
// useMain  可以是 useUser、useCart 之类的名字 
// defineStore('main',{..}) 在devtools 就使用 main 这个名
export const useMain = defineStore('main', {
    // 相当于data
    state: () => {
        return {
            // 所有这些属性都将自动推断其类型,如果推断失败可以试下 as xxx
            counter: 0,
            name: 'Eduardo',
        }
    },
    // 相当于计算属性
    getters: {
        doubleCount: (state) => {
            return state.counter * 2
        },
    },
    // 相当于vuex的 mutation + action,可以同时写同步和异步的代码
    actions: {
        increment() {
            this.counter++
        },
        randomizeCounter() {
            setTimeout(() => {
                this.counter = Math.round(100 * Math.random())
            }, 0);
        },
        // 如果是异步
        async fnName() {
            // await
        }
    },
})

在要使用pinia的组件

以下使用只是用的比较常用的方法,还有其它方法请查看官网  定义一个 Store | Pinia 中文文档
<!--
 * @Author: hukai huzhengen@gmail.com
 * @Date: 2024-09-18 14:44:55
 * @LastEditors: hukai huzhengen@gmail.com
 * @LastEditTime: 2024-09-18 15:52:05
 * @FilePath: \vite\vite-project\src\components\Aouts.vue
 * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
-->
<template>
    <div>counter:{{counter}}</div>
    <div>doubleCount:{{doubleCount}}</div>
    <a-button @click="main.randomizeCounter()">counter(round)</a-button>
    <a-button type="primary" @click="main.increment()">counter++</a-button>
 
    <div>{{name}}</div>
    <a-button @click="amend()">修改</a-button>
</template>
<script setup lang='ts'>
 
//引入想要的pinia文件 {} 里面就是对应导出的名字
import { useMain } from '../store/home.ts'
import { storeToRefs } from 'pinia';
 
const main = useMain()
// 解构main里面的state和getters的数据,
// 使用storeToRefs解构才有响应式,响应式可以直接修改数据,不过这我只用来渲染
let { counter,name ,doubleCount } = storeToRefs(main)
 
//(常用方法三种)
//常用方法一: 使用数据
console.log( counter );
//使用方法(方法可以直接解构,不需要使用storeToRefs)
main.increment()
const T = ref(1)
 console.log( T )
 
// 常用方法二:修改数据
// counter = 9999
 
//常用方法三:
//进阶使用$patch,多个修改
const amend=()=>{
    main.$patch((state) => {
        state.counter += 10;
        state.name = '张三'
    })
}
 
</script>

 Vue.js devtools 环境下通过 defineStore 第一个参数当id值找到对应的仓库

vue-devtools插件

如果你没有vue-devtools,就去谷歌扩展应用

 

然后搜索,直接安装就可以了,从控制台中打开 

数据持久化插件

如果你想要数据持久化可以试下这个插件,简单使用

pinia 和 vuex 一样,数据是短时的,只要一刷新页面,数据就会恢复成初始状态,为了避免这个问题,可以对其采用持久化保存方法。

持久化保存的原理是在 pinia 中数据更新时,同步保存到 localStorage sessionStorage 中,刷新后从本地存储中读取数据,你可以选择自己去写,但是实现起来并不像想象中那么容易,当然,也没那么难。

我推荐使用插件去实现持久化存储,这样更便捷,省时省力。推荐插件为 pinia-plugin-persist,当然,实现持久化存储的插件肯定不止这一种,想用别的也无所谓,本文仅对这款插件讲解使用方法

1. 安装 
yarn add pinia-plugin-persist
# 或者使用 npm
npm install pinia-plugin-persist
2. 引入
import { createApp } from 'vue'
import { createPinia } from 'pinia'
import App from './App.vue'

const pinia = createPinia()

createApp(App).use(pinia).mount('#app') // vue3 的简写语法
3. 使用插件
方式1:默认保存

下面这种写法会将当前模块中的所有数据都进行持久化保存,默认保存在 sessionStorage 中, key 为模块 id,刷新页面不需要手动读取数据,插件会自动读取。

store/user.ts

import { defineStore } from 'pinia'

export const useUserStore = defineStore('user', {
  state: () => ({
    name: null,
    age: null,
    sex: null,
  }),
  persist: {
    enabled: true // true 表示开启持久化保存
  }
})
方式2:设置 key 、指定保存内容

你可以主动设置 key 名,也可以指定哪些数据保存,默认会保存当前模块全部数据。

store/user.ts

export const useUserStore = defineStore('storeUser', {
  state: () => ({
    name: null,
    age: null,
    sex: null,
  }),
  persist: {
    enabled: true,
    strategies: [
      {
        key: 'user',
        storage: localStorage,
        paths: ['name'] 
      },
    ],
  },
})

你甚至可以对不同数据设置不同的本地存储方式。

export const useUserStore = defineStore('storeUser', {
  state: () => ({
    name: null,
    age: null,
    sex: null,
  }),
  persist: {
    enabled: true,
    strategies: [
      { storage: sessionStorage, paths: ['name'] },
      { storage: localStorage, paths: ['age'] },
    ],
  },
})
方式3:保存到 cookie

保存到 cookie 中当然也是可以的,不过需要手动添加 cookie 的保存方式,同样,此处也是推荐使用插件 js-cookie 来完成。

npm install js-cookie
import Cookies from 'js-cookie'

const cookiesStorage: Storage = {
  setItem (key, state) {
    return Cookies.set(key, state.accessToken, { expires: 3 }) // 设置有效期 3 天,不设置默认同 sessionStorage 有效期一致
  },
  getItem (key) {
    return JSON.stringify({
      accessToken: Cookies.get(key),
    })
  },
}

export const useUserStore = defineStore('storeUser', {
  state: () => ({
    name: null,
    age: null,
    sex: null,
    accessToken: 'xxxxxxxxx',
  }),
  persist: {
    enabled: true,
    strategies: [
      {
        storage: cookiesStorage,
        paths: ['accessToken'] // cookie 一般用来保存 token
      },
    ],
  },
})
方式4:2023-12-08更新:持久化存储插件推荐修改

pinia-plugin-persist 在 typeScript 中有类型声明问题。推荐插件改为 pinia-plugin-persistedstate。官网地址如下:

https://prazdevs.github.io/pinia-plugin-persistedstate/zh/

官网的文档非常详细,且使用方法与 pinia-plugin-persist 类似,因此本文不做过多赘述,仅简要描述下使用方法

1.安装插件 
npm i pinia-plugin-persistedstate
2、引入插件

main.ts

import { createPinia } from 'pinia'
import piniaPluginPersistedstate from 'pinia-plugin-persistedstate'

const pinia = createPinia()
pinia.use(piniaPluginPersistedstate)
3、使用插件
import { defineStore } from 'pinia'

export const useStore = defineStore('main', {
  state: () => {
    return {
      someState: '你好 pinia',
    }
  },
  persist: true,
})

只需要添加 persist: true, 整个 store 都将被持久化存储。 

当然也可以指定部分数据持久化,方法如下:

import { defineStore } from 'pinia'

export const useUserStore = defineStore('user', {
  state: () => ({
    name: null,
    age: null,
    sex: null,
    info: {
    	des: null
    }
  }),
  persist: {
    paths: ['name', 'info.des'],
  },
})

这样则只有 nameinfo.des 被持久化保存了。


http://www.niftyadmin.cn/n/5666611.html

相关文章

2024最新!!!iOS高级面试题,全!(二)

iOS应用是如何启动以及如何优化 pre-main阶段 加载动态链接器dyld到App进程 加载动态库&#xff08;包括所依赖的所有动态库&#xff09; Rebase 修正内部的指针指向 Bind 修正外部指针指向 初始化Objective C Runtime 包括oc的类、分类的注册&#xff0c;selector唯一性检查等…

茴香豆:企业级知识问答工具实践闯关任务

基础任务 在 InternStudio 中利用 Internlm2-7b 搭建标准版茴香豆知识助手&#xff0c;并使用 Gradio 界面完成 2 轮问答&#xff08;问题不可与教程重复&#xff0c;作业截图需包括 gradio 界面问题和茴香豆回答&#xff09;。知识库可根据根据自己工作、学习或感兴趣的内容调…

langchain报错记录(js)

文章目录 [ERR_PACKAGE_PATH_NOT_EXPORTED]报错&#xff1a;报错语句&#xff1a;思路&#xff1a;解决方法&#xff1a; [ERR_PACKAGE_PATH_NOT_EXPORTED] 报错&#xff1a; Error [ERR_PACKAGE_PATH_NOT_EXPORTED]: Package subpath ‘./dist/prompts/’ is not defined by…

SISL 插值、近似 example 运行测试

void VisualizeSISLCurve(pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_cv, double r, double g, double b, bool show_cps) {pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZRGB>);cloud->clear();//输入点数const int …

『C/C++』整型和字符串相互转换

■函数名:itoa 功 能:把整数转换为字符串。 原型: char *itoa(int value, char *string, int radix); ◎value: 待转化的整数。 ◎radix: 是基数的意思,即先将value转化为radix进制的数&#xff0c;范围介于2-36&#xff0c;比如10表示10进制。 ◎string: 保存转换后得…

Leetcode面试经典150题-130.被围绕的区域

给你一个 m x n 的矩阵 board &#xff0c;由若干字符 X 和 O 组成&#xff0c;捕获 所有 被围绕的区域&#xff1a; 连接&#xff1a;一个单元格与水平或垂直方向上相邻的单元格连接。区域&#xff1a;连接所有 O 的单元格来形成一个区域。围绕&#xff1a;如果您可以用 X 单…

供方软件供应链安全保障要求及开源场景对照自评表(下)

国标《信息安全技术 软件供应链安全要求》确立了软件供应链安全目标&#xff0c;规定了软件供应链安全风险管理要求和供需双方的组织管理和供应活动管理安全要求。 开源软件供应链作为软件供应链的一种特殊形式&#xff0c;该国标亦适用于指导开源软件供应链中的供需双方开展组…

FPGA开发-0到1

FPGA开发-0到1 文章目录 FPGA开发-0到1前言一、FPGA资源/资源评估1.1 硬件资源1.1.1 BANK的划分1.1.2 布线资源1.1.3 逻辑资源1.1.4 时钟资源1.1.5 存储资源1.1.3 GT资源1.2 资源评估1.2.1 评估步骤1.2.2 评估方法二 代码架构/代码规范三 时钟四 复位五 跨时钟域处理六 常用功能…