搭建Vue3模板

1、项目初始化

1.1 环境准备

  • node v16+
查看node版本:node -v
  • pnpm v9.7.0
查看pnpm版本:pnpm -v

1.2 初始化项目

本项目使用vite项目构建,vite官网:https://cn.vitejs.dev/guide/

pnpm:由npm/yarn衍生而来,解决了npm/yarn内部潜在的bug,极大的优化了性能,被誉为“最先进的包管理工具”

pnpm安装指令:

npm i -g pnpm

项目初始化命令:

pnpm create vite

输入项目名:project
项目初始化
选择框架:vue
选择框架
选择语法:TypeScript
选择语法
项目初始化完成
然后根据提示,切换目录,安装依赖,运行项目

cd project
pnpm install
pnpm run dev

安装依赖
项目成功启动:
项目成功启动

2、项目配置

2.1 项目运行成功后浏览器自动打开

package.json:scripts——dev——“vite --open”
open

2.2 强制使用pnpm包管理工具

团队开发项目的时候,需要统一包管理器工具,因为不同包管理器工具下载同一个依赖,可能版本不一样,导致项目出现Bug问题,因此包管理器工具需要统一管理!!!
在根目录创建scripts/preinstall.js文件,添加下面的内容

if (!/pnpm/.test(process.env.npm_execpath || '')) {
  console.warn(
    `\u001b[33mThis repository must using pnpm as the package manager  ` +
    ` for scripts to work peoperly.\u001b[39m\n`,
  )
  process.exit(1)
}

配置文件package.json:

  "scripts": {
    "preinstall": "node ./scripts/preinstall.js"
  },

当我们使用npm或者yarn来安装包的时候,就会报错了。原理就是在install的时候会触发preinstall(npm提供的生命周期钩子)这个文件里的代码

3、项目集成

3.1 集成element-plus

element-plus官网地址:http://element-plus.org/zh-CN/
安装:

pnpm install element-plus
pnpm install @element-plus/icons-vue

完整引入:
main.ts

import { createApp } from 'vue'
import App from './App.vue'
//引入element-plus插件与样式
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'
//配置element-plus国际化
//@ts-ignore
import zhCn from 'element-plus/es/locale/lang/zh-cn'
//获取应用实例对象
const app = createApp(App)
//安装element-plus插件
app.use(ElementPlus, {
  locale: zhCn,//element-plus国际化配置
})
//将应用挂载到挂载点上
app.mount('#app')

3.2 src别名的配置

在开发项目的时候文件与文件关系可能很复杂,因此我们需要给src文件夹配置一个别名。
vite.config.ts:

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

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [vue()],
  resolve: {
    alias: {
      "@": path.resolve("./src") // 相对路径别名配置,使用@代替src
    }
  }
})

tsconfig.json:

{
  "compilerOptions": {
    "baseUrl": "./", //解析非相对模块的基地址,默认是当前目录
    "paths": { //路径映射,相对于baseUrl
      "@/*": [
        "src/*"
      ]
    }
  }
}

3.3 环境变量的配置

项目开发过程中,至少会经历开发环境、测试环境和生产环境(即正式环境)三个阶段。不同阶段请求的状态(如接口地址等)不尽相同,若手动切换接口地址是相当繁琐且易出错的。于是环境变量配置的需求就应运而生,我们只需做简单的配置,把环境状态切换的工作交给代码。
项目根目录分别添加开发、测试和生产环境的文件!

  • .env.development
# 变量必须以VITE_为前缀才能暴露给外部读取
NODE_ENV = 'development'
VITE_APP_TITLE = '开发环境平台'
VITE_APP_BASE_API = '/dev-api'
VITE_SERVE="http://xxx.com"
  • .env.test
# 变量必须以VITE_为前缀才能暴露给外部读取
NODE_ENV = 'test'
VITE_APP_TITLE = '测试环境平台'
VITE_APP_BASE_API = '/dev-api'
VITE_SERVE="http://zzz.com"
  • .env.production
# 变量必须以VITE_为前缀才能暴露给外部读取
NODE_ENV = 'production'
VITE_APP_TITLE = '生产环境平台'
VITE_APP_BASE_API = '/prod-api'
VITE_SERVE="http://yyy.com"

配置运行命令:
package.json:

{
   "scripts": {
    "dev": "vite --open",
     "build:test": "vue-tsc && vite build --mode test",
    "build:pro": "vue-tsc && vite build --mode production",
    "preview": "vite preview"
  },
}

通过import.meta.env获取环境变量

3.4 SVG图标配置

在开发项目的时候经常会用到svg矢量图,而且我们使用svg以后,页面上加载的不再是图片资源,这对页面性能来说是个很大的提升,而且我们svg文件比img要小的很多,放在项目中几乎不占用资源。

阿里图标地址:https://www.iconfont.cn/

安装svg依赖插件:

pnpm install vite-plugin-svg-icons -D
pnpm install fast-glob

在vite.config.ts中配置插件

import path from 'path'
//引入svg需要用到的插件
import { createSvgIconsPlugin } from "vite-plugin-svg-icons";

export default defineConfig({
  plugins: [vue(),
  createSvgIconsPlugin({
    iconDirs: [path.resolve(process.cwd(), 'src/assets/icons')],
    symbolId: 'icon-[dir]-[name]',
  })
  ],
})

入口文件导入
main.ts:

import 'virtual:svg-icons-register'

使用:
1、封装一个全局的svg组件
src–components–svgIcon–index.vue

<template :style="width,height">
  <!-- svg:图标外层容器节点,内部需要与use标签结合使用 -->
  <svg>
    <!-- xlink:href执行用哪一个图标,属性值务必#icon-图标名字 -->
     <!-- use标签fill属性可以设置图标的颜色,前提是svg图标内不包含fill属性 -->
    <use :xlink:href="prefix+name" :fill="color"></use>
  </svg>
</template>

<script setup lang="ts">
//接收父组件传递过来的参数
defineProps({
  //xlink:href属性值前缀
  prefix:{
    type:String,
    default:'#icon-'
  },
  name:String,
  color:{
    type:String,
    default:''
  },
  width:{
     type:String,
    default:'16px'
  },
  height:{
     type:String,
    default:'16px'
  }

})
</script>

<style scoped>
</style>

2、全局注册
main.ts

import SvgIcon from '@/components/SvgIcon/index.vue'
app.component('SvgIcon',SvgIcon)

3、在别的组件中引入使用

 <template>
  <div>
    <h1>SVG测试</h1>
     <SvgIcon name="phone" color="yellow"></SvgIcon>
  </div>
</template>

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

<style scoped></style>

注:可使用自定义插件注册全局组件
全局组件有很多,使用自定义插件注册全局组件
1、1、封装一个全局的svg组件
src–components–svgIcon–index.vue

<template :style="width,height">
  <!-- svg:图标外层容器节点,内部需要与use标签结合使用 -->
  <svg>
    <!-- xlink:href执行用哪一个图标,属性值务必#icon-图标名字 -->
     <!-- use标签fill属性可以设置图标的颜色,前提是svg图标内不包含fill属性 -->
    <use :xlink:href="prefix+name" :fill="color"></use>
  </svg>
</template>

<script setup lang="ts">
//接收父组件传递过来的参数
defineProps({
  //xlink:href属性值前缀
  prefix:{
    type:String,
    default:'#icon-'
  },
  name:String,
  color:{
    type:String,
    default:''
  },
  width:{
     type:String,
    default:'16px'
  },
  height:{
     type:String,
    default:'16px'
  }

})
</script>

<style scoped>
</style>

2、创建自定义插件
src–components–index.ts

//引入项目中全部的全局组件
import SvgIcon from './svgIcon/index.vue'
const allGlobalComponent = {SvgIcon}

//对外暴露插件对象
export default{
  install(app){
    Object.keys(allGlobalComponent).forEach(key=>{
      //注册为全局组件
      app.component(key,allGlobalComponent[key]);
    })
  }
}

3、引入自定义插件并安装
main.ts

//引入自定义插件对象:注册整个项目全局组件
import globalComponent from '@/components'
//安装自定义插件
app.use(globalComponent)

4、在别的组件中引入使用

 <template>
  <div>
    <h1>SVG测试</h1>
     <SvgIcon name="phone" color="yellow"></SvgIcon>
  </div>
</template>

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

<style scoped></style>

3.5 集成Sass

1、安装sass和sass-loader

pnpm add sass sass-loader -D

2、清除默认样式,创建全局的样式文件
清除默认样式
npm官网–reset.scss–code–reset.scss
src–styles–reset.scss

 html {
  -webkit-text-size-adjust: 100%
}

html:focus-within {
  scroll-behavior: smooth
}

body {
  -webkit-text-size-adjust: 100%;
  -moz-text-size-adjust: 100%;
  text-size-adjust: 100%;
  -moz-osx-font-smoothing: grayscale;
  -webkit-font-smoothing: antialiased;
  min-height: 100vh;
  position: relative;
  text-rendering: optimizeSpeed;
  width: 100%
}

*,
:after,
:before {
  box-sizing: border-box
}

a:not([class]) {
  -webkit-text-decoration-skip: ink;
  text-decoration-skip-ink: auto
}

a,
abbr,
acronym,
address,
applet,
article,
aside,
audio,
b,
big,
blockquote,
body,
canvas,
caption,
center,
cite,
code,
dd,
del,
details,
dfn,
div,
dl,
dt,
em,
embed,
fieldset,
figcaption,
figure,
footer,
form,
h1,
h2,
h3,
h4,
h5,
h6,
header,
hgroup,
html,
i,
iframe,
img,
ins,
kbd,
label,
legend,
li,
mark,
menu,
nav,
object,
ol,
output,
p,
pre,
q,
ruby,
s,
samp,
section,
small,
span,
strike,
strong,
sub,
summary,
sup,
table,
tbody,
td,
tfoot,
th,
thead,
time,
tr,
tt,
u,
ul,
var,
video {
  border: 0;
  font-size: 100%;
  font: inherit;
  margin: 0;
  padding: 0;
  vertical-align: baseline
}

:focus {
  outline: 0
}

article,
aside,
details,
figcaption,
figure,
footer,
header,
hgroup,
main,
menu,
nav,
section {
  display: block
}

ol,
ul {
  list-style: none
}

blockquote,
q {
  quotes: none
}

blockquote:after,
blockquote:before,
q:after,
q:before {
  content: "";
  content: none
}

input,
input:required {
  box-shadow: none
}

input:-webkit-autofill,
input:-webkit-autofill:active,
input:-webkit-autofill:focus,
input:-webkit-autofill:hover {
  -webkit-box-shadow: inset 0 0 0 30px #fff
}

input[type=search]::-webkit-search-cancel-button,
input[type=search]::-webkit-search-decoration,
input[type=search]::-webkit-search-results-button,
input[type=search]::-webkit-search-results-decoration {
  -webkit-appearance: none;
  -moz-appearance: none
}

input[type=search] {
  -webkit-appearance: none;
  -moz-appearance: none
}

input:focus {
  outline: none
}

audio,
canvas,
video {
  display: inline-block;
  max-width: 100%
}

audio:not([controls]) {
  display: none;
  height: 0
}

[hidden] {
  display: none
}

a:active,
a:hover {
  outline: none
}

img {
  height: auto;
  max-width: 100%;
  vertical-align: middle
}

img,
picture {
  display: inline-block
}

button,
input {
  line-height: normal
}

button,
html input[type=button],
input[type=reset],
input[type=submit] {
  -webkit-appearance: button;
  background: transparent;
  border: 0;
  cursor: pointer
}

button[disabled],
html input[disabled] {
  cursor: default
}

[disabled] {
  pointer-events: none
}

input[type=checkbox],
input[type=radio] {
  padding: 0
}

input[type=search] {
  -webkit-appearance: textfield;
  box-sizing: content-box
}

input[type=search]::-webkit-search-cancel-button,
input[type=search]::-webkit-search-decoration {
  -webkit-appearance: none
}

button::-moz-focus-inner,
input::-moz-focus-inner {
  border: 0;
  padding: 0
}

button {
  background: transparent;
  border: 0
}

textarea {
  overflow: auto;
  resize: vertical;
  vertical-align: top
}

table {
  border-collapse: collapse;
  border-spacing: 0;
  text-indent: 0
}

hr {
  background: #000;
  border: 0;
  box-sizing: content-box;
  height: 1px;
  line-height: 0;
  margin: 0;
  overflow: visible;
  padding: 0;
  page-break-after: always;
  width: 100%
}

pre {
  font-family: monospace, monospace;
  font-size: 100%
}

a {
  background-color: transparent
}

abbr[title] {
  border-bottom: none;
  text-decoration: none
}

code,
kbd,
pre,
samp {
  font-family: monospace, monospace
}

small,
sub,
sup {
  font-size: 75%
}

sub,
sup {
  line-height: 0;
  position: relative;
  vertical-align: baseline
}

sub {
  bottom: -5px
}

sup {
  top: -5px
}

button,
input,
optgroup,
select,
textarea {
  font-family: inherit;
  font-size: 100%;
  line-height: 1;
  margin: 0;
  padding: 0
}

button,
input {
  overflow: visible
}

button,
select {
  text-transform: none
}

[type=button],
[type=reset],
[type=submit],
button {
  -webkit-appearance: button
}

[type=button]::-moz-focus-inner,
[type=reset]::-moz-focus-inner,
[type=submit]::-moz-focus-inner,
button::-moz-focus-inner {
  border-style: none;
  outline: 0;
  padding: 0
}

legend {
  border: 0;
  color: inherit;
  display: block;
  max-width: 100%;
  white-space: normal;
  width: 100%
}

fieldset {
  min-width: 0
}

body:not(:-moz-handler-blocked) fieldset {
  display: block
}

progress {
  vertical-align: baseline
}

[type=number]::-webkit-inner-spin-button,
[type=number]::-webkit-outer-spin-button {
  height: auto
}

[type=search] {
  -webkit-appearance: textfield;
  outline-offset: -2px
}

[type=search]::-webkit-search-decoration {
  -webkit-appearance: none
}

::-webkit-file-upload-button {
  -webkit-appearance: button;
  font: inherit
}

summary {
  display: list-item
}

template {
  display: none
}

创建全局的样式文件:
src–styles–index.scss

//引入清除默认样式
@import './reset.scss'

3、引入模板的全局样式
main.ts

//引入模板的全局样式
import '@/styles/index.scss'

4、引入全局变量$
src–styles–variable.scss

//项目提供scss全局变量
//之后样式的全局变量可以写在这

vite.config.ts

export default defineConfig({
  css:{
    preprocessorOptions:{
      scss:{
        javascriptEnabled:true,
        additionalData:'@import "./src/styles/variable.scss";',
      }
    }
  }
})

配置完scss提供的全局变量就可以在组件中使用了

5、组件内使用scss语法:

<style scoped lang="scss">
</style>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值