Vue Cli
一、 快速原型开发
你可以使用 vue serve 和 vue build 命令对单个 *.vue 文件进行快速原型开发
1.1 安装 @vue/cli-service-global 扩展
npm install -g @vue/cli-service-global
1.2 准备一个内容原型
Hello.vue
<template>
<div>
<div v-for="item in items" :key="item.id">
{
{ item }}
</div>
</div>
</template>
<script>
export default {
data() {
return {
key: value
}
},
methods: {
name() {
}
},
}
</script>
<style lang="scss" scoped>
</style>
1.3 vue serve
启动一个服务并运行原型
vue serve Hello.vue
二、创建项目
vue create
创建一个新项目
vue create hello-world
使用图形化界面
vue ui
<template>
<div class="home">
home
<HelloWorld/>
</div>
</template>
<script>
// @ is an alias to /src
// @是/src的别名
import HelloWorld from '@/components/HelloWorld.vue'
export default {
name: 'Home',
components: {
HelloWorld
}
}
</script>
范例:移植之前创建的cart内容到当前项目中
//CourseList.vue
props: {
courses: {
type: Array,
// 对象或数组默认值必须从一个工厂函数获取
default: function() {
return [];
},
},
},
Vue.component('my-component', {
props: {
// 基础的类型检查 (`null` 和 `undefined` 会通过任何类型验证)
propA: Number,
// 多个可能的类型
propB: [String, Number],
// 必填的字符串
propC: {
type: String,
required: true
},
// 带有默认值的数字
propD: {
type: Number,
default: 100
},
// 带有默认值的对象
propE: {
type: Object,
// 对象或数组默认值必须从一个工厂函数获取
default: function () {
return {
message: 'hello' }
}
},
// 自定义验证函数
propF: {
validator: function (value) {
// 这个值必须匹配下列字符串中的一个
return ['success', 'warning', 'danger'].indexOf(value) !== -1
}
}
}
})
三、插件
Vue CLI 使用了一套基于插件的架构。插件可以修改 webpack 的内部配置,也可以向 vue-cli-service 注入命令。在项目创建的过程中,绝大部分列出的特性都是通过插件来实现的。
3.1 现有的项目中安装插件
如果你想在一个已经被创建好的项目中安装一个插件,可以使用 vue add
命令
vue add eslint
vue add router
四、开发
4.1 处理资源资源
静态资源可以通过两种方式进行处理:
- 在 JavaScript 被导入或在 template/CSS 中通过相对路径被引用。这类引用会被 webpack 处理。
- 放置在 public 目录下或通过绝对路径被引用。这类资源将会直接被拷贝,而不会经过 webpack 的处理。
4.1.1 从相对路径导入
当你在 JavaScript、CSS 或 *.vue
文件中使用相对路径 (必须以 . 开头) 引用一个静态资源时,该资源将会被包含进入 webpack 的依赖图中。在其编译过程中,所有诸如 <img src="...">
、background: url(...)
和CSS @import
的资源 URL 都会被解析为一个模块依赖。
4.1.2 转换规则
- 如果 URL 是一个绝对路径 (例如 /images/foo.png),它将会被保留不变。
<img alt="Vue logo" src="/assets/logo.png" /> <!-- logo.png放在public下 -->
<img alt="Vue logo" src="http://image.xx.com/logo.png" />
- 如果 URL 以 . 开头,它会作为一个相对模块请求被解释且基于你的文件系统中的目录结构进行解析。
<img alt="Vue logo" src="./assets/logo.png" />
- 如果 URL 以 ~ 开头,其后的任何内容都会作为一个模块请求被解析。这意味着你甚至可以引用 Node 模块中的资源:
<img src="~some-npm-package/foo.png">
- 如果 URL 以 @ 开头,它也会作为一个模块请求被解析。它的用处在于 Vue CLI 默认会设置一个指向 /src 的别名 @。(仅作用于模版中)
//直接使用
import Hello from "@/components/Hello";
4.1.2 何时使用 public 文件夹
通过 webpack 的处理并获得如下好处:
- 脚本和样式表会被压缩且打包在一起,从而避免额外的网络请求。
- 文件丢失会直接在编译时报错,而不是到了用户端才产生 404 错误。
- 最终生成的文件名包含了内容哈希,因此你不必担心浏览器会缓存它们的老版本。
如下情况考虑使用 public 文件夹
- 你需要在构建输出中指定一个文件的名字。
- 你有上千个图片,需要动态引用它们的路径。
- 有些库可能和 webpack 不兼容,这时你除了将其用一个独立的
使用public文件夹注意事项
- 如果你的应用没有部署在域名的根部,那么你需要为你的 URL 配置 publicPath 前缀
// vue.config.js
module.exports = {
publicPath: process.env.NODE_ENV === 'production'
? '/production-sub-path/'
: '/'
}
- 在
public/index.html
或其它通过html-webpack-plugin
用作模板的 HTML 文件中,你需要通过<%= BASE_URL %>
设置链接前缀
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
- 在模板中,你首先需要向你的组件传入基础 URL
data () {
return {
publicPath: process.env.BASE_URL // /c/
}
}
然后:
<img :src="`${publicPath}assets/logo.png`"> <!-- logo.png 放在src/assets/logo.png-->
五、CSS相关
<style lang="scss" scoped>
.inp{
margin: 5px;
}
</style>
5.1 使用预处理器
如果创建项目的时候没有选择预处理器 (Sass/Less/Stylus),则需要手动安装相应的 webpack loader
# Sass
npm install -D sass-loader node-sass
# Less
npm install -D less-loader less
# Stylus
npm install -D stylus-loader stylus
5.2 自动化导入样式
自动化导入文件 (用于颜色、变量、mixin……)
步骤一:你可以使用 style-resources-loader
vue add style-resources-loader
style-resources-loader 的作用
导入css 预处理器的一些公共的样式文件变量,比如:variables , mixins ,
functions,避免在每个样式文件中手动的@import导入,然后在各个css 文件中直接使用 变量。
步骤二:配置
// vue.config.js 官网
const path = require('path')
module.exports = {
chainWebpack: config => {
const types = ['vue-modules', 'vue', 'normal-modules', 'normal']
types.forEach(type => addStyleResource(config.module.rule('stylus').oneOf(type)))
},
}
function addStyleResource (rule) {
rule.use('style-resource')
.loader('style-resources-loader')
.options({
patterns: [
path.resolve(__dirname, './src/styles/imports.styl'),
],
})
}
实际代码应用
// vue.config.js
const path = require("path");
function addStyleResource(rule) {
rule
.use("style-resource")
.loader("style-resources-loader")
.options({
patterns: [path.resolve(__dirname,
"./src/styles/imports.scss")],
});
}
module.exports = {
chainWebpack: (config) => {
const types = ["vue-modules", "vue", "normal-modules", "normal"];
types.forEach((type) =>
addStyleResource(config.module.rule("scss").oneOf(type))
);
},
};
<!--app.vue -->
<a href="">自动化导入样式</a>
<style lang="scss" >
a {
color: $color; }
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
</style>
结果:
5.3 Scoped CSS
当 <style>
标签有 scoped
属性时,它的 CSS 只作用于当前组件中的元素。
<style scoped>
.red {
color: red;
}
</style>
其原理是通过使用 PostCSS 来实现以下转换:
<template> <div class="red" data-v-f3f3eg9>hi</div> </template> <style> .red[data-v-f3f3eg9] { color: red; } </style>
例子
<!--hellloworld.vue-->
<template>
<div class="hello">
......
</div>
</template>
<style scoped>
/*app.vue*/
#app{
background: #ccc;
}
.hello{
border: 4px solid rgb(5, 231, 92); //有作用
}
.hello p {
color: blue; //没有作用
}
</style>
结论:在父组件可以影响子组件的根元素,仅限于
根元素
混用本地和全局
<style>
/* 全局样式 */
</style>
<style scoped>
/* 本地样式 */
</style>
深度作用选择器:使用 >>>
操作符可以使 scoped
样式中的一个选择器能够作用得“更深”,例如影响子组件
<style scoped>
#app >>> a {
color: red
}
</style>
Sass 之类的预处理器无法正确解析
>>>
。这种情况下你可以使用/deep/
或::v-deep
操作符 取而代之<style scoped lang="scss"> #app { /deep/ a { color: rgb(196, 50, 140) } ::v-deep a { color: rgb(196, 50, 140) } } </style>
结论:
如果自定义子组件是自己的,没有使用>>>的必要
如果修改第三方库的样式可以使用深度作用选择器
5.4 CSS Module
CSS Modules 是一个流行的,用于模块化和组合 CSS 的系统。 vue-loader 提供了与 CSS Modules 的一流集成,可以作为模拟 scoped CSS 的替代方案。
1.添加module
<style module lang="scss">
.red {
color: #f00;
}
.bold {
font-weight: bold;
}
</style>
2.模板中通过$style.xx访问
<a :class="$style.red">awesome-vue</a>
<a :class="{[$style.red]:isRed}">awesome-vue</a>
<a :class="[$style.red, $style.bold]">awesome-vue</a>
3.JS中访问
<script>
export default {
created () {
// -> "red_1VyoJ-uZ"
// 一个基于文件名和类名生成的标识符
console.log(this.$style.red)
}
}
</script>
六、数据访问相关
Vue CLI – 配置参考 – devServer
6.1 数据模拟
使用开发服务器配置before选项,可以编写接口,提供模拟数据。
//vue.config.js
devServer:{
before(app) {
app.get('/api/foods', (req, res) => {
res.json([{
name: '萝卜', price: 100}, {
name: '白菜', price: 50}])
})
}
}
调用
npm i axios --save
//fooed.js
import axios from 'axios'
export function getFoods() {
return axios.get('/api/foods').then(res => res.data);
}
//foodlist.vue
import {
getFoods } from "@/api/foods";
async created() {
const res = await getFoods();
this.list = res;
}
在地址栏测试接口
http://localhost:8080/api/foods
6.2 代理
设置开发服务器代理选项可以有效避免调用接口时出现的跨域问题。
如果你的前端应用和后端 API 服务器没有运行在同一个主机上,你需要在开发环境下将 API 请求代理到 API 服务器。这个问题可以通过 vue.config.js 中的 devServer.proxy 选项来配置。
devServer.proxy 可以是一个指向开发环境 API 服务器的字符串:
module.exports = {
devServer: {
proxy: 'http://localhost:3000'
}
}
测试接口
//启动命令
node ./server/api.js
在地址栏测试接口
http://localhost:3000/api/foods