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。