安装
npm i -g @vue/cli
vue -V
查看版本,以检查是否安装成功创建项目
vue create project-name
cd
进项目目录、执行 npm run serve
运行项目vue ui
vue create demo
命令行创建 Vue 项目 demospace
to select, a
to toggle all, i
to invert selection)
n
N
npm i
/ yarn
下载name
属性应与文件名一样,方便后期维护;组件名使用大驼峰npm i
时下载的依赖包与原版本一致{
"compilerOptions": { // 编译配置
"target": "es5",
"module": "esnext",
"baseUrl": "./",
"moduleResolution": "node",
"paths": {
"@/*": ["src/*"] // 设置路径简写 `@` → `src/`
},
"lib": ["esnext", "dom", "dom.iterable", "scripthost"]
}
}
@
,但是要在前面加 ~
background: url('~@/assets/1.jpg');
npm run serve
:开启服务器;这里其实是在 script
字段中配置了 "serve": "vue-cli-service serve"
"scripts": {
"serve": "vue-cli-service serve",
"build": "vue-cli-service build",
"lint": "vue-cli-service lint"
},
render
为渲染函数,接收 createElement
方法作为第 1 参数,以创建 VNode// 引入 vue,默认为残缺版的 Vue:dist/vue.runtime.common.js,里面没有 [模板解析器]
// 完整版的 Vue 在 vue/dist/vue.js
// 可以在 package.json 文件中设置默认项
import Vue from 'vue'
// 引入 App.vue 组件
import App from './App.vue'
// 关闭生产版本的提示
Vue.config.productionTip = false
// 创建 Vue 实例
new Vue({
// 引入完整版的 Vue 才能使用 template,因为需要 [模板解析器]
// template: ` `,
// components: { App }
// 残缺版的 Vue 可使用 render 渲染模版
// render: h => h(App) // 简写
render(createElement) { // 标准写法
// return createElement("h1", "大哥好") // 使用方法1:渲染节点
return createElement(App) // 使用方法2:渲染组件
}
}).$mount('#app')
/*
使用残缺版 Vue 的理由:
因为 [模版解析器] 的体积非常大,使用阉割版的 Vue 可以使项目打包后体积小一些
假设我需要铺地砖,现有两种方法:
第一种:买 100 块地砖 + 买 3 个工人 => 得到:完整的装修 + 3 个工人
第二种:买 100 块地砖 + 雇 3 个工人 => 得到:完整的装修
render 的使用就像好比第二种,使用完工人(模版解析器)后即可抛弃
*/
npm run serve
vue inspect > 文件名.js
- 可以输出 vue 的 webpack 配置,供用户查看该文件会导出一个 [包含了各种配置选项的] 对象:
module.exports = {}
可以使用 @vue/cli-service 提供的 defineConfig
帮手函数,以获得更好的类型提示:
const { defineConfig } = require('@vue/cli-service');
module.exports = defineConfig({});
一些个基本配置
const { defineConfig } = require('@vue/cli-service');
module.exports = defineConfig({
transpileDependencies: true, // 是否将所有文件都编译一遍(通过 babel 编译文件:ES6+ → ES5)
pages: {
index: {
// page 的入口
entry: 'src/index/main.js',
// 模板来源
template: 'public/index.html',
// 在 dist/index.html 的输出
filename: 'index.html',
// 当使用 title 选项时,
// template 中的 title 标签需要是 <%= htmlWebpackPlugin.options.title %>
title: 'Index Page',
// 在这个页面中包含的块,默认情况下会包含
// 提取出来的通用 chunk 和 vendor chunk
chunks: ['chunk-vendors', 'chunk-common', 'index']
},
// 当使用只有入口的字符串格式时,
// 模板会被推导为 `public/subpage.html`
// 并且如果找不到的话,就回退到 `public/index.html`。
// 输出文件名会被推导为 `subpage.html`。
subpage: 'src/subpage/main.js'
}
});
默认情况下 babel-loader 会忽略所有 node_modules 中的文件
为避免构建后的代码中出现未转译的第三方依赖,可以设置 transpileDependencies: true
不过,对所有的依赖都进行转译会降低构建速度
const { defineConfig } = require('@vue/cli-service');
module.exports = defineConfig({ transpileDependencies: true });
数组
作为属性值,列出需要转译的 [第三方包名] / [正则表达式] 即可'warning'
| 'default'
(默认) | 'error'
true
/ 'warning'
:将错误输出为警告,不会影响编译'default'
:将错误输出,会影响编译'error'
:把警告也输出为错误,会影响编译module.exports = { lintOnSave: false } // 关掉检查
devServer.overlay
字段,让浏览器同时显示警告和错误module.exports = {
devServer: { overlay: { warnings: true, errors: true } }
}
lintOnSave
是一个 truthy 的值时,eslint-loader 在 [开发环境] 和 [生产环境] 下都会被启用module.exports = { lintOnSave: process.env.NODE_ENV !== 'production' }
process.env
得知当前环境,并获取对应配置文件内的数据使用 @vue/cli-service 提供的
defineConfig
帮手函数
const { defineConfig } = require('@vue/cli-service');
module.exports = defineConfig({ lintOnSave: false }); // 关闭 eslint 检验
devServer.proxy
,以解决跨域问题devServer.proxy 的 String 写法:值为 [需要代理的服务器地址]
const { defineConfig } = require('@vue/cli-service');
module.exports = defineConfig({
devServer: { proxy: "http://127.0.0.1:5000" /* 需要代理的服务器地址 */ }
});
此时,前端通过 http://127.0.0.1:8080/url路径
获取数据即可
代理服务器就会向 http://127.0.0.1:5000
的 url路径
发请求,以获取数据
如此,我们获取数据时,如果前端 ( public 文件夹 ) 有该数据资源,则直接获取前端资源
如果前端没有该数据资源,则发送请求给 [被代理的服务器] 获取数据(优先匹配前端资源)
这种写法只能代理一台服务器!
devServer.proxy 的 Object 写法:通过 [请求前缀] 配置需要代理的多台服务器
const { defineConfig } = require('@vue/cli-service');
module.exports = defineConfig({
devServer: {
proxy: {
// 通过 [请求前缀] 设置需要代理的多台服务器
'/students': { target: 'http://localhost:5000' },
'/books': { target: 'http://localhost:5001' },
}
}
});
该写法中,[请求前缀] 既是区分服务器的标识,也是要请求的路径
即:前端仍通过 http://127.0.0.1:8080/url路径
获取数据
获取数据时,仍是优先获取前端资源;前端没有该资源,才发送请求给 [被代理的服务器] 获取数据
const { defineConfig } = require('@vue/cli-service');
module.exports = defineConfig({
devServer: {
proxy: {
'/api1': {
target: 'http://localhost:5000',
pathRewrite: { '^/api1': '' } // 隐藏 [请求前缀],保证请求地址能正确使用
},
'/api2': {
target: 'http://localhost:5001',
pathRewrite: { '^/api2': '' } // 隐藏 [请求前缀],保证请求地址能正确使用
},
}
}
});
上例写法中,[请求前缀] 仅为服务器的标识,只要带上 [请求前缀] 就不会匹配前端资源
此时,我们发送请求时,就需要带上 [请求前缀] 以选择发送请求的服务器 http://127.0.0.1:8080/api1/url路径
devServer.proxy 的其他配置项
changeOrigin
:用于控制请求头中的 host 值
为 true
时,服务器收到的请求头中的 host
为 localhost:3000(默认)
为 false
时,服务器收到的请求头中的 host
为 localhost:8080
ws
:为 true
时,表示支持 webSocket(默认)
项目打包后,代码都是经过压缩加密的。如果运行时报错,输出的错误信息无法准确得知是哪里的代码出错
有了 map 文件就可以准确输出是哪里出错;如果项目不需要,可以不对其打包
const { defineConfig } = require('@vue/cli-service');
module.exports = defineConfig({ productionSourceMap: false }); // 不打包
即会弹出基础模版提示,回车即可补全基础模版
<template> template>
<script>
export default {}; // 创建 Vue 实例,并暴露出去(使用默认暴露)
script>
<style> style>
data
必须为函数式声明
data
必须为函数式声明data
仍然是一个纯粹的对象,则所有的实例将共享同一个数据对象!<template> template>
<script>
export default {
name: "componentName",
data() {
return { msg: "superman" };
}
}
script>
<style lang="less" scoped> style>
scoped
属性
默认情况下,组件之间的样式是共享的;后面引入的样式会覆盖前面引用的样式
style
标签设置了 scoped
属性,表示其 CSS 只作用于当前组件中的元素
使用 scoped
后,父组件的样式将不会渗透到子组件中
其原理是,给当前组件的元素添加了 data-v-XXX
属性;应用样式时,也使用属性选择器,实现指定样式的应用
子组件的根节点会同时受其父组件的 scoped
和子组件的 scoped
影响!!!
如果希望 scoped
样式中的一个选择器可以作用得更深,可以使用 >>>
有些预处理器无法正确解析 >>>
,此时我们可以使用 /deep/
/ ::v-deep
代替
<style scoped>
.a >>> .b { /* ... */ }
style>
v-html
创建的 DOM 不受 scoped
样式影响,但仍能通过深度作用选择器设置其样式一般情况下,我们不会给 App.vue 设置 scoped
。因为 App.vue 是根组件,在这里设置的样式,一般都是需要全局应用的
lang="less"
lang="less"
表示使用 Less 编写样式,需要下载插件 less
<style lang="less"> /* 不设置 lang 则默认为 CSS */ style>
浏览器无法解析 less 语法,所以我们需要下载插件 less-loader 将 less 转换为 css
注意:less-loader 依赖于 webpack,需要下载对应的版本
webpack@4 → less-loader@7;webpack@5 → less-loader@8/9
我们可以查看 XXX 的所有版本:npm view XXX versions
npm run build
:打包并生成 dist 文件夹mode
为 history
时,需要下载、配置 connect-history-api-fallback,以解决路由跳转时出现的兼容问题:npm i connect-history-api-fallback
、 ② 配置 connect-history-api-fallbackconst express = require('express');
const app = express();
app.listen(3000);
// 配置 connect-history-api-fallback,否则页面刷新后无法正常显示
const history = require('connect-history-api-fallback');
app.use(history());
app.use(express.static("./public"));