textarea元素设置placeholder的怪异点

257 阅读1分钟

开发时遇到过这样的需求:

用一个textarea控件录入一段长文本,它的placeholder需要异步的动态设置。

怪异点在于,在ios移动设备上,如果初始时,文本框的valueplaceholder都是空字符串。那么当异步设置placeholder值时会出现设置失效的情况,需要你聚焦一下文本框,placeholder才会出现。而PC端浏览器无此问题。

下面是可以复现bug的代码,也可以直接访问CodePen - Weirdness of the placeholder in textarea (cdpn.io)来查看

<div id="app">
  <textarea :placeholder="placeholder"></textarea>
</div>
const app = new Vue({
  el: "#app",
  data: {
    placeholder: ""
  },
  mounted() {
    setTimeout(() => {
      this.placeholder = "ph";
    }, 1000);
  }
});

线上版本

经过测试发现,复现此问题还需要一个必要条件就是异步设置的placeholder字符串足够短,没有超过文本域的高度。如果placeholder字符串的长度够长的话也不会出现这个bug——比如说你设置一个This is a placeholder.This is a placeholder.This is a placeholder.This is a placeholder.This is a placeholder.This is a placeholder.This is a placeholder.This is a placeholder.This is a placeholder.This is a placeholder.This is a placeholder.这种超过文本域高度的字符串。

为了再次排除是否是vue的原因,我还尝试用原生js来实现这个过程。结果是bug仍然存在。

<div id="app">
  <textarea id="textarea" placeholder=""></textarea>
</div>
setTimeout(() => {
  document.querySelector('#app').setAttribute('placeholder', 'ph')
}, 1000)

起初发现这个问题是我在用vant开发时发现的,以为是vant的bug,还向vant提了一个issue。但其实是原生textarea渲染的一个坑。

为了解决这个问题,可以利用一个hack:将初始的placeholder值设置成' ',一个空格字符串,就不会出现这个问题了。