目录
一、开发环境配置
1、安装node.js
2、npm配置淘宝镜像
3、安装 Vue CLI
升级版本
4、创建一个项目
二、项目框架结构
三、常用的集成
1、Vue Router
安装
使用
2、Vuex
安装
使用
3、axios
安装
使用
四、CLI 服务
1、使用命令
2、vue-cli-service serve
3、vue-cli-service build
4、缓存和并行处理
五、模式和环境变量
1、模式
2、环境变量
只在本地有效的变量
六、本地预览
通过官网下载安装node.js
http://nodejs.cn/
在用 Vue 构建大型应用时需要使用到node里面的 npm 来安装各种插件
Node 版本要求
Vue CLI 4.x 需要 Node.js v8.9 或更高版本 (推荐 v10 以上)。你可以使用 n,nvm 或 nvm-windows 在同一台电脑中管理多个 Node 版本。
如果在本地一直装不上npm的包,可以考虑用国内的淘宝镜像,使用淘宝定制的 cnpm (gzip 压缩支持) 命令行工具代替默认的 npm
npm install -g cnpm --registry=https://registry.npm.taobao.org
npm config set registry https://registry.npm.taobao.org
Vue CLI 是 Vue 提供的一个命令行工具,为单页面应用 (SPA) 快速搭建繁杂的脚手架。它为现代前端工作流提供了功能齐备的构建设置。只需要几分钟的时间就可以运行起来并带有热重载、保存时 lint 校验,以及生产环境可用的构建版本。
对于 Vue 3,我们应该使用 npm
上可用的 Vue CLI v4.5 作为 @vue/cli
。
可以使用下列任一命令安装cli:
npm install -g @vue/cli
# OR
yarn global add @vue/cli
安装之后,我们就可以在命令行中访问 vue
命令。可以通过简单运行命令 vue
,看看是否展示出了一份所有可用命令的帮助信息,来验证它是否安装成功。
查看vue版本可输入以下命令,可检查其版本是否正确:
vue --version
如需升级全局的 Vue CLI 包,可运行:
npm update -g @vue/cli
# 或者
yarn global upgrade --latest @vue/cli
运行 vue create 命令创建一个 名为 hello-world 的项目
vue create hello-world
运行之后,我们会被提示选取一个 preset。
你可以选默认的包含了基本的 Babel + ESLint 设置的 preset,也可以选“手动选择特性”来选取需要的特性。
这个默认的设置非常适合快速创建一个新项目的原型,而手动设置则提供了更多的选项,它们是面向生产的项目更加需要的。
|- node_modules // 项目依赖包
|- public // 一般用于存放静态文件,打包时会被直接复制到输出目录(./dist)
|- src // 项目源代码
|- assets // 静态资源文件夹,用于存放静态资源,打包时会经过 webpack 处理
|- components // 组件文件夹,存放 Vue 组件
└─ loading
|- index.vue
|- index.ts
|- index.less
|- pages // 页面视图文件夹
|- Index
|- index.vue
|- index.ts
|- index.less
|- router // 路由配置文件夹
|- router.js // 路由文件配置
|- store // vuex文件夹
├── index.js # 我们组装模块并导出 store 的地方
├── actions.js # 根级别的 action
├── mutations.js # 根级别的 mutation
└── modules
├── cart.js # 购物车模块
└── products.js # 产品模块
|- service // 服务请求文件夹
|- http.js // 请求接口文件
|- request.js // 请求配置文件
|- utils // 工具类文件夹
|- App.vue // 入口文件
|- main.js // 注册路由与服务
|- .env // 环境配置文件
|- .env.development // dev环境配置文件
|- .env.test // test环境配置文件
|- .env.production // prd环境配置文件
|- vue.config.js // 配置文件
|- package.json // 包管理代码
|- .gitignore // git忽略文件
|- README.md // 说明文件
npm install vue-router@4
用 Vue + Vue Router 创建单页应用非常简单:通过 Vue.js,我们已经用组件组成了我们的应用。当加入 Vue Router 时,我们需要做的就是将我们的组件映射到路由上,让 Vue Router 知道在哪里渲染它们。
App.vue
Hello App!
Go to Home
Go to About
router-link:我们没有使用常规的 a
标签,而是使用一个自定义组件 router-link
来创建链接。这使得 Vue Router 可以在不重新加载页面的情况下更改 URL,处理 URL 的生成以及编码。
router-view:
将显示与 url 对应的组件。可以把它放在任何地方,以适应布局。
router.js
import { createRouter, createWebHashHistory } from 'vue-router'
const Steps = () => import('@/pages/Steps/index')
const Guide = () => import('@/pages/Guide/index')
const Distinguish = () => import('@/pages/Distinguish/index')
const Massage = () => import('@/pages/Massage/index')
const Project = () => import('@/pages/Project/index')
const Custom = () => import('@/pages/Custom/index')
const Referrals = () => import('@/pages/Referrals/index')
const Main = () => import('@/pages/Main/index')
const AudioTest = () => import('@/pages/AudioTest/index')
const CameraTest = () => import('@/pages/cameraTest/index')
import Test from '@/pages/Test/index'
const routes = [
{ path: '/', name: 'firstPage', component: Project }, // 我的方案
{ path: '/steps', component: Steps },
{ path: '/guide', component: Guide },
{
path: '/distinguish',
component: Distinguish,
meta: {
keepAlive: false
}
},
{ path: '/massage', component: Massage },
{ path: '/test', component: Test },
{ path: '/custom', component: Custom }, // 方案定制
{ path: '/referrals', component: Referrals }, // 推荐测肤
{ path: '/main', component: Main },
{ path: '/audio', component: AudioTest },
{ path: '/cameraTest', component: CameraTest },
]
const router = createRouter({
// 4. 内部提供了 history 模式的实现。为了简单起见,我们在这里使用 hash 模式。
history: createWebHashHistory(),
routes, // `routes: routes` 的缩写
})
router.beforeEach((to, from, next) => {
// console.log(to, from, location.href)
// 地址参数纠正
if (to.name === 'firstPage') {
// 代码逻辑
}
next()
})
// 滚动条回到顶部
router.afterEach(() => {
document.body.scrollTop = 0
document.documentElement.scrollTop = 0;
})
export default router
main.js
import router from 'router.js'
// 5. 创建并挂载根实例
const app = Vue.createApp({})
//确保 _use_ 路由实例使
//整个应用支持路由。
app.use(router)
app.mount('#app')
// 现在,应用已经启动了!
通过调用 app.use(router)
,我们可以在任意组件中以 this.$router
的形式访问它,并且以 this.$route
的形式访问当前路由:
// Index.vue
export default {
computed: {
username() {
// 我们很快就会看到 `params` 是什么
return this.$route.params.username
},
},
methods: {
goToDashboard() {
if (isAuthenticated) {
this.$router.push('/dashboard')
} else {
this.$router.push('/login')
}
},
},
}
要在
setup
函数中访问路由,请调用useRouter
或useRoute
函数。
Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式 + 库。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。
npm install vuex@next --save
# OR
yarn add vuex@next --save
注意:vue 3.x 和 4.x 的写法有点不一致,具体请查阅官方文档
import Vue from 'vue';
import Vuex from 'vuex';
import createVuexAlong from 'vuex-along';
Vue.use(Vuex);
export default new Vuex.Store({
state: {
urlParams: {},
albumList: [],
albumCourse: []
},
getters: {
musicById: state => id => {
for (let i = 0; i < state.albumCourse.length; i++) {
const course = state.albumCourse[i];
for (let j = 0; j < course.length; j++) {
if (id === course[j].id) {
return course[j];
}
}
}
}
},
mutations: {
urlParams: (state, payload) => {
state.urlParams = payload;
},
albumList: (state, payload) => {
state.albumList = payload;
}
},
actions: {
createAudio(context, audio) {
return new Promise(resolve => {
const audioObj = new Audio(audio.url);
context.commit('audioObj', audioObj);
resolve(audioObj);
});
}
},
modules: {},
plugins: [createVuexAlong({
name: '__phzn-store',
justSession: true,
session: {
list: []
}
})]
});
State
computed: {
localComputed () { /* ... */ },
// 使用对象展开运算符将此对象混入到外部对象中
...mapState([
// 映射 this.count 为 store.state.count
'count'
])
}
Getter
import { mapGetters } from 'vuex'
export default {
// ...
computed: {
// 使用对象展开运算符将 getter 混入 computed 对象中
...mapGetters([
'doneTodosCount',
'anotherGetter',
// ...
])
}
}
// 如果你想将一个 getter 属性另取一个名字,使用对象形式:
...mapGetters({
// 把 `this.doneCount` 映射为 `this.$store.getters.doneTodosCount`
doneCount: 'doneTodosCount'
})
Mutation
import { mapMutations } from 'vuex'
export default {
// ...
methods: {
...mapMutations([
'increment', // 将 `this.increment()` 映射为 `this.$store.commit('increment')`
// `mapMutations` 也支持载荷:
'incrementBy' // 将 `this.incrementBy(amount)` 映射为 `this.$store.commit('incrementBy', amount)`
]),
...mapMutations({
add: 'increment' // 将 `this.add()` 映射为 `this.$store.commit('increment')`
})
}
}
Action
import { mapActions } from 'vuex'
export default {
// ...
methods: {
...mapActions([
'increment', // 将 `this.increment()` 映射为 `this.$store.dispatch('increment')`
// `mapActions` 也支持载荷:
'incrementBy' // 将 `this.incrementBy(amount)` 映射为 `this.$store.dispatch('incrementBy', amount)`
]),
...mapActions({
add: 'increment' // 将 `this.add()` 映射为 `this.$store.dispatch('increment')`
})
}
}
Module
由于使用单一状态树,应用的所有状态会集中到一个比较大的对象。当应用变得非常复杂时,store 对象就有可能变得相当臃肿。
为了解决以上问题,Vuex 允许我们将 store 分割成模块(module)。每个模块拥有自己的 state、mutation、action、getter、甚至是嵌套子模块——从上至下进行同样方式的分割:
const moduleA = {
state: () => ({ ... }),
mutations: { ... },
actions: { ... },
getters: { ... }
}
const moduleB = {
state: () => ({ ... }),
mutations: { ... },
actions: { ... }
}
const store = new Vuex.Store({
modules: {
a: moduleA,
b: moduleB
}
})
store.state.a // -> moduleA 的状态
store.state.b // -> moduleB 的状态
Axios 是一个基于 promise 的 HTTP 库,可以用在浏览器和 node.js 中。
npm install axios
import axios from 'axios'
// create an axios instance
const service = axios.create({
baseURL: process.env.VUE_APP_BASE_API, // url = base url + request url
// withCredentials: true, // send cookies when cross-domain requests
timeout: 30e3 // request timeout
})
// request interceptor
service.interceptors.request.use(
config => {
// do something before request is sent
return config
},
error => {
// do something with request error
console.log(error) // for debug
return Promise.reject(error)
}
)
// response interceptor
service.interceptors.response.use(
/**
* If you want to get http information such as headers or status
* Please return response => response
*/
/**
* Determine the request status by custom code
* Here is just an example
* You can also judge the status by HTTP Status Code
*/
response => {
return response.data
},
error => {
console.log('err ' + error) // for debug
return Promise.reject(error.response)
}
)
export default service
import request from './request'
const baseurl = 'api/'
export function userClockin(data) {
return request({
url: baseurl + 'clockin',
params: data,
method: 'get'
})
}
export function updateUserProject(data) {
return request({
url: baseurl + 'update',
data,
method: 'post'
})
}
Pinia 是一个 Vue 存储库,推荐使用 Pinia 替代 Vuex
Pinia 中文文档
在一个 Vue CLI 项目中,@vue/cli-service
安装了一个名为 vue-cli-service
的命令。你可以在 npm scripts 中以 vue-cli-service
、或者从终端中以 ./node_modules/.bin/vue-cli-service
访问这个命令。
这是使用默认 preset 的项目的 package.json
:
{
"scripts": {
"serve": "vue-cli-service serve",
"build": "vue-cli-service build"
}
}
我们可以通过 npm 或 Yarn 调用这些 script:
npm run serve
# OR
yarn serve
如果可以使用 npx (最新版的 npm 应该已经自带),也可以直接这样调用命令:
npx vue-cli-service serve
用法:vue-cli-service serve [options] [entry]
选项:
--open 在服务器启动时打开浏览器
--copy 在服务器启动时将 URL 复制到剪切版
--mode 指定环境模式 (默认值:development)
--host 指定 host (默认值:0.0.0.0)
--port 指定 port (默认值:8080)
--https 使用 https (默认值:false)
vue-cli-service serve
命令会启动一个开发服务器 (基于 webpack-dev-server) 并附带开箱即用的模块热重载 (Hot-Module-Replacement)。
除了通过命令行参数,也可以使用 vue.config.js
里的 devServer 字段配置开发服务器。
命令行参数 [entry]
将被指定为唯一入口 (默认值:src/main.js
,TypeScript 项目则为 src/main.ts
),而非额外的追加入口。尝试使用 [entry]
覆盖 config.pages
中的 entry
将可能引发错误。
用法:vue-cli-service build [options] [entry|pattern]
选项:
--mode 指定环境模式 (默认值:production)
--dest 指定输出目录 (默认值:dist)
--modern 面向现代浏览器带自动回退地构建应用
--target app | lib | wc | wc-async (默认值:app)
--name 库或 Web Components 模式下的名字 (默认值:package.json 中的 "name" 字段或入口文件名)
--no-clean 在构建项目之前不清除目标目录的内容
--report 生成 report.html 以帮助分析包内容
--report-json 生成 report.json 以帮助分析包内容
--watch 监听文件变化
vue-cli-service build
会在 dist/
目录产生一个可用于生产环境的包,带有 JS/CSS/HTML 的压缩,和为更好的缓存而做的自动的 vendor chunk splitting。它的 chunk manifest 会内联在 HTML 里。
这里还有一些有用的命令参数:
--modern
使用现代模式构建应用,为现代浏览器交付原生支持的 ES2015 代码,并生成一个兼容老浏览器的包用来自动回退。
--target
允许你将项目中的任何组件以一个库或 Web Components 组件的方式进行构建。
--report
和--report-json
会根据构建统计生成报告,它会帮助你分析包中包含的模块们的大小。
cache-loader
会默认为 Vue/Babel/TypeScript 编译开启。文件会缓存在node_modules/.cache
中——如果你遇到了编译方面的问题,记得先删掉缓存目录之后再试试看。
thread-loader
会在多核 CPU 的机器上为 Babel/TypeScript 转译开启。
默认情况下,一个 Vue CLI 项目有三个模式:
development
模式用于vue-cli-service serve
test
模式用于vue-cli-service test:unit
production
模式用于vue-cli-service build
和vue-cli-service test:e2e
你可以通过传递 --mode
选项参数为命令行覆写默认的模式。
例如,如果你想要在构建命令中使用开发环境变量:
vue-cli-service build --mode development
我们可以在项目根目录中放置下列文件来指定环境变量:
.env # 在所有的环境中被载入
.env.local # 在所有的环境中被载入,但会被 git 忽略
.env.[mode] # 只在指定的模式中被载入
.env.[mode].local # 只在指定的模式中被载入,但会被 git 忽略
请注意,只有 NODE_ENV
,BASE_URL
和以 VUE_APP_
开头的变量将通过 webpack.DefinePlugin
静态地嵌入到客户端侧的代码中。这是为了避免意外公开机器上可能具有相同名称的私钥。
有的时候可能有一些不应该提交到代码仓库中的变量,尤其是当项目托管在公共仓库时。这种情况下你应该使用一个 .env.local
文件取而代之。本地环境文件默认会被忽略,且出现在 .gitignore
中。
.local
也可以加在指定模式的环境文件上,比如 .env.development.local
将会在 development 模式下被载入,且被 git 忽略。
vue项目执行打包命令后会自动生成一个dist文件夹,dist
目录需要启动一个 HTTP 服务器来访问 (除非你已经将 publicPath
配置为了一个相对的值),所以以 file://
协议直接打开 dist/index.html
是不会工作的。
在本地预览生产环境构建最简单的方式就是使用一个 Node.js 静态文件服务器,例如 serve:
npm install -g serve
# -s 参数的意思是将其架设在 Single-Page Application 模式下
# 这个模式会处理即将提到的路由问题
serve -s dist