分类 技术宅的演示性文稿 下的文章

mint-ui是vue开发中常用的组件库,而loadmore 通常用于处理下拉加载与上拉加载

坑1、页面渲染完,loadmore设置的上拉/下拉执行两次
产生原因:loadmore设置中的auto-fill需要设置为false

实现代码如下:

<load-more :bottom-method="loadBottom" :bottom-all-loaded="isLoadAll" ref="loadmore" :auto-fill="false"> 
    <div v-for="item of datas">
      <p>{{item}}</p>
    </div>
</load-more>

坑2、页面上拉/下拉后一直加载不结束,loadmore的加载中一直转圈圈
如下图所示

产生原因:数据加载时未调用 onBottomLoaded()方法

实现代码如下

<load-more :bottom-method="loadBottom" :bottom-all-loaded="isLoadAll" ref="loadmore" :auto-fill="false"> 
    <div v-for="item of datas">
      <p>{{item}}</p>
    </div>
</load-more>
loadBottom() {
        if (!this.isLoadAll) {
          this.$refs.loadmore.onBottomLoaded(); //通知loadmore组件从新渲染,计算
          this.currentPage++;
          //网络请求加载数据  省略
        } else {
          console.log("已加载全部");
        }
      },

坑3、loadmore上拉/下拉加载与滚动事件冲突,造成页面卡顿,滑动会回弹
这个坑是比较隐蔽的,一开始也是一头雾水,后面查看了loadmore组件的源码,在源码中才找到一点端倪

mint-ui的loadmore组件触发下拉/上拉加载的原理:(源码:http://mint-ui.github.io/docs/#/en2/loadmore

checkBottomReached() {
   if (this.scrollEventTarget === window) {
      return document.body.scrollTop + document.documentElement.clientHeight >= document.body.scrollHeight;
   } else {
      return this.$el.getBoundingClientRect().bottom <= this.scrollEventTarget.getBoundingClientRect().bottom + 1;
   }
},

仔细阅读源码会发现,下拉/上拉加载的触发条件是父组件与组件本身距离底部的高度是一样的,即:

this.$el.getBoundingClientRect().bottom 与 this.scrollEventTarget.getBoundingClientRect().bottom + 1 的值基本相等,造成滑动时并就好触发上拉/下拉加载,从而加载数据,页面滚动卡顿

解决方法:

将父组件的高度设置为屏幕所需要展示的高度(如果需要全屏展示,就设置为100%)

注:如果要下拉/上拉加载一定要保证父组件高度小于下拉组件本身
————————————————
版权声明:本文为CSDN博主「涟动下渔舟」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/woyidingshijingcheng/article/details/79899823

我们在做一个密码输入框的时候,模仿了6位支付密码输入的弹框输入。但是这6个密码框是6个单独的input。安卓下面没有发现什么问题,但是在IOS输入的时候,每输入一位数字,IOS会重新弹起键盘,并且重置键盘类型(英文输入和数字输入)。

如果把input的type类型改为tel或者number的时候,是可以做到软键盘弹出时候不来回切换键盘类型,但是输入框变成了明文,那么我们又想实现不让键盘切换,又要使用password类型怎么办呢?

 <input type="password"  pattern="[0-9]*" inputmode="numeric"> 

我们加上一个html5.1的新属性inputmode="numeric"

HTML 5.1 草稿包含 inputmode 属性,它已被设计以解决输入模式(如键盘)选择的具体问题,但它尚未实施。
尽管如此,您可以在将来使用它目前的HTML5.1不允许它为 type = password ,出于某种奇怪的原因

加上以后,解决了我们的这个问题。但是实际上效果并不是很好。个人还是建议以虚拟键盘和输入框的形式来进行模拟,而不是用input框来输入

微信的SDK自从更新了1.8.6以后在APIcloud使用wxPlus模块进行微信登录,微信分享的时候就会报一个-1未知错误。今天查了资料,发现是必须填写universalLink这个东西(看见这玩意儿一脸懵逼……)后来才知道是用来APP进行跳转的。之前是使用的URL Schemes方式跳转APP,现在为了安全问题,更改成了universalLink方式跳转,所以更新以后,我们需要重新设置一下。

一、我们准备一个有https的服务器(必须要有https)。

二、这个时候需要在服务器上制作一个apple-app-site-association文件。这个文件其实就是一个JSON对象。不需要有任何后缀。内容如下

{
  "applinks":{
    "apps":[],
    "details":[
        {
            "appID": "******",
            "paths": ["*"]
        }
    ]
   }
 }

APPID就是用前缀+bundleID的方式
出来的数据大概是USDHUS82.com.teaxia.teg这种形式的。这个在苹果开发者平台的后台就可以找到了
1176193-6a951ecb3a95a38d_看图王.png
这里面的paths是访问APP的对应页面路径,其实可以只填一个通配符就可以了
我们把准备好的apple-app-site-association文件放入我们准备好的https的服务器下面,比如我测试用的就是
https://www.teaxia.com/app

三、在微信的开发者平台,填入刚刚我们制作好的UniversalLink地址。(比如我现在的就是https://www.teaxia.com/app 不用加文件名)

四、在App Store应用管理开启Associated Domains
1176193-9c46a5edad704f5b.png
这里添加了Domains以后,还需要重新更新下载一下IOS的描述文件,描述文件的制作这里就不再阐述了,不清楚如何制作的同学,可以去这里查看https://docs.apicloud.com/Dev-Guide/iOS-License-Application-Guidance

五、在apicloud的config里面配置

<feature name="wxPlus">
    <param name="urlScheme" value="wxd0d84bbf23b4a0e4"/>
    <param name="apiKey" value="wxd0d84bbf23b4a0e4"/>
    <param name="apiSecret" value="a354f72aa1b4c2b8eaad137ac81434cd"/>
    <param name="universalLink" value="https://www.teaxia.com/app"/>
</feature>

以上的配置大家自行改成自己的配置信息

六、创建 entitlements 文件(.entitlements是xml格式的文件)
新建一个文本文档,修改内容后命名为UZApp.entitlements文件,然后将文件放置在widget网页包的res目录下,云编译时会将里面的内容添加到编译工程里面的UZApp.entitlements中。
UZApp.entitlements内容如下

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
     <dict>
        <key>com.apple.developer.associated-domains</key>
        <array>
            <string>applinks:domain.com</string>
        </array>
     </dict>
 </plist>

applinks:domain.com这个也是直接填写www.teaxia.com/app
准备好以上信息后,使用云编译打包一次就可以愉快的玩耍了:)

把项目脚手架升级为cli3.X了以后,模板简洁了很多,运行起来也更加快速。但是也随之而来是某些兼容问题。比如我们要在项目钟使用px2rem来计算设计稿的时候,我们不能像以前老的脚手架那样操作了。那我们应该来如何设置呢?
首先,我们应该用NPM来安装postcss-px2rem

npm i postcss-plugin-px2rem  --save -dev

然后我们需要在vue.config.js中创建一个配置。由于在vue-cli3.X中。去掉了build和config文件夹。所有的配置都放到了vue.config.js,然而这个文件脚手架并没有生成,所以需要手动在项目的根目录创建一个文件
在vue.config.js里配置

module.exports = {
    lintOnSave: true,
    css: {
        loaderOptions: {
            postcss: {
                plugins: [
                    require('postcss-plugin-px2rem')({
                        rootValue:75,           // 新版本的是这个值
                        mediaQuery: false,  //(布尔值)允许在媒体查询中转换px。
                        minPixelValue: 3 //设置要替换的最小像素值(3px会被转rem)。 默认 0
                    }),
                ]
            }
        }
    },
}

这里需要说明一点。网上搜的一堆教程都强调应该增加remUnit来设置rem的计算标准。但是其实在新版后,这个值换成了rootValue这个。例如你设计稿为750的宽度标准,那么这里的值设置为75则可。

接下来还有一个工作。由于rem是根据根字体的大小来作为基准值的,然而我们的移动设备屏幕大小以及有些屏幕为视网膜屏的,会是普通屏幕的2倍,所以这个基准值我们需要根据不同设备来进行计算。这里我们在src/plugins下新建一个rem.js文件(代码如下)。

(function (win, lib) {
    var doc = win.document;
    var docEl = doc.documentElement;
    var metaEl = doc.querySelector('meta[name="viewport"]');
    var flexibleEl = doc.querySelector('meta[name="flexible"]');
    var dpr = 0;
    var scale = 0;
    var tid;
    var flexible = lib.flexible || (lib.flexible = {});

    if (metaEl) {
        //console.warn('将根据已有的meta标签来设置缩放比例');
        var match = metaEl.getAttribute('content').match(/initial\-scale=([\d\.]+)/);
        if (match) {
            scale = parseFloat(match[1]);
            dpr = parseInt(1 / scale);
        }
    } else if (flexibleEl) {
        var content = flexibleEl.getAttribute('content');
        if (content) {
            var initialDpr = content.match(/initial\-dpr=([\d\.]+)/);
            var maximumDpr = content.match(/maximum\-dpr=([\d\.]+)/);
            if (initialDpr) {
                dpr = parseFloat(initialDpr[1]);
                scale = parseFloat((1 / dpr).toFixed(2));
            }
            if (maximumDpr) {
                dpr = parseFloat(maximumDpr[1]);
                scale = parseFloat((1 / dpr).toFixed(2));
            }
        }
    }

    if (!dpr && !scale) {
        var isAndroid = win.navigator.appVersion.match(/android/gi);
        var isIPhone = win.navigator.appVersion.match(/iphone/gi);
        var devicePixelRatio = win.devicePixelRatio;
        if (isIPhone) {
            // iOS下,对于2和3的屏,用2倍的方案,其余的用1倍方案
            if (devicePixelRatio >= 3 && (!dpr || dpr >= 3)) {
                dpr = 3;
            } else if (devicePixelRatio >= 2 && (!dpr || dpr >= 2)) {
                dpr = 2;
            } else {
                dpr = 1;
            }
        } else {
            // 其他设备下,仍旧使用1倍的方案
            dpr = 1;
        }
        scale = 1 / dpr;
    }

    docEl.setAttribute('data-dpr', dpr);
    if (!metaEl) {
        metaEl = doc.createElement('meta');
        metaEl.setAttribute('name', 'viewport');
        metaEl.setAttribute('content', 'initial-scale=' + scale + ', maximum-scale=' + scale + ', minimum-scale=' + scale + ', user-scalable=no');
        if (docEl.firstElementChild) {
            docEl.firstElementChild.appendChild(metaEl);
        } else {
            var wrap = doc.createElement('div');
            wrap.appendChild(metaEl);
            doc.write(wrap.innerHTML);
        }
    }

    function refreshRem() {
        var width = docEl.getBoundingClientRect().width;
        if (width / dpr > 540) {
            width = 540 * dpr;
        }
        var rem = width / 10;
        docEl.style.fontSize = rem + 'px';
        flexible.rem = win.rem = rem;
    }

    win.addEventListener('resize', function () {
        clearTimeout(tid);
        tid = setTimeout(refreshRem, 300);
    }, false);
    win.addEventListener('pageshow', function (e) {
        if (e.persisted) {
            clearTimeout(tid);
            tid = setTimeout(refreshRem, 300);
        }
    }, false);

    if (doc.readyState === 'complete') {
        doc.body.style.fontSize = 12 * dpr + 'px';
    } else {
        doc.addEventListener('DOMContentLoaded', function (e) {
            doc.body.style.fontSize = 12 * dpr + 'px';
        }, false);
    }


    refreshRem();

    flexible.dpr = win.dpr = dpr;
    flexible.refreshRem = refreshRem;
    flexible.rem2px = function (d) {
        var val = parseFloat(d) * this.rem;
        if (typeof d === 'string' && d.match(/rem$/)) {
            val += 'px';
        }
        return val;
    }
    flexible.px2rem = function (d) {
        var val = parseFloat(d) / this.rem;
        if (typeof d === 'string' && d.match(/px$/)) {
            val += 'rem';
        }
        return val;
    }

})(window, window['lib'] || (window['lib'] = {}));

然后在main.js里面引入该文件

import './plugins/rem.js'

这样,我们的工作就完成了。可以直接在css里面写px的绝对值。
demo1.jpg

demo2.jpg

npm install --save vue-clipboard2

使用NPM管理安装vue-clipboard2后,在vue的main.js里面,引入

import VueClipboard from 'vue-clipboard2'
Vue.use(VueClipboard)

至此,插件引入完毕;
使用方法

v-clipboard:copy="需要复制的内容"

  v-clipboard:success="onCopy" // 复制成功的回调

  v-clipboard:error="onError" // 复制失败的回调

比如点击按钮,然后复制的话,可以这样使用

<button v-clipboard:copy="需要复制的内容" v-clipboard:success="onCopy" v-clipboard:error="onError">复制</button>