困扰99%前端程序员的Vue问题,全在这了

 1.前言

最近要求使用vue进行前后端分离开发微信公众号,不断摸索踩坑之后,总结出如下几点vue项目开发中常见的问题及解决办法。如果你是vue大佬,请忽略小弟的愚见

  • 列表进入详情页的传参问题。
  • 本地开发环境请求服务器接口跨域的问题
  • axios封装和api接口的统一管理
  • UI库的按需加载
  • 如何优雅的只在当前页面中覆盖ui库中组件的样式
  • 定时器问题
  • rem文件的导入问题
  • Vue-Awesome-Swiper基本能解决你所有的轮播需求
  • 打包后生成很大的.map文件的问题
  • fastClick的300ms延迟解决方案
  • 组件中写选项的顺序

2.列表进入详情页传参问题

例如商品列表页面前往商品详情页面,需要传一个商品id;

 
 
 
 
  1. 前往detail页面 

c页面的路径为 http://localhost:8080/#/detail?id=1 ,可以看到传了一个参数 id=1 ,并且就算刷新页面id也还会存在。此时在c页面可以通过id来获取对应的详情数据,获取id的方式是 this.$route.query.id vue传参方式有:query、params+动态路由传参。

vue传参方式有:query、params+动态路由传参。说下两者的区别:

  • query通过 path 切换路由,params通过 name 切换路由
 
 
 
 
  1. // query通过path切换路由 
  2. 前往Detail页面 
  3. // params通过name切换路由 
  4. 前往Detail页面 
  • query通过 this.$route.query 来接收参数,params通过 this.$route.params 来接收参数。
 
 
 
 
  1. // query通过this.$route.query接收参数 
  2. created () { 
  3.     const id = this.$route.query.id; 
  4.  
  5. // params通过this.$route.params来接收参数 
  6. created () { 
  7.     const id = this.$route.params.id; 
  • query传参的url展现方式: /detail?id=1&user=123&identity=1&更多参数 params+动态路由的url方式: /detail/123
  • params动态路由传参,一定要在路由中定义参数,然后在路由跳转的时候必须要加上参数,否则就是空白页面
 
 
 
 
  1.     path: '/detail/:id', 
  2.     name: 'Detail', 
  3.     component: Detail 
  4. }, 

注意,params传参时,如果没有在路由中定义参数,也是可以传过去的,同时也能接收到,但是一旦刷新页面,这个参数就不存在了。这对于需要依赖参数进行某些操作的行为是行不通的,因为你总不可能要求用户不能刷新页面吧。例如:

 
 
 
 
  1. // 定义的路由中,只定义一个id参数 
  2.     path: 'detail/:id', 
  3.     name: 'Detail', 
  4.     components: Detail 
  5.  
  6. // template中的路由传参, 
  7. // 传了一个id参数和一个token参数 
  8. // id是在路由中已经定义的参数,而token没有定义 
  9. 前往Detail页面 
  10.  
  11. // 在详情页接收 
  12. created () { 
  13.     // 以下都可以正常获取到 
  14.     // 但是页面刷新后,id依然可以获取,而token此时就不存在了 
  15.     const id = this.$route.params.id; 
  16.     const token = this.$route.params.token; 

3.本地开发环境请求服务器接口跨域的问题

上面的这个报错大家都不会陌生,报错是说没有访问权限(跨域问题)。本地开发项目请求服务器接口的时候,因为客户端的同源策略,导致了跨域的问题。下面先演示一个没有配置允许本地跨域的的情况:

可以看到,此时我们点击获取数据,浏览器提示我们跨域了。所以我们访问不到数据。那么接下来我们演示设置允许跨域后的数据获取情况:

我们在1出设置了允许本地跨域,在2处,要注意我们访问接口时,写的是 /api ,此处的 /api 指代的就是我们要请求的接口域名。如果我们不想每次接口都带上 /api ,可以更改axios的默认配置 axios.defaults.baseURL = '/api'; 这样,我们请求接口就可以直接 this.$axios.get('app.php?m=App&c=Index&a=index') ,很简单有木有。此时如果你在 network 中查看 xhr 请求,你会发现显示的是 localhost:8080/api 的请求地址。这样没什么大惊小怪的,代理而已:

好了,最后附上proxyTable的代码:

 
 
 
 
  1. proxyTable: { 
  2.       // 用‘/api’开头,代理所有请求到目标服务器 
  3.       '/api': { 
  4.         target: 'http://jsonplaceholder.typicode.com', // 接口域名 
  5.         changeOrigin: true, // 是否启用跨域 
  6.         pathRewrite: { // 
  7.           '^/api': '' 
  8.         } 
  9.       } 

注意:配置好后一定要关闭原来的server,重新 npm run dev 启动项目。不然无效。

axios的封装,主要是用来帮我们进行请求的拦截和响应的拦截。在请求的拦截中我们可以携带userToken,post请求头、qs对post提交数据的序列化等。在响应的拦截中,我们可以进行根据状态码来进行错误的统一处理等等。axios接口的统一管理,是做项目时必须的流程。这样可以方便我们管理我们的接口,在接口更新时我们不必再返回到我们的业务代码中去修改接口。

4.UI库的按需加载

为什么要使用按需加载的方式而不是一次性全部引入,原因就不多说了。这里以vant的按需加载为例,演示vue中ui库怎样进行按需加载:

  • 安装: cnpm i vant -S
  • 安装 babel-plugin-import 插件使其按需加载: cnpm i babel-plugin-import -D
  • 在 .babelrc文件中中添加插件配置 :
 
 
 
 
  1. libraryDirectory { 
  2.      
  3.     "plugins": [ 
  4.         // 这里是原来的代码部分 
  5.         // ………… 
  6.  
  7.         // 这里是要我们配置的代码 
  8.         ["import", 
  9.             { 
  10.                 "libraryName": "vant", 
  11.                 "libraryDirectory": "es", 
  12.                 "style": true 
  13.             } 
  14.         ] 
  15.     ] 
  • 在main.js中按需加载你需要的插件:
 
 
 
 
  1. // 按需引入vant组件 
  2. import { 
  3.     DatetimePicker, 
  4.     Button, 
  5.     List 
  6. } from 'vant'; 
  • 使用组件:
 
 
 
 
  1. // 使用vant组件 
  2. Vue.use(DatetimePicker) 
  3.     .use(Button) 
  4.     .use(List); 
  • 最后在在页面中使用:
 
 
 
 
  1. 按钮 

ps:出来 vant 库外,像 antiUi 、 elementUi 等,很多ui库都支持按需加载,可以去看文档,上面都会有提到。基本都是通过安装babel-plugin-import插件来支持按需加载的,使用方式与vant的如出一辙,可以去用一下。

5.如何优雅的只在当前页面中覆盖ui库中组件的样式

首先我们vue文件的样式都是写在  标签中的,加scoped是为了使得样式只在当前页面有效。那么问题来了,看图:

我们正常写的所有样式,都会被加上[data-v-23d425f8]这个属性(如1所示),但是第三方组件内部的标签并没有编译为附带[data-v-23d425f8]这个属性。所以,我们想修改组件的样式,就没辙了。怎么办呢,有些小伙伴给第三方组件写个class,然后在一个公共的css文件中或者在当前页面再写一个没有socped属性的style标签,然后直接在里面修改第三方组件的样式。这样不失为一个方法,但是存在全局污染和命名冲突的问题。约定特定的命名方式,可以避免命名冲突。但是还是不够优雅。作为一名优(  )秀(  )的(  )前(  )端(  ),怎么能允许这种情况出现呢?好了,下面说下优雅的解决方式:通过深度选择器解决。例如修改上图中组件里的van-ellipsis类的样式,可以这样做:

 
 
 
 
  1. .van-tabs /deep/ .van-ellipsis { color: blue}; 

编译后的结果就是:

这样就不会给 van-ellipsis 也添加 [data-v-23d425f8] 属性了。至此你可以愉快的修改第三方组件的样式了。当然了这里的深度选择器 /deep/ 是因为我用的 less 语言,如果你没有使用 less/sass 等,可以用 >>> 符号。更多的关于深度选择器的内容,在文章后面有介绍。

6.定时器问题

我在a页面写一个定时,让他每秒钟打印一个1,然后跳转到b页面,此时可以看到,定时器依然在执行。这样是非常消耗性能的。如下图所示:

解决方法1

首先我在data函数里面进行定义定时器名称:

 
 
 
 
  1. data() { 
  2.     return { 
  3.         timer: null  // 定时器名称 
  4.     } 
  5. }, 

然后这样使用定时器:

 
 
 
 
  1. this.timer = (() => { 
  2.     // 某些操作 
  3. }, 1000) 

最后在beforeDestroy()生命周期内清除定时器:

 
 
 
 
  1. beforeDestroy() { 
  2.     clearInterval(this.timer); 
  3.     this.timer = null; 

方案1有两点不好的地方,引用尤大的话来说就是:

 
 
 
 
  1. timer 

解决方案2

该方法是通过$once这个事件侦听器器在定义完定时器之后的位置来清除定时器。以下是完整代码:

 
 
 
 
  1. const timer = setInterval(() =>{ 
  2.     // 某些定时器操作 
  3. }, 500); 
  4. // 通过$once来监听定时器,在beforeDestroy钩子可以被清除。 
  5. this.$once('hook:beforeDestroy', () => { 
  6.     clearInterval(timer); 
  7. }) 

方案2要感谢@zzx18023在评论区提供出的解决方案。类似于其他需要在当前页面使用,离开需要销毁的组件(例如一些第三方库的picker组件等等),都可以使用此方式来解决离开后以后在背后运行的问题。综合来说,我们更推荐使用 方案2,使得代码可读性更强,一目了然 。如果不清楚once、on、$off的使用,这里送上官网的地址教程,在程序化的事件侦听器那里: https:// cn.vuejs.org/v2/guide/c omponents-edge-cases.html#%E7%A8%8B%E5%BA%8F%E5%8C%96%E7%9A%84%E4%BA%8B%E4%BB%B6%E4%BE%A6%E5%90%AC%E5%99%A8 。

7.rem文件的导入问题

我们在做手机端时,适配是必须要处理的一个问题。例如,我们处理适配的方案就是通过写一个rem.js,原理很简单,就是根据网页尺寸计算html的font-size大小,基本上小伙伴们都知道,这里直接附上代码,不多做介绍。

 
 
 
 
  1. (function(c, d) { 
  2.   var e = document.documentElement || document.body, 
  3.     a = "orientationchange" in window ? "orientationchange" : "resize", 
  4.     b = function() { 
  5.       var f = e.clientWidth; 
  6.       e.style.fontSize = f >= 750 ? "100px" : 100 * (f / 750) + "px"; 
  7.     }; 
  8.   b(); 
  9.   c.addEventListener(a, b, false); 
  10. })(window); 

这里说下怎么引入的问题,很简单。在main.js中,直接 import './config/rem' 导入即可。import的路径根据你的文件路径去填写。

8.Vue-Awesome-Swiper基本能解决你所有的轮播需求

在我们使用的很多ui库(vant、antiUi、elementUi等)中,都有轮播组件,对于普通的轮播效果足够了。但是,某些时候,我们的轮播效果可能比较炫,这时候ui库中的轮播可能就有些力不从心了。当然,如果技术和时间上都还可以的话,可以自己造个比较炫的轮子.这里我说一下 vue-awesome-swiper 这个轮播组件,真的非常强大,基本可以满足我们的轮播需求。swiper相信很多人都用过,很好用,也很方便我们二次开发,定制我们需要的轮播效果。vue-awesome-swiper组件实质上基于swiper的,或者说就是能在vue中跑的 swiper 。下面说下怎么使用:

 
 
 
 
  1. cnpm install vue-awesome-swiper --save 

 
 
 
 
  1. // 引入组件 
  2. import 'swiper/dist/css/swiper.css' 
  3. import { swiper, swiperSlide } from 'vue-awesome-swiper' 
  4.  
  5. // 在components中注册组件 
  6. components: { 
  7.     swiper, 
  8.     swiperSlide 
  9.  
  10. // template中使用轮播 
  11. // ref是当前轮播 
  12. // callback是回调 
  13. // 更多参数用法,请参考文档 
  14.  
  15.      
  16.     1
 
  •     2
  •  
  •     3
  •  
  •            
  •      
  •      
  •      
  •      
  •      
  •  
  • // 参数要写在data中 
  • data() { 
  •     return { 
  •         // swiper轮播的参数 
  •         swiperOption: { 
  •             // 滚动条 
  •             scrollbar: { 
  •                 el: '.swiper-scrollbar', 
  •             }, 
  •             // 上一张,下一张 
  •             navigation: { 
  •                 nextEl: '.swiper-button-next', 
  •                 prevEl: '.swiper-button-prev', 
  •             }, 
  •             // 其他参数………… 
  •         } 
  •     } 
  • }, 
  • swiper需要配置哪些功能需求,自己根据文档进行增加或者删减。附上文档:npm文档,swiper3.0/4.0文档,更多用法,请参考文档说明。

    9.打包后生成很大的.map文件的问题

    项目打包后,代码都是经过压缩加密的,如果运行时报错,输出的错误信息无法准确得知是哪里的代码报错。 而生成的.map后缀的文件,就可以像未加密的代码一样,准确的输出是哪一行哪一列有错可以通过设置来不生成该类文件。但是我们在生成环境是不需要.map文件的,所以可以在打包时不生成这些文件:在 config/index.js 文件中,设置 productionSourceMap: false, 就可以不生成 .map 文件

    10.fastClick的300ms延迟解决方案

    开发移动端项目,点击事件会有300ms延迟的问题。至于为什么会有这个问题,请自行百度即可。这里只说下常见的解决思路,不管vue项目还是jq项目,都可以使用 fastClick 解决。安装 fastClick :

     
     
     
     
    1. cnpm install fastclick -S 

    在main.js中引入fastClick和初始化:

     
     
     
     
    1. import FastClick from 'fastclick'; // 引入插件 
    2. FastClick.attach(document.body); // 使用 fastclick 

    11.组件中写选项的顺序

    为什么选项要有统一的书写顺序呢?很简单,就是要将选择和认知成本最小化。

     
     
     
     
    1. delimiters 
    2. comments 
     
     
     
     
    1. components 
    2. directives 
    3. filters 
     
     
     
     
    1. extends 
    2. mixins 
     
     
     
     
    1. data 
    2. computed 
     
     
     
     
    1. beforeCreate 
    2. created 
    3. beforeMount 
    4. mounted 
    5. beforeUpdate 
    6. updated 
    7. activated 
    8. deactivated 
    9. beforeDestroy 
    10. destroyed 
    11. watch 

    文章标题:困扰99%前端程序员的Vue问题,全在这了
    本文URL:http://www.shufengxianlan.com/qtweb/news36/371736.html

    网站建设、网络推广公司-创新互联,是专注品牌与效果的网站制作,网络营销seo公司;服务项目有等

    广告

    声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-86922220;邮箱:631063699@qq.com。内容未经允许不得转载,或转载时需注明来源: 创新互联

    猜你还喜欢下面的内容

    App设计知识

    同城分类信息