文档
https://cn.vuejs.org/v2/guide/
https://cli.vuejs.org/zh/guide
新建项目
https://github.com/2384830985...
# 安装 Vue Cli
npm install -g @vue/cli
# 创建一个项目
vue create hello-world
# 创建完成后,可以通过命令打开图形化界面,如下图所示
vue ui
- vuex-router-sync
vue脚手架自动生成框架的技术分析
VUE启动步骤:public/index.html - main.js - App.vue、router.js
-- main.js将App.vue嵌入public/index.html
的<div id="app"></div>
-- 根据router.js,渲染App的router-view
开发环境
$ node -v
v10.16.1
$ npm -v
6.9.0
安装vue-cli:npm install -g @vue/cli
$ vue -V
3.10.0
创建工程
vue-cli已经被取代!
$ vue create unified-platform-front-yunying
去掉pwa
删除:<li>pwa</li>
去掉dependencies:"register-service-worker": "^1.6.2"
npm uninstall @vue/cli-plugin-pwa
配置
全局配置:$ vue config
配置参考:https://cli.vuejs.org/zh/config/
vue-cli升级到3.x版本之后,构建出来的项目比较简练,但是没有了webpack的显式配置,如果想要脚手架适用自己的项目,就需要配置vue.config.js。
配置完之后可以通过 vue ui 命令打开 vue-cli3 提供的视图界面:任务 -> inspect 来检查 webpack 的配置,也可以使用 vue inspect 来查看某一项的配置。
你可以列出所有规则和插件的名字:
vue inspect --rules
vue inspect --plugins
有些外部工具可能需要通过一个文件访问解析好的 webpack 配置,比如那些需要提供 webpack 配置路径的 IDE 或 CLI。在这种情况下你可以使用如下路径:<projectRoot>/node_modules/@vue/cli-service/webpack.config.js
该文件会动态解析并输出 vue-cli-service 命令中使用的相同的 webpack 配置,包括那些来自插件甚至是你自定义的配置。
vue-cli-service
"@vue/cli-service": "^3.10.0"
在一个 Vue CLI 项目中,@vue/cli-service 安装了一个名为 vue-cli-service 的命令。你可以在 npm scripts 中以 vue-cli-service、或者从终端中以 ./node_modules/.bin/vue-cli-service 访问这个命令。
- vue-cli-service serve
vue-cli-service serve 命令会启动一个开发服务器 (基于 webpack-dev-server) 并附带开箱即用的模块热重载 (Hot-Module-Replacement)。
除了通过命令行参数,你也可以使用 vue.config.js 里的 devServer 字段配置开发服务器。
命令行参数 [entry] 将被指定为唯一入口,而非额外的追加入口。尝试使用 [entry] 覆盖 config.pages 中的 entry 将可能引发错误。
- vue-cli-service build
vue-cli-service build 会在 dist/ 目录产生一个可用于生产环境的包,带有 JS/CSS/HTML 的压缩,和为更好的缓存而做的自动的 vendor chunk splitting。它的 chunk manifest 会内联在 HTML 里。
- vue-cli-service inspect
你可以使用 vue-cli-service inspect 来审查一个 Vue CLI 项目的 webpack config。更多细节请查阅审查 webpack config。
缓存和并行处理
cache-loader 会默认为 Vue/Babel/TypeScript 编译开启。文件会缓存在 node_modules/.cache 中——如果你遇到了编译方面的问题,记得先删掉缓存目录之后再试试看。
thread-loader 会在多核 CPU 的机器上为 Babel/TypeScript 转译开启。
配置时无需 Eject
通过 vue create 创建的项目无需额外的配置就已经可以跑起来了。插件的设计也是可以相互共存的,所以绝大多数情况下,你只需要在交互式命令提示中选取需要的功能即可。
浏览器兼容性
browserslist
https://github.com/browsersli...
browserslist 是在不同的前端工具之间共用目标浏览器和 node 版本的配置工具。它主要被以下工具使用:
Autoprefixer
Babel
post-preset-env
eslint-plugin-compat
stylelint-unsupported-browser-features
postcss-normalize
链接:https://juejin.im/post/5b8cff326fb9a019fd1474d6
Polyfill
一个默认的 Vue CLI 项目会使用 @vue/babel-preset-app,它通过 @babel/preset-env 和 browserslist 配置来决定项目需要的 polyfill。
默认情况下,它会把 useBuiltIns: 'usage' 传递给 @babel/preset-env,这样它会根据源代码中出现的语言特性自动检测需要的 polyfill。这确保了最终包里 polyfill 数量的最小化。然而,这也意味着如果其中一个依赖需要特殊的 polyfill,默认情况下 Babel 无法将其检测出来。
现代模式
Vue CLI 提供了一个“现代模式”帮你解决这个问题。以如下命令为生产环境构建:
vue-cli-service build --modern
Vue CLI 会产生两个应用的版本:一个现代版的包,面向支持 ES modules 的现代浏览器,另一个旧版的包,面向不支持的旧浏览器。
最酷的是这里没有特殊的部署要求。其生成的 HTML 文件会自动使用 Phillip Walton 精彩的博文中讨论到的技术:
现代版的包会通过 <script type="module"> 在被支持的浏览器中加载(需要配合始终开启的 CORS 进行加载);它们还会使用 <link rel="modulepreload"> 进行预加载。
旧版的包会通过 <script nomodule> 加载,并会被支持 ES modules 的浏览器忽略。
一个针对 Safari 10 中 <script nomodule> 的修复会被自动注入。
对于一个 Hello World 应用来说,现代版的包已经小了 16%。在生产环境下,现代版的包通常都会表现出显著的解析速度和运算速度,从而改善应用的加载性能。
HTML 和静态资源
index.html
public/index.html 文件是一个会被 html-webpack-plugin 处理的模板。在构建过程中,资源链接会被自动注入。
构建一个多页应用
不是每个应用都需要是一个单页应用。Vue CLI 支持使用vue.config.js 中的 pages 选项构建一个多页面的应用。构建好的应用将会在不同的入口之间高效共享通用的 chunk 以获得最佳的加载性能。
注:https://juejin.im/post/5bd128...
处理静态资源
静态资源可以通过两种方式进行处理:
在 JavaScript 被导入或在 template/CSS 中通过相对路径被引用。这类引用会被 webpack 处理。
放置在 public 目录下或通过绝对路径被引用。这类资源将会直接被拷贝,而不会经过 webpack 的处理。
public 文件夹
任何放置在 public 文件夹的静态资源都会被简单的复制,而不经过 webpack。你需要通过绝对路径来引用它们。
注意我们推荐将资源作为你的模块依赖图的一部分导入,这样它们会通过 webpack 的处理并获得如下好处:
脚本和样式表会被压缩且打包在一起,从而避免额外的网络请求。
文件丢失会直接在编译时报错,而不是到了用户端才产生 404 错误。
最终生成的文件名包含了内容哈希,因此你不必担心浏览器会缓存它们的老版本。
public 目录提供的是一个应急手段,当你通过绝对路径引用它时,留意应用将会部署到哪里。如果你的应用没有部署在域名的根部,那么你需要为你的 URL 配置 publicPath 前缀。
环境变量和模式
环境变量
你可以替换你的项目根目录中的下列文件来指定环境变量:
.env # 在所有的环境中被载入
.env.local # 在所有的环境中被载入,但会被 git 忽略,只在本地有效的变量
.env.[mode] # 只在指定的模式中被载入
.env.[mode].local # 只在指定的模式中被载入,但会被 git 忽略,只在本地有效的变量
被载入的变量将会对 vue-cli-service 的所有命令、插件和依赖可用。
为一个特定模式准备的环境文件的 (例如 .env.production) 将会比一般的环境文件 (例如 .env) 拥有更高的优先级。
此外,Vue CLI 启动时已经存在的环境变量拥有最高优先级,并不会被 .env 文件覆写。
如果在环境中有默认的 NODE_ENV,你应该移除它或在运行 vue-cli-service 命令的时候明确地设置 NODE_ENV。
模式
默认情况下,一个 Vue CLI 项目有三个模式:
development 模式用于 vue-cli-service serve
production 模式用于 vue-cli-service build 和 vue-cli-service test:e2e
test 模式用于 vue-cli-service test:unit
注意模式不同于 NODE_ENV,一个模式可以包含多个环境变量。也就是说,每个模式都会将 NODE_ENV 的值设置为模式的名称——比如在 development 模式下 NODE_ENV 的值会被设置为 "development"。
可以通过传递 --mode 选项参数为命令行覆写默认的模式。
在客户端侧代码中使用环境变量
只有以 VUE_APP_ 开头的变量会被 webpack.DefinePlugin 静态嵌入到客户端侧的包中。你可以在应用的代码中这样访问它们:
console.log(process.env.VUE_APP_SECRET)
除了 VUE_APP_* 变量之外,在你的应用代码中始终可用的还有两个特殊的变量:
NODE_ENV - 会是 "development"、"production" 或 "test" 中的一个。具体的值取决于应用运行的模式。
BASE_URL - 会和 vue.config.js 中的 publicPath 选项相符,即你的应用会部署到的基础路径。
所有解析出来的环境变量都可以在 public/index.html 中以 HTML 插值中介绍的方式使用。
你可以在 vue.config.js 文件中计算环境变量。它们仍然需要以 VUE_APP_ 前缀开头。这可以用于版本信息 process.env.VUE_APP_VERSION = require('./package.json').version。
注意:process.env,只能在代码中使用,一旦启动,无法在浏览器中访问!!
构建目标
应用模式是默认的模式。在这个模式中:
index.html 会带有注入的资源和 resource hint
第三方库会被分到一个独立包以便更好的缓存
小于 4kb 的静态资源会被内联在 JavaScript 中
public 中的静态资源会被复制到输出目录中
库的使用
如何在 Vue 项目中使用 echarts
推荐直接引入echarts,如下
安装echarts项目依赖
npm install echarts --save
"dependencies": { "echarts": "^4.5.0" },
VUE文件中引入
import echarts from 'echarts' require('echarts/theme/macarons') // echarts theme import resize from './mixins/resize' // 我们自己写的,可忽略
echarts4.5.0时,以下不需要
// 引入饼图组件 require('echarts/lib/chart/pie') // 引入柱状图组件 require('echarts/lib/chart/bar') // 引入提示框和title组件 require('echarts/lib/component/tooltip') require('echarts/lib/component/title')
示例如下
<template>
<div :class="className" : />
</template>
<script>
import echarts from 'echarts'
require('echarts/theme/macarons') // echarts theme
import resize from './mixins/resize'
const animationDuration = 6000
export default {
mixins: \[resize\],
props: {
className: {
type: String,
default: 'chart'
},
width: {
type: String,
default: '100%'
},
height: {
type: String,
default: '450px'
},
chartData: {
type: Object,
required: true
}
},
data() {
return {
chart: null
}
},
watch: {
chartData: {
deep: true,
handler(val) {
this.setOptions(val)
}
}
},
mounted() {
// nextTick里面的代码会在DOM更新后执行
this.$nextTick(() => {
this.initChart()
})
},
beforeDestroy() {
if (!this.chart) {
return
}
this.chart.dispose()
this.chart = null
},
methods: {
initChart() {
// this.$el,指的是当前组件的的元素。是在mounted页面渲染后(nextTick)才会出现的,在created的时候是没有的
this.chart = echarts.init(this.$el, 'macarons')
this.setOptions(this.chartData)
},
setOptions({ legendData, xAxisData, series } = {}) {
if(null == xAxisData || xAxisData.length < 1 || null == series || series.length < 1){
return
}
const seriesDefault = \[\]
for (let i = 0, len = series.length; i < len; i++) {
const item = Object.assign({}, series\[i\])
// item.name = item.name
// item.data = item.data
item.type = 'bar'
item.barGap = item.barGap || '0'
item.barCategoryGap = item.barCategoryGap || '40%'
item.animationDuration = item.animationDuration || animationDuration
seriesDefault.push(item)
}
this.chart.setOption({
color: \[
'#94d2fb', '#bfdfab'
\],
tooltip: {
trigger: 'axis',
textStyle: {
fontSize: 14
}
},
toolbox: {
show: false
},
legend: {
x: 'left',
data: legendData
},
grid: {
bottom: 90
},
dataZoom: \[{
type: 'inside'
}, {
type: 'slider'
}\],
xAxis: \[
{
type: 'category',
axisLabel: {
rotate: 30,
interval: 0
},
axisLine: { show: false },
splitLine: { show: false },
data: xAxisData
}
\],
yAxis: \[
{
type: 'value',
name: '',
axisLabel: {
formatter: '{value}'
},
axisLine: { show: false },
splitNumber: 8
}
\],
series: seriesDefault
})
部署
通用指南
如果你用 Vue CLI 处理静态资源并和后端框架一起作为部署的一部分,那么你需要的仅仅是确保 Vue CLI 生成的构建文件在正确的位置,并遵循后端框架的发布方式即可。
-- 即本项目采用的方式,后端是unified-platform/web
如果你独立于后端部署前端应用——也就是说后端暴露一个前端可访问的 API,然后前端实际上是纯静态应用。那么你可以将 dist 目录里构建的内容部署到任何静态文件服务器中,但要确保正确的 publicPath。
本地预览
dist 目录需要启动一个 HTTP 服务器来访问 (除非你已经将 publicPath 配置为了一个相对的值),所以以 file:// 协议直接打开 dist/index.html 是不会工作的。
history 模式
vue-router 默认 hash 模式 —— 使用 URL 的 hash 来模拟一个完整的 URL,于是当 URL 改变时,页面不会重新加载。
如果不想要很丑的 hash,我们可以用路由的 history 模式,这种模式充分利用 history.pushState API 来完成 URL 跳转而无须重新加载页面。
当你使用 history 模式时,URL 就像正常的 url,例如 http://yoursite.com/user/id,也好看!
所以呢,你要在服务端增加一个覆盖所有情况的候选资源:如果 URL 匹配不到任何静态资源,则应该返回同一个 index.html 页面,这个页面就是你 app 依赖的页面。
- nginx
location / {
try_files $uri $uri/ /index.html;
}
注:若是tomcat、jetty,则需要在WEB-INF目录下的web.xml文件中添加如下<error-code>404</error-code>
,以便在vue的index.html中重新路由(router在这里设置了路由跳转)
<error-page>
<error-code>404</error-code>
<location>/index.html</location>
</error-page>
https://segmentfault.com/a/1190000010379441
注:我们本质是单页面(多个单页面),需要支持/giftpack/index的形式直接url访问,故也有vue-router问题。
ANS:单独npm run serve启动前端,是没有问题,可直接访问http://localhost:9092/unified-platform-web/yunying/giftpack/index,
但是,若和后端框架一起作为部署的一部分,如resin、jetty中,则无法直接访问http://localhost:8092/unified-platform-web/yunying/giftpack/index!!
axios
在main.js中如下声明使用
import axios from 'axios';
Vue.prototype.$axios=axios;
那么在其他vue组件中就可以this.$axios调用使用
http request 请求拦截器
axios.interceptors.request.use(
config => {
if (token) { // 每次发送请求之前判断是否存在token,如果存在,则统一在http请求的header都加上token,不用每次请求都手动添加了
config.headers.Authorization = token;
}
return config;
},
err => {
return Promise.reject(err);
}
);
设置默认参数:
this.$axios.defaults.headers.common['sign'] = sign;
catch也会捕获then中的异常!
修改contextPath
1.修改vue.config.js
publicPath: '/unified-platform-web/front_yunying/' -- 默认是‘/’。 静态文件,都会自动寻址...${publicPath}/123.css。
2.修改router
vue-router配置base的路径,这个路径默认是‘/’,把配置改成base: '/unified-platform-web/front_yunying'
-- 可直接访问路由:http://localhost:9092/unified-platform-web/front_yunying/giftpack/all
将dist下生成的文件,复制到后端webapp/front_yunying中(后端的contextpath=/unified-platform-web)
注:devServer.proxy,需要特殊处理,避免本地serve启动时静态文件也指向代理地址
vue-router
获取url参数:var sign = this.$route.query.sign;
获取路由参数:$route.params.id
点击 <router-link :to="..."> 等同于调用 router.push(...)
在 Vue 实例内部,你可以通过 $router 访问路由实例。
对于同一个路由User组件,不同路由参数,例如从 /user/foo 导航到 /user/bar,原来的组件实例会被复用。因为两个路由都渲染同个组件,比起销毁再创建,复用则显得更加高效。不过,这也意味着组件的生命周期钩子不会再被调用。
复用User组件时,想对路由参数的变化作出响应的话,你可以简单地在User中 watch (监测变化) $route 对象,或者使用 2.2 中引入的 beforeRouteUpdate 导航守卫。
当使用一个通配符时,$route.params 内会自动添加一个名为 pathMatch 参数。
<router-view> 是最顶层的出口,渲染最高级路由匹配到的组件。同样地,一个被渲染组件同样可以包含自己的嵌套 <router-view>
没有匹配到合适的子路由,则子路由占位符不会渲染任何东西。如果你想要渲染点什么,可以提供一个 空的 子路由。
router.go(n) - 这个方法的参数是一个整数,意思是在 history 记录中向前或者后退多少步,类似 window.history.go(n)
<router-link :to="{ name: 'user', params: { userId: 123 }}">User</router-link>
等价于router.push({ name: 'user', params: { userId: 123 }})
可以在界面中拥有多个单独命名的视图,而不是只有一个单独的出口。如果 router-view 没有设置名字,那么默认为 default。如`<router-view class="view three" name="b"></router-view>
一个视图使用一个组件渲染,因此对于同个路由,多个视图就需要多个组件。
const router = new VueRouter({
routes: [
{
path: '/',
components: {
default: Foo,
a: Bar,
b: Baz
}
}
]
})
完整的导航解析流程
导航被触发。
在失活的组件里调用离开守卫。
调用全局的 beforeEach 守卫。
在重用的组件里调用 beforeRouteUpdate 守卫 (2.2+)。
在路由配置里调用 beforeEnter。
解析异步路由组件。
在被激活的组件里调用 beforeRouteEnter。
调用全局的 beforeResolve 守卫 (2.5+)。
导航被确认。
调用全局的 afterEach 钩子。
触发 DOM 更新。
用创建好的实例调用 beforeRouteEnter 守卫中传给 next 的回调函数。
Vue2.0的三种常用传值方式、父传子、子传父、非父子组件传值
https://blog.csdn.net/lander_...
https://blog.csdn.net/cckevin...
父组件向子组件传值: 使用props属性来定义父组件传递过来的数据
子组件中data和props的区别:
子组件中的data数据,不是通过父组件传递的是子组件私有的,是可读可写的。
子组件中的所有 props中的数据,都是通过父组件传递给子组件的,是只读的。
子组件向父组件传值: 父组件将方法的引用,传递到子组件内部,子组件在内部调用父组件传递过来的方法,同时把要发送给父组件的数据,在调用方法的时候当作参数传递进去
父组件:<son @func="getMsg"></son>
子组件:this.$emit('func', 'OK'); // 调用父组件传递过来的方法,同时把数据传递出去
非父子组件之间传值,需要定义个公共的公共实例文件bus.js,作为中间仓库来传值,不然路由组件之间达不到传值的效果
//bus.js
import Vue from 'vue'
export default new Vue()
// 组件A
// 引入公共的bug,来做为中间传达的工具
import Bus from './bus.js'
Bus.$emit('val', this.elementValue)
// 组件B
// 引入公共的bug,来做为中间传达的工具
import Bus from './bus.js'
// 用$on事件来接收参数
Bus.$on('val', (data) => {
console.log(data)
vm.name = data
})
v-model上绑定一个 vuex 值
使用 computed 的 set 和 get 方法,你也可以把它当做一个 watch的升级版。它可以监听数据的变化,当发生变化时,做一些额外的操作。最经典的用法就是v-model上绑定一个 vuex 值的时候,input 发生变化时,通过 commit更新存在 vuex 里面的值。
多环境开发
rem适配方案
还是那句话,用vw还是用rem,这是个问题?
选用rem的原因是因为vant直接推荐了这个适配方案,直接上手:
Vant 中的样式默认使用px作为单位,如果需要使用rem单位,推荐使用以下两个工具
- postcss-pxtorem 是一款 postcss 插件,用于将单位转化为 rem
也可用:postcss-px2rem-exclude
- lib-flexible 用于设置 rem 基准值
下面提供了一份基本的 postcss 配置,可以在此配置的基础上根据项目需求进行修改
module.exports = {
plugins: {
'autoprefixer': {
browsers: ['Android >= 4.0', 'iOS >= 7']
},
'postcss-pxtorem': {
rootValue: 37.5,
propList: ['*']
}
}
}
移动端console.log
- vconsole(在移动端查看调试器)
常见运行依赖
- qs
- lodash
- moment
- vue-router(路由跳转)
- axios(数据请求)
- vuex(状态管理)
- vue-awesome-picker
- vue-awesome-swiper
- vue-lazyload(图片懒加载)
- fastclick(解决移动端浏览器 300 毫秒点击延迟问题)
- vue-touch(手势判断)
常见开发依赖
- @vue/cli-plugin-eslint
- @vue/cli-plugin-babel
- @vue/cli-plugin-pwa
- @vue/cli-service
- @vue/eslint-config-standard
- http-push-webpack-plugin
- compression-webpack-plugin
- html-webpack-inline-source-plugin
- px2rem-loader
- cross-env
- mock.js(模拟后台数据)
生产环境使用CDN
优化方案
- 腾讯智图(压缩图片,减少图片的体积)
- vue-lazyload(图片懒加载,缓解加载数据,提高网页性能)
- fastclick(解决移动端300ms延迟,提高页面交互流畅度)
- vue-rouer(路由懒加载,分离app的js为多个js文件,到对应的页面再执行对应的js)
- webpack(config/index.js文件内的productionSourceMap改为false,这样打包出来的文件可以没有.map结尾的js文件,且文件体积减少至少一半)
- Vuex刷新保存状态
使用Vuex做状态管理的时候,当用户刷新页面,Vuex里面的状态会全部丢失,从而引起程序的一场。解决思路是在creared()钩子函数里面添加以下方法:
created(){
console.log('页面执行刷新时,保存Vuex的状态到LocalStorage')
//在页面加载时读取localStorage里的状态信息
localStorage.getItem("userMsg") && this.$store.replaceState(Object.assign(this.$store.state,JSON.parse(localStorage.getItem("userMsg"))));
//在页面刷新时将vuex里的信息保存到localStorage里
window.addEventListener("beforeunload",()=>{
localStorage.setItem("userMsg",JSON.stringify(this.$store.state))
})
}
上面代码的原理是,当页面刷新时,会将当前Vuex的状态存储到LocalStorage里面,刷新成功,再从LocalStorage赋值到Vuex里面.
pwa
https://github.com/JXtreehous...
https://zhuanlan.zhihu.com/p/...
错误监控
持续集成服务 Travis CI/ gitlab-ci
项目升级vue cli3
vue-cli3 项目从搭建优化到docker部署
通过vue-cli3构建一个SSR应用程序
常见问题
关于tunneling socket could not be established , cause=getaddrinfo ENOTFOUND 错误的解决方法
初始化一个vue项目的时候,出现了一些问题
因为我的代理设置的是这个:
团队建设
生鲜 B2B 技术平台的前端团队该如何搭建
技术栈:小菜前端的技术栈是如何规划和演进的
技术栈:为什么 Node 是小菜前端团队的核心技术栈
架构
大型项目前端架构浅谈
Vue 项目架构设计与工程化实践
前端工程师必备:前端的模块化
用 Feature First 的方式管理前端项目复杂度
参考
封装Vue组件的一些技巧
基于vue-cli3.0构建功能完善的移动端架子
「Vue实践」武装你的前端项目
Vue CLI 3结合Lerna进行UI框架设计
技术地图 - vue-cli
一张图教你快速玩转vue-cli3
Vue全家桶商城全站升级之引入HTTPS,PWA,错误监控,持续构建。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。