Vue Cli
快速原型开发
你可以使用 vue serve 和 vue build 命令对单个 *.vue 文件进行快速原型开发。
安装@vue/cli-service-global扩展
npm install -g @vue/cli-service-global
准备一个内容原型
vue serve
启动一个服务并运行原型
vue serve Hello.vue
创建项目
vue create
创建一个vue项目
vue create my-vue-test
vue ui
图形化项目管理
vue ui
范例:移植之前创建的cart内容到当前项目中来
插件
Vue Cli使用了一套基于插件的架构。插件可以修改webpack的内部配置,也可以向vue-cli-service注入命令。在项目创建的过程中,绝大部分列出的特性都是通过插件来实现的。
在现有的项目中安装插件
如果你想在一个已经被创建好的项目中安装一个插件,可以使用vue add命令。
vue add router
开发
处理资源路径
当你在JavaScript、CSS或*.vue文件中使用相对路径(必须以’.'开头)引用一个静态资源时,该资源将被webpack处理。
转换规则
- 如果URL是一个绝对路径(例如/images/foo.png),它将会被保留不变。
<img alt="Vue logo" src="/assets/logo.png"> <img alt="Vue logo" src="http://image.xx.com/logo.png">
- 如果URL以
.
开头会作为一个项目木块请求被解释基于文件系统相对路径。<imag 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.vue'
何时使用public文件夹
通过webpack的处理并获得如下好处:
- 脚本和样式表会被压缩且打包在一起,从而避免额外的网络请求。
- 文件丢失会直接在编译时报错,而不是到了用户端才产生404错误
- 最终生成的文件名包含了内容哈希,因此你不必担心浏览器会缓存它们的老版本。
如下情况考虑使用public文件夹 - 你需要在构建输出中制定一个固定的文件名字。
- 你有上千个图片,需要动态引用它们的路径
- 有些库可能和webpack不兼容,处理将其用一个独立的
使用public文件夹的注意事项
- 如果你的应用没有部署在域名的根部,那么你需要为你的URL配置publicPath前缀
// vue.config.js module.exports = { publicPath: process.env.NODE_ENV === 'production' ? '/cart/':'/' }
- 在
public/index.html
等通过html-webpack-plugin
用作模板的HTML文件中,你需要通过<%= BASE_URL %>
设置连接前缀:<link rel="icon" href="<%=BASE_URL%>favicon.ico">
- 在模板中,先向驻足传入BASE_URL:
data() { return { publicPath: process.env.BASE_URL } }
然后:
<img :src="${publicPath}my-image.png">
CSS相关
使用预处理器
如果创建项目时没有选择需要的预处理器(Sass/Less/Stylus),则需要手动安装响应的loader
#Sass
npm install -D sass-loader node-sass
#Less
npm install -D less-loader less
#Stylus
npm install -D stylus-loader stylus
范例:App.vue修改为Sass
<style scoped lang="scss">
$color: #42b983;
a {
color: $color;
}
</style>
自动化导入样式
自动化导入样式文件(用于颜色、变量、mixin等),可以使用style-resources-loader。
npm i -D style-resources-loader
配置
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)))
}
}
Scoped CSS
当
<style scoped>
.red{
color: red;
}
</style>
其原理是通过使用PostCSS来实现以下转换:
<template>
<div class="red"></div>
</template>
<style>
.red[data-v-f3f3g9] {
color: red
}
</style>
其原理是通过使用PostCSS来实现以下转换:
<template>
<div class="red" data-v-f3f3eg9>hi</div>
</template>
<style>
.red[data-v-f3f3eg9] {
color: red
}
</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: rgba(196, 50, 140)
}
::v-deep a {
color: rgb(196, 50, 140)
}
}
</style>
CSS Module
CSS Modules是一个流行的,用于模块化和组合CSS的系统。vue-loader
提供了与CSS Modules的一流继承,可以作为模拟scoped CSS的替代方案。
添加module
<style module lang="scss">
.red {
color: #f00;
}
.bold {
font-weight: bold;
}
</style>
模板中通过$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>
JS中访问
<script>
export default {
created() {
// -> "red_1vyoJ-uz"
// 一个机遇文件名和类名生成的标示符
console.log(this.$style.red)
}
}
</script>
数据访问相关
数据模拟
使用开发服务器配置before选项,可以编写借口,提供模拟数据。
devServer: {
before(app) {
app.get('/api/courses', (req, res) => {
res.json([{ name: '笔记本', price: 8999 }, { name: '台式', price: 4999 }])
} )
}
}
调用
import axios from 'axios'
export function getCourses() {
return axios.get('/api/courses').then(res => res.data)
}
代理
设置开发服务器代理选项可以有效避免调用接口时出现的跨域问题。
devServer: {
proxy: 'http://localhost:3000'
}
测试接口
// 需要安装express: npm i express
const express = require('express')
const app = express()
app.get('/api/courses', (req, res) => {
res.json([{ name: '笔记本', price: 8999 }, { name: '台式', price: 4999 }])
})
app.listen(3000)
相关参数:
proxy: {
'/api': { // '/api':匹配项
target: 'https://10.35.96.20:8320', // 接口域名
secure: false, // 如果是https接口,需要配置这个参数
changeOrigin: true, // 如果接口跨域,需要进行这个参数配置
// pathRewrite: { // 如果接口本身没有/api需要通过pathRewrite来重写地址
// '^api': ''
// }
}
}