兼容性问题,这几天要抓狂了

2,037 阅读2分钟

1、是著名的输入框输入时被遮挡的问题

      解决方案:focus的时候

setTimeout(function(){   
    document.body.scrollTop = document.body.scrollHeight - 20;
},300);

2、又是著名的输入时底部的固定定位的div会被弹起在键盘上

      解决方案:

     1、监听输入时让底部的隐藏,失去焦点时显示。  ×

     2、只能让原生开发提供键盘的唤醒和退出,然后我们来监听

     3、监听页面的滚动

let screenHeight = document.body.offsetHeight               let _this = this            // 为window绑定resize事件            window.onresize = function () {                let changeHeight = document.body.scrollHeight                if (changeHeight < screenHeight) {                    // 隐藏被弹起的固定定位                    _this.showFixedBottom = false                } else {                    // 显示                    _this.showFixedBottom = true                }            }

3、利用html2canvas生成图片时,textarea的多行输入不能控制显示,用line-height设置不能生效,且截图出来的图片只能展示一行,多余的被隐藏掉了。且设置的text-indent也不生效,查阅官方文档不支持改css属性。

       解决方案:将textarea换成

<div contenteditable="true" class="textarea"></div>

哎,安卓试一下,很好,这个问题解决了,hin开心。

下午拿ios一试,根本就无法输入=_=
接下来又是一百度,很多答案都是添加属性

-webkit-user-select:text;

真的这么简单吗,加一个css属性就好了

结果,并没有什么n用

问了一下旁边的人,他们用有赞的组件是可以实现输入框换行的

但是我这个项目没有用到有赞库

只能继续查找有没有fix方法

最后找到了一个方法,发现了无法输入的原因,是因为引入了fastclick.js这么一个库。

这个库导致这个可编辑的div被点击无法轻松的唤起输入法。 长按才能成功。

贴一波代码:

<div contenteditable="true" class="textarea needsclick" v-html="text"></div>
import FastClick from 'fastclick'
// const $ = window.$
// 点击延迟 因为和编辑器冲突, 重制起原型方法needsClick
const deviceIsWindowsPhone = navigator.userAgent.indexOf('Windows Phone') >= 0
const deviceIsIOS = /iP(ad|hone|od)/.test(navigator.userAgent) && !deviceIsWindowsPhone
FastClick.prototype.needsClick = function (target) {
  // 下面这句
  // 这是jq写法
  // if ($(target).parents('.needsclick').length) return true
  while (target.tagName !== 'BODY') {
   // 放在本地插件库, 请将includes换成indexOf判断
    if (target.className.includes('needsclick')) return true
    target = target.parentNode
  }

  switch (target.nodeName.toLowerCase()) {
    // Don't send a synthetic click to disabled inputs (issue #62)
    case 'button':
    case 'select':
    case 'textarea':
      if (target.disabled) {
        return true
      }

      break
    case 'input':

      // File inputs need real clicks on iOS 6 due to a browser bug (issue #68)
      if ((deviceIsIOS && target.type === 'file') || target.disabled) {
        return true
      }

      break
    case 'label':
    case 'iframe': // iOS8 homescreen apps can prevent events bubbling into frames
    case 'video':
      return true
  }

  return (/\bneedsclick\b/).test(target.className)
}
FastClick.attach(document.body)

注,以上解决方法引自:my.oschina.net/u/4267906/b…

_--------------------------------------------------------------------------------
_

你以为这样就够了吗=_=

需求里还写着最多20个字符

ding,用input事件不就好啦

发现并不生效。而且有一个hin奇怪的现象:输入一个字母光标就跑到前面去了,并且输入不了中文。

那么我们用v-model双向数据绑定呢,咦,v-model是不支持在div上用的,但是组件可以啊。没准我们还可以把它封装成一个组件,又多出品了一个组件啦(内心是开心的,问题一步步有眉目了,慢慢接近终点了)。

参考www.cnblogs.com/dreamsqin/p…

发现自己呢,还是无法实现最多20个字符。周末自己写代码生成脚手架项目的时候,发现awesome-vue里发现了vue-input-contenteditable这个插件,就是用div contenteditable来取代input的。

代码看起来

主要的代码是这段:

 let text = this.$refs.contenteditable.textContent;      //enforce a maxlength     
 if (this.maxlength !== -1) {        //I chose this instead of preventDefault on 'keydown', 'paste', 'drop' as if we preventDefault        
//we need to check a bunch of specific valid cases to pass through like backspace, delete        //Ctrl+A, A Ctrl+V that makes the text shorter, arrow keys, etc. which may be impossible...        //        //Instead, retroactively trimming the string after 'input' and setting the cursor properly        //(as changing the text string will change the cursor in some browsers... :( ) is a better bet        //IMO. Current method was tested in Chrome, FF, and Android      
  let selection = window.getSelection();        let { anchorNode, anchorOffset } = selection;        if (text.length > this.maxlength) {          //Find the cursor position inside the contenteditable. Can't use anchorOffset          //because Firefox will add multiple text nodes when pasting sometimes          //(and then collapse them later? it's kind of weird...)         
 const textNodes = Array.from(this.$refs.contenteditable.childNodes);          const realAnchorOffset = textNodes.length <= 1 ? anchorOffset : (            textNodes              //Collect all nodes up to, but not including, anchorNode              .slice(0, textNodes.indexOf(anchorNode))              //Map them all to their length              .map(n => n.textContent.length)              //Sum them together              .reduce((acc, itm) => acc + itm, 0) +              //And then add the final offset in the final node              anchorOffset);          //Use either the lastText if exists, or the current text but trimmed          const newTextToSet = this.lastText || text.slice(0,this.maxlength);          //Find the last position of the cursor before the input event. Use the          //current cursor position, and remove the difference between the untrimmed text          //and the trimmed text (to back the cursor up to the position the          //input event happened at)          //We can't use anchorOffset because FF likes to make new text nodes          //for pasted text for some reason??          let newOffsetToSet = realAnchorOffset - (text.length - newTextToSet.length);          newOffsetToSet = Math.min(newOffsetToSet, this.maxlength); // Make sure not over maxlength          //console.log(realAnchorOffset, anchorOffset, text.length, newTextToSet.length, this.$refs.contenteditable.childNodes.length);          //This will reset the cursor to the start of the contenteditable _and_          //make a new text node (so don't use anchorNode for selection.collapse())          this.$refs.contenteditable.textContent = newTextToSet;          //Set selection using last valid offset          selection.collapse(this.$refs.contenteditable.childNodes[0], newOffsetToSet);          this.lastText = newTextToSet;          return;        } else {          this.lastText = text;        }      }

-----上测试了,问题还很多

1、生成图片后,超过一行的,苹果手机会把两行文字重叠在一起。发现设置direction:rtl就不会重叠,但是这样会导致内容反着来展示了,比如 6277 **** **** 0090 展示成了0900 **** ****7726。很无奈,至今这个问题不能解决。如果只有文字是不会反着展示的,所以只能在全部都是文字并且没有空格可能会超过一行设置direction:rtl。