vue开发常见问题集合

责编:menVScode 2017-12-15 15:20 阅读(1032)

        特别说明,以下是针对vue2.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-sasssass-loader

        特别提醒:vue组件里的style里需加上lang="scss",这样才能被webpack识别

        1、如果想在vue组件中使用Stylus,需要在package.json里的devDependencies加stylusstylus-loader

        特别提醒:vue组件里的style里需加上lang="stylus",这样才能被webpack识别。

        高能预警:这里用的是stylus-loader而不是style-loader;stylus对缩进要求极其严苛,这点真的和Python很像,你不注意,webpack就敢给你报错,所以请注意缩进。

        1、如果想在vue组件中使用Less,需要在package.json里的devDependencies加lessless-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

improt 'babel-polyfill';

特别说明:

        1、babel-polyfill属于生产依赖,所以必须使用-S安装;

        2、由于要用其做语法转换,所以要确保improt '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开发过程中遇到的问题。


标签: vue
前端交流群: MVC前端网(menvscode.com)-qq交流群:551903636

邮箱快速注册

忘记密码