19Y-04M: Swiper滑块绑定Vue点击事件失效问题。
使用Swiper 3.3.1做页面轮播,接口取到数据后创建Swiper实例,在滑块上绑定Vue点击事件@click,初始点击跳转生效,滑动或点击后不再生效。
解决办法:给滑块定义data-href属性传递url跳转地址,在Swiper实例属性onClick属性上获取地址后跳转。

公告区轮播DIV:
<div class="tip">
    <i class="tip-laba"></i>
    <div class="swiper-container" id="noticeSwiper">
        <div class="swiper-wrapper">
            <div v-for="(item, index) in data" :key="index" :data-href="item.url" class="swiper-slide" @click="goPage(item.url)">
                <div class="tip-item">
                  <p class="txt">{{ item.title }}</p>
                  <i class="icon-arrow"></i>
                </div>
            </div>
        </div>
    </div>
</div>

let swiper = new Swiper('#noticeSwiper', {
    initialSlide: 0,
    direction : 'vertical',
    paginationClickable: true,
    slidesPerView: 1,
    preventClicks: false,
    speed: 1000,
    autoplay: 3000,
    autoplayDisableOnInteraction: false,
    loop: data.length > 1 ? true : false,
    onClick: (swiper, e) => {
      this.goPage($(swiper.clickedSlide).data('href'))
    }
})

20Y-04M1:Swiper滑块在荣耀畅玩4手机上下沉或不展示问题。

页面元素同上,外层元素(class="tip")设置了高度,但未给swiper元素设置高度:
.tip {
  min-height: .7rem;
  padding: .14rem .3rem;
  background: #fffbf4;
}
解决办法:给Swiper设置高度
/*fix 荣耀4畅玩轮播公告文字不出现兼容bug*/
.tip .notice-swiper{
  height: .7rem;
}

20Y-04M2:background-size在ISO和Android上表现不一致问题。

<p>
  <i class="doc-video doc-audio"></i>文本内容
</p>
当跳转内容是视频时,只使用.doc-video展示视频小图标;当内容是音频时,叠加使用.doc-audio展示音频小图标。在IOS上表现正常,在Android上音频小图标只展示了左上角四分之一。
.doc-video { // 视频小图标,
  display: inline-block;
  vertical-align: middle;
  width: 24px;
  height: 24px;
  background: url(../images/icon-video.png) no-repeat;
  background-size: 100% 100%;
}
.doc-audio { // 音频小图标
  background: url(../images/icon-audio.png) no-repeat;
}

解决办法:.doc-audio覆盖.doc-video的background样式时,去掉了background-size属性,把这个属性加上Android上也正常了。
.doc-audio { 
  background: url(../images/icon-audio.png) no-repeat;
  background-size: 100% 100%;
}

background-size 属性规定背景图像的尺寸。

20Y-05M:HTML5 <input type="number'/>手机浏览器不支持

在Android/iOS手机上:
  <input type="number"/>  // 唤起数字键盘,不是纯数字键盘,且设置type=number情况下,一旦输入字母,keydown/keypress/keyup获取的e.target.value变为空
  <input type="tel" pattern="[0-9]*"/> // 唤起纯数字键盘,pattern生效,建议使用

20Y-05M1:自定义Vue指令限制HTML5输入框可输入类型
(代码兼容Android和iOS)
(1)<input v-enter-chars:50 type="text" placeholder="请输入真实姓名">

/**
 * 只允许输入中英文字符
 * @directive: v-enter-chars
 */
export let enterChars = {
  bind(el, binding) {
    const bindLen = isNaN(binding.arg) ? 500 : Number.parseInt(binding.arg)  // 默认限制长度500
    const nonChar = /[^\u4e00-\u9fa5a-zA-Z]/ig // 非汉字或英文字符Regex i 大小写不敏感 g 全局匹配
    const target = el instanceof HTMLInputElement ? el : el.querySelector("input")

    target.addEventListener("keyup", e => {
      console.warn('keyup -- e.target.value', e.target.value); // keyup是获取触发事件之后的值

      if (/[a-zA-Z]$/.test(e.target.value)) { // 字母按键可能是在输入中文
        const strLen = e.target.value.replace(/[^\x00-\xff]/g,"01").length // 计算字符串长度(区分中文和英文)
        console.log('strLen', strLen, 'limit', bindLen);
        if (strLen > bindLen) {
          e.target.value = getSubStr(e.target.value, bindLen)
        }
        e.target.dispatchEvent(new Event("input"))
      } else {
        if (nonChar.test(e.target.value)) {
          e.target.value = e.target.value.replace(nonChar, "")
        }
        const strLen = e.target.value.replace(/[^\x00-\xff]/g,"01").length // 计算字符串长度(区分中文和英文)
        console.log('strLen', strLen, 'limit', bindLen);
        if (strLen > bindLen) {
          e.target.value = getSubStr(e.target.value, bindLen)
        }
        e.target.dispatchEvent(new Event("input"))
      }
    })

    target.addEventListener("paste", e => {
      console.warn('paste -- e.target.value', e.target.value);
      if (nonChar.test(e.target.value)) {
        e.target.value = e.target.value.replace(nonChar, "")
      }
      const strLen = e.target.value.replace(/[^\x00-\xff]/g,"01").length // 计算字符串长度(区分中文和英文)
      console.log('strLen', strLen, 'limit', bindLen);
      if (strLen > bindLen) {
        e.target.value = getSubStr(e.target.value, bindLen)
      }
      e.target.dispatchEvent(new Event("input"))
    })
  }
}

// 从头截取指定长度字符串,区分中英文
function getSubStr(str, limit) {
  let count = 0
  let result = ''
  for (let i = 0; i < str.length; i++) {
    let charCode = str.charCodeAt(i)
    if (charCode >= 0 && charCode <= 128 && count + 1 <= limit) {
      result += str[i]
      count++
    } else if (count + 2 <= limit) {
      result += str[i]
      count += 2
    } else {
      break
    }
  }
  return result
}

(2)<input v-restrict:11="/\D/g" type="tel" pattern="[0-9]*" placeholder="请输入手机号码">

/**
 * 限制输入
 * 限制内容正则表达式由指令绑定值传入,如: v-restrict:15="/\D/" 限制输入非数字,长度限制15个字符
 * @directive: v-restrict
 */
export let restrict = {
  bind(el, binding) {
    const bindLen = isNaN(binding.arg) ? 500 : Number.parseInt(binding.arg)  // 默认限制长度500
    const bindReg = binding.value instanceof RegExp ? binding.value : new RegExp("") // 默认不限制输入内容
    const target = el instanceof HTMLInputElement ? el : el.querySelector("input")
    target.addEventListener("keydown", e => {
      console.warn('v-restrict -- keydown -- e.target.value', e.target.value); // keydown, keypress 是获取触发事件之前的值
      // 如果HTML5 <input>标签的type=number,则输入字母后,获取的e.target.value变为空
      if (bindReg.test(e.target.value)) { // Regex check
        e.target.value = e.target.value.replace(bindReg, "")
        // e.target.dispatchEvent(new Event("input"))
      }
      if (e.target.value.length >= bindLen) {
        e.target.value = getSubStr(e.target.value, bindLen)
        // if (e.preventDefault) {
        //   e.preventDefault()
        // } else {
        //   e.returnValue = false
        // }
      }
      e.target.dispatchEvent(new Event("input"))
    })
    target.addEventListener("keyup", e => {
      console.warn('v-restrict -- keyup -- e.target.value', e.target.value); // keyup是获取触发事件之后的值
      if (bindReg.test(e.target.value)) { // Regex check
        e.target.value = e.target.value.replace(bindReg, "")
        // e.target.dispatchEvent(new Event("input"))
      }
      if (e.target.value.length >= bindLen) {
        e.target.value = getSubStr(e.target.value, bindLen)
        // if (e.preventDefault) {
        //   e.preventDefault()
        // } else {
        //   e.returnValue = false
        // }
      }
      e.target.dispatchEvent(new Event("input"))
    })

    target.addEventListener("paste", e => {
      console.warn('v-restrict -- paste -- e.target.value', e.target.value); // keyup是获取触发事件之后的值
      if (bindReg.test(e.target.value)) { // Regex check
        e.target.value = e.target.value.replace(bindReg, "")
      }
      if (e.target.value.length >= bindLen) {
        e.target.value = getSubStr(e.target.value, bindLen)
      }
      e.target.dispatchEvent(new Event("input"))
    })
  }
}


// 从左往右截取字符串指定长度,区分中英文
function getSubStr(str, limit) {
  let count = 0
  let result = ''
  for (let i = 0; i < str.length; i++) {
    let charCode = str.charCodeAt(i)
    if (charCode >= 0 && charCode <= 128 && count + 1 <= limit) {
      result += str[i]
      count++
    } else if (count + 2 <= limit) {
      result += str[i]
      count += 2
    } else {
      break
    }
  }
  return result
}

20Y-08M1:new Date(date)在ios下的兼容性问题。

Google浏览器上new Date('2017-03-08 01:01')
能正确显示, 但是在iOS上或者苹果的Safari浏览器上一直显示NaN,发现是iOS的日期格式跟Windows不一样。
let startTime = new Date('2017-03-08 00:00:00');   //ios中starTime为NaN
let startTime2 = new Date('2017-03-08T00:00:00');  //日期和时间中间加个T,兼容ios
或者
let startTime3 = new Date('2017-03-08 00:00:00'.replace(/\-/g, '/'));  //把横杠-换成斜杠/,兼容ios

20Y-08M2:微信端从主页面跳转二级页面选择日期并存储在session缓存,history.back或history.go(-1)返回主页面后,没刷新页面,导致主页面时没有重新执行Vue的声明周期函数,未能获取缓存。

[onpageshow 监听页面是否是缓存页面。](https://www.cnblogs.com/leolovexx/p/7026022.html)

[onpageshow 事件在用户浏览网页时触发。](https://www.runoob.com/jsref/event-onpageshow.html)
onpageshow 事件类似于 [onload] 事件,onload 事件在页面第一次加载时触发, onpageshow 事件在每次加载页面时触发,即 onload 事件在页面从浏览器缓存中读取时不触发。

为了查看页面是直接从服务器上载入还是从缓存中读取,你可以使用 PageTransitionEvent 对象的 persisted 属性来判断。 如果页面从浏览器的缓存中读取该属性返回 ture,否则返回 false。

20Y-08M3:在JS代码中使用了数组的方法Array.isArray(ECMAScript 5.1新增),导致兼容测试在华为荣耀畅玩4、OPPO r9m两款机型上不通过,其他机型测试都通过。

通过排除未使用ES6新语法,确定是未加babel-polyfill垫片导致。
解决办法:由于webpack打包多页项目时没有将babel-polyfill放入每个entry的最前面,也没有单独抽出来放到dll中,所以必须在每个页面单独引入。单独引入方法有require('babel-polyfill')或者import,这两种方式都会经过多余打包,所以用原生的标签引入资源。
<script src="{{data.cdn}}static/js/polyfill.min.js"></script>

其他数组方法所属规范:
Array.map-- ECMAScript 1.6
Array.forEach -- ECMAScript 3
Array.keys() -- ECMAScript 6

20Y-08M4:搭建了多页项目框架golf-home,为了使用ES6及更高级语法,使用了(webpack4+babel7+preset-env预设)在打包时转义成ES5。项目没有新建.babelrc或babel.config.js配置文件,使用默认推荐配置。由于忘记显示配置preset-env,导致箭头函数等都没转义,兼容测试不通过。

package.json:
    "@babel/core": "^7.9.6",
    "@babel/plugin-transform-runtime": "^7.9.6",
    "@babel/preset-env": "^7.9.6",
    "add-asset-html-webpack-plugin": "^3.1.3",
    "babel-loader": "^8.1.0",

webpack.config.js: 未配置babel预设
      {
        test: /\.js$/,
        loader: 'babel-loader?cacheDirectory',
        include: resolve('src'),
        exclude: resolve('src/assets/swiper.min.js'),
      },
配置babel预设后,成功转义箭头函数等高级语法,兼容测试通过:
      {
        test: /\.js$/,
        loader: 'babel-loader?cacheDirectory',
        include: resolve('src'),
        exclude: resolve('src/assets/swiper.min.js'),
        options: {
          presets: ['@babel/preset-env']
        }
      },
 
 备注:
 webpack4以上内置babel-polyfill,设置useBuiltIns才会生效,usage会根据配置的浏览器兼容,以及你代码中用到的 API 来进行 polyfill,实现了按需添加;
 此外,babel-preset-env 插件借助了browserslist库提供了对浏览器版本的配置能力,如在.babelrc添加配置:
{
  "presets": [
    ["@babel/env", {
      "targets": {
        "node": "current",
        "chrome": 52,
        "browsers": ["last 2 versions", "safari 7"]
      }
    }]
  ]
}
也可在package.json中配置browserslist,如下:
"browserslist": [ 
    "> 1%", 
    "last 2 versions", 
    "not dead" 
]
配置优先级:
targets.browsers > package.json/browserslist

参考一:关于Babel你只需要知道三个插件
参考二:babel-preset-env使用指南
参考三:useBuiltIns

21Y-04M1:Swiper 3.3.1在配置里设置点击事件,触摸滑动时也触发了点击事件。

var swiperInstance = new Swiper(
    "#advanceSwiper" + area.areaCode,
    {
        autoplay: number > 1 ? 5000 : 0,
        autoplayDisableOnInteraction: false,
        onClick(swiper) {
            // 触摸滑动也会触发click事件
            // 如果是水平滑动,currentX和startX不会相等
            if (swiper.touches.currentX == swiper.touches.startX) {
                var dataIndex = $(swiper.clickedSlide).data(
                    "swiper-slide-index"
                );
                var item = area.shopWindowList[dataIndex] || {}
                var href = $(swiper.clickedSlide).data("href")
                _this.goPage(item.actionUrl || href)
            }
        },
        loop: number > 1 ? true : false
    }
)

JohnsonGH
32 声望1 粉丝