现在的前端发展可以说是日新月异,新技术、新东西层出不穷。新技术、新东西的出现带来的变化便是开发模式的转变。传统的开发模式已经慢慢地被前后端分离模式所取代。正是这种开发模式的转变,使得前端开发人员要学习的东西越来越多,技术水平要求也越来越高。
纵观前端的发展历程:jQuery处理了浏览器的兼容性问题,方便了DOM操作;Vue、Angular、React以MV*模式取代了传统的DOM操作,以数据驱动视图,极大的提高了页面性能。以目前的发展趋势来看,MV*模式将会成为未来前端发展的主流方向。
使用vue-cli开发的同学,笔者建议使用最新稳定版的VS Code,原因如下:
1、一款好的编辑器能极大提高工作效率,这就是我们常说的:工欲善其事,必先利其器。
2、VS Code是近几年“异军突起”的一款免费开源软件,小巧、轻便、启动迅速、资源占用低,合理的插件扩展让你书写代码有一种畅快淋漓感。
如何让WebStrom忽略node_modules的索引
用WebStrom开发的同学,应该会发现WebStrom在打开一个项目的时候会有一个索引过程。如果电脑配置不高的同学,打开一个带有node_modules文件夹的项目,那简直就是一场“灾难”。为了提高打开速度,避免每次“灾难”的重现,我们可以这样做:
File -> Setting -> Editor -> File types -> Ignore files and folders
在Ignore files and folders最后加上node_modules;保存就可以了,然后重启WebStorm一切就将改变。
特别说明,以下是针对vue2.0总结的问题,部分通用于vue1.0。
提醒:npm install等价于npm i,--save等价于-S,--save-dev等价于-D。一个是完整命令,一个是快捷命令。npm cache clean的别名为npm cache clear和npm cache rm。
使用vue-cli构建vue项目
理由:vue-cli用于快速构建vue的应用。它的优点是进一步屏蔽了很多配置的步骤、自动按官方推荐的模式进行代码组织、自动生成组件/服务等模板以及更方便的发布和测试代码。
特别说明:$符号是某些类DOS系统特有的,后面才是真正的执行命令(敲入$之后的命令即可),很多新手都会在这里犯错。
1、安装Node最新版本(推荐使用LTS版,该版本为长期稳定版)
2、替换npm为淘宝镜像(如无必要,尽量不要使用镜像)
---->卸载cnpm命令(npm uninstall cnpm -g),此条只针对全局安装过cnpm的人
注:打开DOS面板,执行npm config set registry https://registry.npm.taobao.org
如果想恢复默认,打开DOS面板,执行npm config set registry https://registry.npmjs.org
特别说明:替换npm为淘宝镜像原因是因为npm在国内访问不太稳定。当然,如果你的网络访问npm没问题,可忽略这步;
特别强调:淘宝镜像和cnpm是不一样的,这里设置的是淘宝镜像而不是cnpm。经过笔者多次踩坑和血淋淋的教训得出的结论——珍爱生命,远离cnpm;
3、安装vue-cli(建议先清一下缓存:npm cache clean)
npm install vue-cli -g
4、初始化项目
vue init webpack vue-demo
注:此处的webpack和vue-demo可以替换为别的,根据项目使用的模版选择对应的即可。如果是学习vue使用,建议使用webapck模板。
特别说明:安装过程中会有提示,根据提示走即可,回车或输入对应命令即可进行下一步
友情提示:Vue build有两种方式(这两种打包方式对用户没区别)
第一种是Runtime + Compiler方式——打包的是/node_modules/vue/dist/vue.js
第二种是Runtime-only方式——打包的是/node_modules/vue/dist/vue.common.js
当我们使用.vue文件开发时,推荐使用Runtime-only,这样可以让体积减轻6k左右。
5、项目初始化完成后,根据提示进行即可
vue文件中使用Scss/Stylus/Less
特别说明:以下操作是针对使用webpack模版初始化项目的。
1、如果想在vue组件中使用Scss,需要在package.json里的devDependencies加node-sass和sass-loader
特别提醒:vue组件里的style里需加上lang="scss",这样才能被webpack识别
1、如果想在vue组件中使用Stylus,需要在package.json里的devDependencies加stylus和stylus-loader
特别提醒:vue组件里的style里需加上lang="stylus",这样才能被webpack识别。
高能预警:这里用的是stylus-loader而不是style-loader;stylus对缩进要求极其严苛,这点真的和Python很像,你不注意,webpack就敢给你报错,所以请注意缩进。
1、如果想在vue组件中使用Less,需要在package.json里的devDependencies加less和less-loader
特别提醒:vue组件里的style里需加上lang="less",这样才能被webpack识别
2、.eslintrc.js文件加入
- // 允许自由缩进
- 'indent': 0,
- // JS语句必须以分号结束
'semi': ['error', 'always'], - // 允许使用宽松运算符
- 'eqeqeq': 0,
- // 允许三目运算中使用布尔值
- 'no-unneeded-ternary': 0,
- // 允许使用表达式
- 'no-unused-expressions': 0,
- // 函数定义时,function关键字后面不加空格
- 'space-before-function-paren': 0
特别说明:如果你没有选择eslint规范JS代码,可忽略这步(此代码是笔者常用配置项)。具体如何配置,参考eslint官网
3、重新npm install
4、安装完成,执行npm run dev就可以了
5、按提示进行修改即可
特别说明:此处修改是因为刚才咱们配置过eslint导致的报错,按提示修改代码即可
如何在全局引入Scss的变量声明
笔者习惯于使用Scss,因此给出Scss的解决方法,其它CSS预处理器自行搜索。
相信很多朋友已经习惯于在用到Scss变量的组件中每次导入Scss变量文件的做法。这种做法代价较高且依赖性强(体现在路径不能随意修改,否则牵一发而动全身)。
因此,全局引入Scss变量的做法来更替次次组件导入的方法显得尤为合适。你可以和笔者一样写一个公用的mixin.scss文件(里面不仅能放变量声明,还可以放mixin等),然后一次引入,.vue文件中开箱即用(不需导入)。
方法如下:
1、安装sass-resources-loader
npm install sass-resources-loader --save-dev
2、打开build/utils.js文件,修改对应代码如下:
- scss: generateLoaders('sass').concat(
- {
- loader: 'sass-resources-loader',
- options: {
- resources: path.resolve(__dirname, '../src/common/scss/mixin.scss')
- }
- }
- ),
注意:上面的文件路径一定要根据自己的项目来写,不要一味照抄
npm安装依赖报错
当我们使用npm安装依赖时,很多时候会出现一堆报错。报错的原因是多数是因为在node scripts/install阶段会从github上下载一个.node文件。而GitHub Releases里的文件都托管在s3.amazonaws.com上面,而这个托管网址在国内访问极度不稳定的,所以当依赖包含有node-sass、electron、phantomjs等依赖时会报错。
解决方法:
在C:\Users\Administrator目录下找一个为.npmrc的文件(没有可以自己新建一个),打开该文件并添加对应包的淘宝镜像即可(第四行代码是将npm默认地址替换为淘宝镜像,如果已经设置过淘宝镜像只须添加对应报错依赖项即可,笔者给出常见报错依赖项的淘宝镜像,推荐这三项都添加进去)。然后删除项目的node_modules文件夹,重新安装依赖(建议安装依赖前执行一下清除npm缓存操作:npm cache clean)。
- sass_binary_site=https://npm.taobao.org/mirrors/node-sass/
- electron_mirror=https://npm.taobao.org/mirrors/electron/
- phantomjs_cdnurl=https://npm.taobao.org/mirrors/phantomjs/
- registry=https://registry.npm.taobao.org
启动项目,端口被占用
排除一些软件默认使用指定端口的情况外,最大的可能性是之前有用Node运行过其它项目导致端口被占用。如果是后面这种情况,最简单的方法就是通过任务管理器结束掉所有Node进程,然后再执行项目启动命令即可。
当然,如果你喜欢折腾,你也可以去修改webpack的配置文件来更改默认的端口,然后再执行项目启动命令即可。相比这种方式,笔者更推荐通过任务管理器结束掉所有Node进程的方式。
vue文件中的样式不生效
按照Vue官方给出的说法,style身上加上scoped可以让样式“私有化”(即只针对本vue文件中的代码有效,不会对别的代码造成样式覆盖问题)。很多时候,我们引入了第三方UI,在vue文件中进行样式覆盖不生效,多半问题是style上的scoped导致的。
解决方案:将需要覆盖样式的这部分代码放到单独的CSS文件中,最后在main.js文件中导入即可。
防止Vue在解析时出现闪烁
针对这个问题,解决方法如下:
官网为我们提供了一个v-cloak指令,我们只需要这样写即可:
- // CSS代码
- [v-cloak] {
- display: none;
- }
- // HTML代码
- <div v-cloak>{{ message }}</div>
除了上述方法外,我们还可以借助Vue的v-text和v-html指令,同样可以达到效果。这两个指令的区别在于,v-html会解析HTML代码,而v-text不会。这几种方法,可根据自己的需要选择使用。
vue组件异步加载
将一个组件(以及其所有依赖)改为异步加载,只需要把:
import HelloWorld from '@/components/HelloWorld'
改成
const HelloWorld = () => import('@/components/HelloWorld')
vue项目引入jQuery和Bootstrap
引入其它第三方JS步骤类似
1、npm安装expose-loader(webpack官方推荐方式)
npm install expose-loader -S
2、npm安装jQuery和Bootstrap
npm install jquery bootstrap -S
3、修改build文件夹下的webpack.base.conf.js
- module: {
- rules: [{
- test: require.resolve('jquery'),
- use: [{
- loader: 'expose-loader',
- options: 'jQuery'
- },
- {
- loader: 'expose-loader',
- options: '$'
- }]
- }]
- }
4、修改main.js
- import 'bootstrap/dist/css/bootstrap.min.css';
- /* eslint-disable no-unused-vars */
- import $ from 'jquery';
- import 'bootstrap';
5、如果要在某个组件中使用$,请在对应的组件中导入jQuery即可
import $ from 'jquery';
注:请使用npm执行上面的步骤,切勿使用cnpm、切勿使用cnpm、切勿使用cnpm。如果npm安装无法安装,可以使用淘宝镜像——淘宝镜像和cnpm是不一样的,设置淘宝镜像可以参考文章开头部分。
router-link里的元素点击加stop失效
出现这个问题,多半是因为你使用了默认的router-link标签,默认vue会将这个解析为a标签。
解决办法如下,因为router-link可以指定tag,所以我们可以利用这个属性将默认的a链接换成其它标签再给加点击事件的元素加上stop就可以完美解决。
vue-resource拦截和axios拦截
有些时候,我们在处理页面请求的时候需要对页面进行类似token过期的处理。如果我们每个页面都去设置将是一个非常庞大的工程。因此,借助全局拦截器来进行统一设置将是最方便快捷的处理方法。下面介绍一下如何配置全局的vue-resource拦截器和axios拦截器。
注:此代码放在main.js文件中,并且在main.js中导入vue-resource或axios再进行如下配置
- // 导入并挂载
- import VueResource from 'vue-resource';
- Vue.use(VueResource);
- // vue-resource拦截配置
- Vue.http.interceptors.push((req, next) => {
- // 请求头设置,此设置根据后台要求进行配置
- Vue.http.headers.common['要传的字段'] = '要传的内容';
- // 此处可以配置请求拦截设置
- if (req.method.toLowerCase() == 'post') {
- req.emulateJSON = true;
- }
- // 此处可以配置请求拦截设置
- next((res) => {
- // 此处可以配置响应拦截设置
- return res;
- });
- });
- // 导入
- import axios from 'axios';
- // 针对只支持application/x-www-form-urlencoded的全局设置(qs模块为Node内置模块,无需单独安装)
- import qs from 'qs';
- // axios请求拦截器
- axios.interceptors.request.use((req) => {
- // 请求头设置,此设置根据后台要求进行配置
- req.headers['要传的字段'] = '要传的内容';
- // 此处可以配置请求拦截设置
- if (req.method.toLowerCase() == 'post') {
- req.data = qs.stringify(req.data);
- }
- return req;
- });
- // axios响应拦截器
- axios.interceptors.response.use((res) => {
- // 此处可以配置响应拦截设置
- return res;
- });
- // 由于受vue-resource的影响,大多数人沿袭了之前的风格,进行全局配置axios
- Vue.prototype.$http = axios;
vue-resource传参和axios传参报错
在用AJAX做数据交互的过程中,避免不了的就是参数传递,因为是在使用Vue进行开发,那么我们就会用搭配的AJAX工具,无论我们是用vue-resource或axios,在POST传参方面都不会像jQuery那样顺利。使用这两个工具,不传参什么事都没有,一传参它们就立马报错。原因在于vue-resource和axios默认传参是以JSON形式进行传递,大多数服务器默认并不支持接收JSON数据,所以可以通过下面的配置将JSON形式改成通用形式。
针对vue-resource的解决方案是,在POST传参的时候加一个配置项:{emulateJSON: true}
- this.$http.post('/someUrl', {foo: 'bar'}, {emulateJSON: true})
- .then((res) => {
- console.log(res);
- }, (err) => {
- console.log(err);
- });
针对axios的解决方案是,在POST传参的时候利用qs模块进行格式化:qs.stringify()
在使用axios的页面导入Node的qs模块
- import qs from 'qs';
- this.$http.post('/user',
- qs.stringify({
- firstName: 'Fred',
- lastName: 'Flintstone'
- }))
- .then((res) => {
- console.log(res);
- })
- .catch((err) => {
- console.log(err);
- });
特别说明:如果你想像vue-resource那样使用this.$http,只需要在main.js中将axios挂载到Vue的原型上面即可Vue.prototype.$http = axios;如果你不想那么麻烦,你可以使用拦截器进行全局配置,具体配置可以参考上一个问题。
这里笔者发表一下自己的看法,使用axios有一段时间了,没发现axios比vue-resource好多少,问题到是发现了几个。
1、axios不支持JSONP,官方好像怕出安全问题。
2、对于官方readme中提供的application/x-www-form-urlencoded的设置方法,至少目前一点作用没有,还要借助qs模块来完成。对于这个bug,不少人都有在Issues反馈,官方却一直没有解决。
如果vue作者没有推荐axios,笔者相信基本不会有人使用axios,毕竟vue-resource经历了vue2.0之前版本的检验,而且依然支持现在的版本。
AJAX进行header传值报错
在 进行项目开发的过程中,有些时候我们需要通过header进行传值。对于像PHP、Java、Objective-C等是在正常不过的一种传值方式。但是,对于像使用jQuery、axios等用AJAX来进行header传值的人来说,就不是那么容易了。如果仅仅只是前端配置header,后端没提前做过设置,控制台会报错(大意是说:请求头在服务器响应中不存在)。
要解决这个问题,只需要后端进行一下设置即可。header传值报错根本问题在于服务端的设置,即是否允许前端提交自定义header。
下面笔者给出方法:
- // 比如要用header传递X-AA-TOKEN,那就在下面这句话里加上X-AA-TOKEN即可
- header('Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept, X-AA-TOKEN');
本地模拟数据,AJAX请求路径报错
本地模拟数据(笔者以data.json为例)是在开发过程中常见的一种模拟前后端交互的方式。当然了,如果条件允许最好以真实接口为准,毕竟模拟数据的网络请求及数据处理过程远没有真实环境复杂。因此,很容易让我们忽略掉一些生产环境中交互的细枝末节。
在 用vue-cli搭建的项目中,要避免路径出错,最好先了解一下生成项目后的文件目录结构(打包后的文件除了index.html外,其余文件都会放到 static文件夹里)。换句话说,原static文件夹里的东西,在打包后会不做变动。利用这一特点,我们可以将本地模拟数据放到static文件夹里,然后用到AJAX的地方路径改为'./static/data.json'或'static/data.json'即可解决路径报错问题,此方法仅支持get方式。
打包之后静态资源图片404问题
很多同学都遇到过这种问题,当我们通过npm run build打包之后将文件放在服务器上时会出现图片404问题。这些图片可能是以img方式引入, 也可能是在CSS中定义的背景图片。
针对这个问题,首页要说明一下:在以vue-cli初始化的webpack模板中,webpack默认设置会将不大于10K的图片转成base64,大于10K的会保留原方式,并且最终会以hash命名的方式打包进static文件夹里(仅针对大于10K的图片)。
知道了这一点,多种解决方法也就出来:
1、可以通过修改webpack设置,将默认10K大小根据需要改大一点;
2、可以将图片和组件放在一个文件夹里,然后引入(笔者常用的方式),要使用相对路径(./或../)开头;
3、可以将图片做成外链图片,引入绝对地址;
4、可以将图片放到static文件夹里,然后引入。用这种方式的同学,在写路径时一定要找对,要不然会报错的。
以上方法任选其一即可,笔者推荐第2种或第3种方法。
路由执行了,但是却没有显示对应的组件
有些时候我们在进行路由切换的时候会发现路由已经执行(url已经发生了改变),但是却没有显示对应的组件。
经笔者测试,出现这种问题的原因多数是因为组件的data书写有问题。在vue的组件中,data必须为函数且参数需以return的行式返回出来。
选择性使用keep-alive
有些时候,我们的项目中需要对某些页面进行缓存处理来达到某些需求。这时,我们便会用到vue中的keep-alive。笔者见到大多数人在使用keep-alive时都是对所有组件进行缓存,对于这种做法,笔者认为弊大于利。原因在于:现在我们接触的项目页面一般都不会太少,如果我们把每个页面都缓存到内存中,一旦页面过多,必然影响手机的反映速度和流畅性。
因此,笔者的建议就是选择性组件缓存。要实习这种选择性组件缓存其实并不难,我们只需要在配置路由和使用view-router时做些手脚即可达到效果。
配置路由时,我们可以在我们需要进行缓存的组将多加一个参数(有meta字段的组件代表要缓存,没有则不需要),代码如下:
- routes: [
- {
- path: '/home',
- name: 'home',
- component: home,
- meta: {
- keep: true
- }
- },
- {
- path: '/mall',
- name: 'mall',
- component: mall
- }
- ]
将原来使用view-router的代码替换成如下代码:
- <keep-alive>
- <router-view v-if="$route.meta.keep"></router-view>
- </keep-alive>
- <router-view v-if="!$route.meta.keep"></router-view>
如何将vue组件通过use的方式全局调用
很多时候,我们希望自己也能做出一个vue组件,通过在main.js里use一下就可以到处用,而不用每次import。其实官方有给我们提供方法的,按着官方方法来就行了。
vue官方推荐的组件写法是通过文件来的方式,笔者以loading组件为例(loading组件文件夹包含loading.vue和index.js两个文件)
在loading文件夹里新建一个index.js,然后写上如下代码即可:
- // loading即为我们的loading组件
- import loading from './loading';
- // install是官方提供的一个方法,loading这就是后面可以全局使用的组件名字,此名字可以修改
- export default {
- install(Vue) {
- Vue.component('loading', loading);
- }
- };
然后在main.js入口文件里增加如下代码:
- // 导入loading组件,引入路径根据自己的书写
- import loading from 'loading组件路径';
- // 利用Vue.use挂载我们的loading组件
- Vue.use(loading);
通过上面的步骤,我们就可以在全局使用loading标签成功引入loading组件了。
dist文件部署显示空白问题
打包生成后的文件放到服务环境下,访问空白,请注意下面两点:
1、确保dist文件夹里的东西放到了网站根目录下(即常见的www文件夹里)
特别说明:不是将dist文件夹放到网站根目录下,而是把dist文件夹里的东西放到网站根目录下。
2、是否使用的是IE系列浏览器打开的网址
特别说明:原因在于IE系列浏览器不支持JS的一些高级特性,因此我们需要借助babel-polyfill来实现高级特性转换。
-->安装babel-polyfill
npm install babel-polyfill -S
-->在main.js的第一行引入babel-polyfill
import 'babel-polyfill';
特别说明:
1、babel-polyfill属于生产依赖,所以必须使用-S安装;
2、由于要用其做语法转换,所以要确保import 'babel-polyfill'是在main.js的第一行;
dist文件部署后刷新出现404问题
文件部署到服务器后,直接访问没有问题,但是刷新当前页后出现404问题。出现这个问题,99.99%是因为你在配置路由的时候启用了history模式。 起用history模式后,在开发环境不会出现刷新后404问题。但是,部署到服务器环境是需要对服务器做相关配置的。
解决方案:找到对应的服务器,把对应的代码放到对应的位置即可
- # Apache代码,加入到网站的.htaccess里,没有该文件,自己可以新建一个
- <IfModule mod_rewrite.c>
- RewriteEngine On
- RewriteBase /
- RewriteRule ^index\.html$ - [L]
- RewriteCond %{REQUEST_FILENAME} !-f
- RewriteCond %{REQUEST_FILENAME} !-d
- RewriteRule . /index.html [L]
- </IfModule>
- # Tomcat代码,加入到网站的web.xml里,没有该文件,自己可以新建一个
- <web-app>
- <error-page>
- <error-code>404</error-code>
- <location>/index.html</location>
- </error-page>
- </web-app>
- # Nginx代码,加入到网站的nginx.conf里,没有该文件,自己可以新建一个
- location / {
- try_files $uri $uri/ /index.html;
- }
如何将打包好的文件放到指定目录
很多时候,我们因为某些原因不能将打包好的dist文件夹里的东西直接放到网站根目录(多数为www目录),而需要放到一个指定的文件夹,这里笔者以demo文件夹为例。因此,我们的访问路径就变为类似这样的地址:www.***.com/demo/。
对于这样的操作,webpack并没有提前帮我们做相关处理。如果我们采用默认配置,直接将打包好的dist文件夹里的东西上传到demo文件夹,将无法达到我们预期的效果。
要想实现将打包好的文件放到指定目录其实非常简单,只需要我们做一些相关配置即可,此配置不会影响本地开发。
此方法针对vue-cli以webpack初始化的模板,其它模板,未经测试。
特别说明:demo文件夹仅是例子,可自行根据需要修改为其它名字。
第一步,找到config文件夹里的index.js文件
- // 将'/'改成'/demo/'
- assetsPublicPath: '/demo/'
第二步,在路由配置文件里加上
- base: '/demo/'
完成了第二步,如果你的路由使用的是默认形式(即hash模式)则大功告成,无须进行下面步骤。
如果你想使用histroy模式,你需要在路由配置文件里加上
- mode: 'histroy',
- base: '/demo/'
除了上面这些,你还需要对服务器做相关配置,这里笔者以Apache为例
- # Apache代码,加入到网站的.htaccess里,没有该文件,自己可以新建一个(注意将最后一条规则里的demo修改成自己的目录名,否则只对demo文件夹有效)
- <IfModule mod_rewrite.c>
- RewriteEngine On
- RewriteBase /
- RewriteRule ^index\.html$ - [L]
- RewriteCond %{REQUEST_FILENAME} !-f
- RewriteCond %{REQUEST_FILENAME} !-d
- RewriteRule ^(demo|demo/.*)$ demo/index.html [L]
- </IfModule>
在进行vue项目开发的过程中,笔者建议路由使用默认形式(即hash模式),这样可以少踩很多坑,特别是在微信中。
欢迎分享你在使用Vue开发过程中遇到的问题。