vue项目小点(二)

1.解决使用vue-awesome-swiper组件分页器pagination样式设置失效问题

解决方案:给父标签设置一个id,例如父标签id="parent",在sass/less中使用/deep/样式穿透,例:

#parent /deep/ .swiper-pagination-bullet{
      background-color: 'red';
}

在stulys中使用:>>>实现样式穿透:

#parent >>> .swiper-pagination-bullet-active {
     border-radius: 'unset';
}

vue穿透详解:

在一次这样的需求中,需要实现滑倒底部时自动请求数据,需要动态创建节点然后追加到某元素中,这期间遇到的问题就是在动态创建节点后,类名也已经加上了 ,但是样式就是没有生效,最后发现原因的产生竟然是<style scoped></style>中scoped属性,该属性的作用是用来绑定当前样式不被污染。

这时就需要通过 >>> 穿透scoped

stylus的样式穿透 使用>>>。iview中需要在组件上使用i-class声明第三方组件类名

<style scoped>
    外层 >>> 第三方组件类名{
        样式
    }
</style>

有些Sass 、Less之类的预处理器无法正确解析>>>。可以使用/deep/操作符( >>> 的别名)

<style lang="sass" scoped>
/deep/  第三方组件类名 {
      样式
  }
</style>

实例:

<template>
  <input i-class="ivu-input">
</template>
// 样式
.num-input {
    width: 90px;
    margin-top: 15px;
    >>> .ivu-input {
      text-align: center!important;
    }
}
// Less || Sass
.num-input {
    width: 90px;
    margin-top: 15px;
    /deep/ .ivu-input {
      text-align: center!important;
    }
}

关于vue项目中使用 vue-awesome-swiper组件 的详细博客:https://segmentfault.com/a/1190000014609379

2. axios 发 post 请求,后端接收不到参数的解决方案

这里直接推荐一篇博客,我觉得写得很详细,而且能完美的解决这个问题:https://www.cnblogs.com/yiyi17/p/9409249.html

3. vue中生成二维码

①. 安装qrcodejs2插件,在控制台输入:

npm install qrcodejs2 --save
* 注意:这里安装的是qrcodejs2,不是qrcode,否则会报错

②. 页面引入——在入口文件(默认是main.js)或者 所用插件的 .vue 文件里引入:

import QRCode from 'qrcodejs2'

③. 在对应的Html页面中,添加html标签

<div id="qrcode" ref="qrcode"></div>

④. 在methods方法里配置:

qrcode () {
    let qrcode = new QRCode('qrcode',{
        width: 200, // 设置宽度,单位像素
        height: 200, // 设置高度,单位像素
        text: 'https://www.baidu.com'   // 设置二维码内容或跳转地址
    })
}

⑤. 调用

this.$nextTick(() => {
    this.qrcode()
})

* 注意,调用的时候必须保证: 此DOM为显示状态,否则会出现 *appendChild null错误,就是id为qrcode的dom获取不到,返回结果为null

4. vue中插件qs的使用

有时在请求数据时使用axios请求数据传参时无法正常的获取数据。之后也是一通百度,发现原因是传递参数要将参数序列化。简单来说,qs 是一个增加了一些安全性的查询字符串解析和序列化字符串的库。使用步骤如下:

①. 首先先下载:

npm i qs

②. 在需要用到 qs插件 的文件引入:

import qs from 'qs

③. qs主要有两个方法 :

方法一:qs.stringify()方法一:将对象序列化,多个对象之间用&拼接(拼接是由底层处理,无需手动操作)

qs.stringify()  转换成查询字符串
let comments = {content: this.inputValue}
let comValue = qs.stringify(comments)

方法二:qs.parse()是将URL解析成对象的形式

qs.parse() 转换成json对象
let comValue = qs.parse(comments)

5. vue无限滚动,实现数据懒加载。

一般后台会对数据做分页,这里用mintui的知识来解决就会简单不少,但是它也有不少坑,

  • 在最开始使用的时候,如果将v-infinite-scroll的值设为我的请求数据的函数,发现会无限调用,导致页面卡死,将请求函数放在loadMore函数中调用便避免了这个问题
  • 滚动容器ul必须设置overflow:hidden,否则会导致滚动到底部时不请求
  • v-infinite-scroll中的loadMore函数会在页面加载后立即执行,所以不需要在created中进行初始化请求
  • loading的值初始为false,否则页面不会请求
  • 每次请求完成将page++
  • 控制请求的次数,设置一个变量bRequest,默认为true,如果获取的数据数组长度为0,将bRequset设置为false,每次请求之前检查这个变量的值

代码:

//需要滚动饿元素标签内添加如下代码,详细饿去看mintui官网
v-infinite-scroll="loadMore"
infinite-scroll-disabled="loading"
nfinite-scroll-distance="10"

<div class="scroll" v-if="have"
                     v-infinite-scroll="loadMore"
                     infinite-scroll-disabled="loading"
                     infinite-scroll-distance="10">
                    <div class="rec" v-for="(item,index) in goodsList" :key="index">
                        <img src="../assets/record2.png" alt="">
                        <div class="right">
                            <div class="rt">
                                <div class="tit">{{item.name}}</div>
                                <div class="pay">{{item.pay_money}}</div>
                            </div>
                            <div class="rb">
                                <div class="time">{{item.pay_time}}</div>
                                <div class="no">节省:{{item.discount_money}}</div>
                            </div>
                        </div>
                    </div>
                    <div class="des">
                        <div class="loading-box tc" v-if="isLoading">
                            <span class="loading-more-txt">加载中</span>
                            <mt-spinner type="triple-bounce" color="#16A6F7" :size="15"></mt-spinner>
                        </div>
                        <div class="no-more" v-if="noMore">没有更多了~</div>
                    </div>
                </div>

js:

data(){
      return{
                loading: false,
                bRequest: true,
                page: 1,
                goodsList: [],
                isLoading : false,
                noMore : false,
         }
 },
 methods:{
            loadMore(){
                if (this.bRequest) {
                    this.loadList(this.page);
                }
            },
            loadList (page){
                this.post({
                    data:{
                        request:'private.consume.order.record.page',
                        token: this.$store.getters.token,
                        page: page,
                        page_size: 6
                    },
                    success: res => {
                        // console.log(res);
                        this.record = res.data;
                        if(res.data.data.length === 0){
                            this.bRequest = false;
                            this.isLoading = false;
                            this.noMore = true;
                        }else {
                            this.goodsList = this.goodsList.concat(res.data.data);
                            this.isLoading = true;
                            this.noMore = false;
                        }
                        this.page++;
                    }
                })
            }
        }

参考博客:https://rosenprivate.gitee.io/2018/08/26/mint-ui%E4%B8%AD%E6%97%A0%E9%99%90%E6%BB%9A%E5%8A%A8%E7%BB%84%E4%BB%B6%E7%9A%84%E7%94%A8%E6%B3%95/

以上情况是在后端将数据分页的情况下的代码,如果后台没有将数据分页,前端需要自己处理数据哦。可参考如下博客:https://blog.csdn.net/lb1135909273/article/details/83856800

如果是不能用mintui去写,你可以去看看这个博客:https://www.jianshu.com/p/29aa8ac3e1c5

6. axios的兼容性问题

① axios在PC端浏览器的兼容性问题

axios支持IE8+,但原理是基于promise之上实现的,因此会存在不兼容IE的问题。

trident内核的浏览器下会报:vuex requires a Promise polyfill in this browser

解决方案:

(1)、首先安装 babel-polyfill,来解决IE不支持 promise对象的问题

npm  install  babel-polyfill -s

安装成功以后需要在 main.js 中引入 babel-polyfill

import 'babel-polyfill'

(2)、一般会配置 webpack.base.config.js 中 entry

module.exports = {
  context: path.resolve(__dirname, '../'),
  entry: {
    app: ["babel-polyfill", "./src/main.js"] 
    // app: './src/main.js'
  },
}

② axios在安卓低版本兼容性处理

在较低版本的安卓手机中发现发现封装的axios请求无效,主要原因还是低版本的安卓手机无法使用promise

注意:安卓4.3以下的手机不支持axios的使用,无法使用promise,加上 polyfill就可以了。

解决方案:

(1)、项目中安装 es6-promise

npm install es6-promise -s

(2)、引入 es6-promise

import promise from 'es6-promise'

(3)、注册 es6-promise (一定要在axios之前注册)

// 注意:es6-promise   一定要在 axios 之前注册
promise.polyfill()

或者

require('es6-promise').polyfill();
import axios from 'axios'

7. CSS实现div的高度填满剩余空间

利用定位强制定义盒模型的区域。

html:

<div id="main">
    <div id="nav">nav</div>
    <div id="content">content</div>
</div>

css:

#nav {
    background-color: #85d989;
    width: 100%;
    height: 50px;
}
#content {
    background-color: #cc85d9;
    width: 100%;
    position: absolute;
    top: 50px;
    bottom: 0px;
    left: 0px;
}

8. css实现表单输入框前面的文字两端对齐

一个全角空格就可以解决了。效果如图:

用户名:
密 码:

9. vue跳转页面传输对象,再刷新浏览器数据丢失问题(vue使用router传递数据)

vue Router跳转传字符串是这样的:(params传值需在路由中做配置刷新后数据才不会丢失)

① 点击事件跳转

// 传值
this.$router.push({path:'throughList',query:{id:id}});
//接收
this.ids = this.$route.query.id

还可以这样:

// 传值
this.$router.push({path:'/oil_pay/' + this.oilDes.id})
//router-index.js
{path: '/oil_pay/:sid', name: 'oil_pay',meta:{index:3}, component: (resolve) => require(['../views/oil_pay'], resolve)},
//接收
this.store_id = this.$route.params.sid;

② 标签 router-link 跳转

// 传值
<router-link v-for="(item,index) in station" :key="index" :to="{name:'oil_des',query:{id:item.id}}"></router-link>
//接收
this.ids = this.$route.query.id

params传值同上就不再说了,咱们开始看重点。如果vue Router跳转传对象,刷新数据仍然会丢失,那我们该怎么办呢?

数据类型的原因,再传递数据之前使用【JSON.stringify】把要传递的数据转换成字符串类型,再刷新就没有问题了!

其实vue很多数据丢失或者数据格式不对的问题都是数据格式导致的,下次再有这样的问题的话,可以直接使用【JSON.stringify】转换一下数据格式,如果一次转换还是不行的话就做双重转换,问题一般就都解决了!!

① 点击事件跳转

// 传值
this.$router.push({path:'throughList',query:{deviceInfo:JSON.stringify(deviceInfo)}});
//接收
this.ids = JSON.parse(this.$route.query.deviceInfo),

② 标签 router-link 跳转

// 传值
<router-link v-for="(item,index) in station" :key="index" :to="{name:'oil_des',query:{oilDes:JSON.stringify(item)}}"></router-link>
//接收
this.oilDes: JSON.parse(this.$route.query.oilDes),

10. vue有时会报下图所示的错误,已解决。

解决办法:

先来看一下后台返回的数据例子:

而我定义的 data 是这样的:

data(){
   return{
     noPay: {}
   }
}

正确的定义的 data 应该是这样的:

data(){
   return{
     noPay: {
         oil:{
           data:{}
         },
         product:{}
      }
   }
}

11. 微信公众号+vue+图片上传

首先做好微信的授权配置,我这里需要定位,支付,图片上传的功能,所以我封装了一个js文件 src->utils->WXUntil.js

import wx from "weixin-jsapi";
import { getJSSDK } from './api/appid';//获取appid信息的接口,以后台人员接口为准
import { payorders } from "./api/pay";//一个更具订单id获取appid的接口

const wxUtils = (token,url) => {
    return new Promise((resolve, reject) => {
        getJSSDK(token,url).then(data => {
            wx.config({
                debug: false, // TODO: 测试阶段使用
                appId: data.appId,
                timestamp: data.timestamp,
                nonceStr: data.noncestr,
                signature: data.signature,
                jsApiList: [
                    'getLocation',
                    'hideMenuItems',
                    'chooseImage',
                    'uploadImage'
                ]
            });
            wxReady(resolve)
        }).catch(error => {
            reject();
            console.log(error);
        })
    })
};
// 微信jssdk加载完成
const wxReady = resolve => {  //不让分享
    wx.ready(() => {
        wx.hideMenuItems({
            menuList: [
                'menuItem:share:timeline', // 分享给朋友圈
                'menuItem:share:qq', // 分享到QQ
                'menuItem:share:weiboApp', // 分享到Weibo
                'menuItem:favorite', // 收藏
                'menuItem:share:QZone', // 分享到 QQ 空间
                'menuItem:copyUrl', // 复制链接
                'menuItem:openWithQQBrowser', // 在QQ浏览器中打开
                'menuItem:openWithSafari', // 在Safari中打开
                'menuItem:share:email', // 邮件
                'menuItem:readMode', // 阅读模式
                'menuItem:originPage' // 原网页
            ] // 要隐藏的菜单项,只能隐藏“传播类”和“保护类”按钮,所有menu项见附录3
        });
        resolve();
    });
};
// 微信支付
const WXinvoke = (token,orderId, resolve) => {  //orderId 订单ID
    payorders(token,orderId).then(res => {
        wx.invoke(
            'getBrandWCPayRequest', {
                "appId": res.appId, // 公众号名称,由商户传入
                "timeStamp": res.timestamp, // 时间戳,自1970年以来的秒数
                "nonceStr": res.nonceStr, // 随机串
                "package": res.package,
                "signType": res.signType, // 微信签名方式:
                "paySign": res.signature // 微信签名
            },
            function (res) {
                setTimeout(function () {
                    if (res.err_msg == "get_brand_wcpay_request:ok") {
                        resolve()
                    }
                }, 500);
            }
        );
    })
};

// 获取地理位置
const getLocation = () => {
    return new Promise((resolve, reject) => {
        wx.getLocation({
            type: 'wgs84', // 默认为wgs84的gps坐标,如果要返回直接给openLocation用的火星坐标,可传入'gcj02'
            success: response => {
                resolve(response);
            },
            fail: err => {
                reject(err);
            }
        });
    });
};
export { getLocation, WXinvoke, wxUtils };
export default wxUtils;

文件中又封装了请求方法 ( 定位功能 ):src->api->appid.js

import { getReq } from '../../http/http';

const getJSSDK=(token,url)=>{
    return new Promise((resolve,reject) => {
        getReq({
            data:{
                request:'',
                token:token,
                url: url,
                request_type:'request'
            },
            success: res => {
                if(res.code == 0){
                    resolve(res.data)
                }else{
                    reject(res.msg?res.msg:{msg:'request err'})
                }
            }
        });
    })
};
export { getJSSDK }

当然了,这里用到的请求也是自己封装的:src->http->http.js

import Vue from 'vue';
import promise from 'es6-promise';
promise.polyfill();

import axios from 'axios';
import store from '../store/index';
import qs from 'qs';


Vue.config.baseHttpUrl = 'https://www.ykelai.com/yocolung/api/';    //网络请求地址
Vue.config.platform = 'wxgzh';                    //终端类型

// axios 配置
axios.defaults.timeout = 10000;                    //网络请求超时时间
axios.defaults.baseURL = Vue.config.baseHttpUrl;            
axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded;charset=UTF-8';

// http request 拦截器
axios.interceptors.request.use(
    config => {
        if(config.method === 'post'){
          config.data = qs.stringify(config.data);
    }
        return config;
    },
    err => {
        return Promise.reject(err);
    });

Vue.prototype.axios = axios;
var getReq = function(obj){
  const _this = this;
  var url = '';
  obj.data.platform = obj.data.platform || Vue.config.platform;
  if(obj.url){
        url =   obj.url;
  }
  axios.post(url,obj.data)
  .then(function (response) {
    try{
      if(obj.success && typeof obj.success == 'function'){
        if(response.data.code == 999){
                    // store.dispatch('setLoginStatus', 0)
                    // store.dispatch('setToken', '')
                    // location.reload();
        }else{
          obj.success(response.data)
        }
      }else{
        throw "function 'success' undefind or it's not a function: This HttpRequest has no 'success' methods"
      }
    }
    catch(err){
      console.log('err',err);
    }
    
  })
  .catch(function (error) {
    if(obj.fail && typeof obj.fail == 'function'){
      obj.fail(error)
    }else{
      obj.fail = function(error){
        console.log('error',error);
        alert('网络请求错误');
      }
    }
  });
};
Vue.prototype.post = getReq;
export { getReq }
export default{
    getLoginUrl(redirectUri){
        return new Promise((resolve, reject) => {
            axios.post('', {
                request: 'public.auth.redirect.uri.get',
                platform: 'wxgzh',
                weburl: redirectUri,
                request_type:'request'
            }).then((data) => {
                console.log(data);
                if (data.data.code == 0) {
                    resolve(data.data.data.url)
                }
            }).catch((err) => {
                reject(err)
            });
        })

    },
    getToken(code){
        return new Promise((resolve, reject) => {
            axios.post('', {
                request: 'public.auth.login.to.user.action',
                platform: 'wxgzh',
                code: code,
                request_type:'request'
            }).then((data) => {
                if (data.data.code == 0) {
                    resolve(data.data.data.token)
                }
            }).catch((err) => {
                reject(err)
            });
        })
    }
}

封装的另一个请求方法( 支付功能 ):src->api->pay.js

import { getReq } from '../../http/http';
const payorders=(token,orderId)=>{
    return new Promise((resolve,reject) => {
        getReq({
            data:{
                request:'',
                token:token,
                request_type:'request',
                id: orderId
            },
            success: res => {
                if(res.code == 0){
                    console.log('支付请求成功');
                    console.log(res.data);
                    resolve(res)
                }else{
                    console.log(res.msg ? res.msg : {msg: 'request err'});
                    reject(res)
                }
            }
        });
    })

};
export { payorders }

微信公众号vue文件中使用定位功能是这样使用的:

import { getLocation,wxUtils } from "@/utils/WXUntil";
import config from '@/utils/config';

created(){
    wxUtils(this.$store.getters.token,config.baseURL).then(() => {
         this.getLocationFn();
    }).catch(() => {});
},
methods: {
    getLocationFn(){
       getLocation().then((res) => {
          //获取的经纬度传到 vuex 里
          this.$store.commit('getLocation',res)
       }).catch((err) => {
           console.log(err)
       })
    },

config.js文件是接口传入的url ( 公共地址+ 路由 ) , src->utils->config.js:

export default {
    baseURL:''
}

微信公众号vue文件中使用上传图片功能是这样使用的:

//上传截图
            addVipImage:function(){
                wxUtils(this.$store.getters.token,config.baseURL + this.$route.path).then(() => {
                    wx.chooseImage({
                        count: 1, // 默认9
                        sizeType: ['original', 'compressed'], // 可以指定是原图还是压缩图,默认二者都有
                        sourceType: ['album', 'camera'], // 可以指定来源是相册还是相机,默认二者都有
                        success: res => {
                            var localIds = res.localIds; // 返回选定照片的本地ID列表,localId可以作为img标签的src属性显示图片
                            this.imgSrc = localIds[0];
                            this.uploadImages(localIds[0])
                        }
                    });
                }).catch(() => {});
            },
            uploadImages:function(localIds){
                wx.uploadImage({
                    localId: localIds, // 需要上传的图片的本地ID,由chooseImage接口获得
                    isShowProgressTips: 1, // 默认为1,显示进度提示
                    success: res => {
                        this.serverId = res.serverId; // 返回图片的服务器端ID
                    }
                });
            },

获取的 图片的服务器端ID 将在请求后台接口时作为参数传递。以上的上传图片功能是一张图片,多张图片仍然要对数据进行必要的处理。一下是我看到讲解多张图片最清楚的博客(其实是代码清晰

):https://blog.csdn.net/weixin_42330073/article/details/82992107

微信公众号vue文件中使用支付功能是这样使用的:

import { WXinvoke,wxUtils } from "@/utils/WXUntil";

//必要的时候调用此方法进行微信配置初始化
created(){
    wxUtils(this.$store.getters.token,location.href).then(() => {}).catch(() => {})
}

//    支付的点击事件
wxPayInside:function () {
      this.post({
          data:{
             request:'',
             token:this.$store.getters.token,
             request_type: 'request',
              gun_id: this.oilQ,
              oil_money: this.oilM,
              store_id: this.store_id
           },
           success: res => {
              if(res.code === 0){
                 //获取orderId
                 var order_id = res.id;
                 WXinvoke(this.$store.getters.token, order_id, this.orderSuccess);
              }
       }
    })
},
//    订单提交成功的回调
orderSuccess(){
    this.$router.push('/nearby_oil');
 }

参考微信js-SDK说明文档:https://developers.weixin.qq.com/doc/offiaccount/OA_Web_Apps/JS-SDK.html

12. html表格表头不动,表头以下可滑动

人狠话不多,上代码。

html:

<div class="m2">
                    <div class="m-demo">
                        <table border="0">
                            <thead>
                            <tr>
                                <th>好友手机号</th>
                                <th>获得时间</th>
                                <th>奖励的礼品</th>
                            </tr>
                            </thead>
                        </table>
                        <div class="gains">
                            <table border="0">
                                <tbody>
                                <tr>
                                    <td>135****1652</td>
                                    <td>2018-9-24</td>
                                    <td style="color:#FDD31B">5元优惠券</td>
                                </tr>
                                </tbody>
                            </table>
                        </div>
                        <div class="noMore" v-if="false">暂无邀请战绩</div>
                    </div>
                </div>

css:

.m2{
                    width: 100%;
                    box-sizing: border-box;
                    padding: 25rem/@wid 20rem/@wid 27rem/@wid 20rem/@wid;
                    background-color: rgba(0,0,0,0.3);
                    margin: 20rem/@wid 0;
                    border-radius: 15rem/@wid;
                    color: #fff;
                    table{
                        width: 100%;
                        border-collapse:collapse;
                        border-spacing:0;
                        tr{
                            th{
                                width: 33.3%;
                                font-weight: normal;
                                line-height: 50rem/@wid;
                                font-size:24rem/@wid;
                            }
                            td{
                                width: 33.3%;
                                text-align: center;
                                line-height: 48rem/@wid;
                                font-size:22rem/@wid;
                            }
                        }
                    }
                    .m-demo{width: 100%;}
                    .m-demo .gains{width: 100%;height:230rem/@wid;border-top:0;overflow-y:auto;}
                    .m-demo .gains::-webkit-scrollbar{display: none}
                    .m-demo .gains .noMore{width: 100%;text-align:center;margin-top: 30rem/@wid;color: #999999;font-size: 30rem/@wid}
                    .m-demo table{width:100%;table-layout:fixed;}
                    .m-demo thead th:last-child,.m-demo tbody td:last-child{width:auto;}
                    .m-demo tbody tr:first-child td{border-top:0;}
                    .m-demo tbody tr:last-child td{border-bottom:0;}
                    .m-demo tbody tr td:first-child{border-left:0;}
                    .m-demo tbody tr td:last-child{border-right:0;}
                }

13. input自动获取焦点

<input ref="input">
 mounted() {
    this.$refs['input'].focus()
    // this.$refs['input'].value = ''
  }

本文分享自微信公众号 - 生南星(gh_36d61425a5dc)

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2019-09-29

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

扫码关注云+社区

领取腾讯云代金券