想法来源
关于输入,input标签和textarea标签可以满足我们90%以上的需求,但有些时候有些一些特殊需求,或者在改别人的项目时,换标签不方便,这个时候需求就没办法无法满足。
此时,我们就可以使用div等一些标签来实现
本文涉及知识点
属性:contenteditable是一个枚举属性,表示元素是否可被用户编辑。 如果可以,浏览器会修改元素的部件以允许编辑。
当标签加上这个属性时,就可进行内容编辑,来实现输入的效果。并且实现placeholder效果,如下
//html
<div>请在下方的框中输入你喜欢的句子</div>
<div contenteditable placeholder='请输入文字' class="input"></div>
//css
.input {
width: 500px;
height: 24px;
line-height: 24px;
font-size: 14px;
padding: 5px 8px;
border: 1px solid #ddd;
}
.input:empty::before {
content: attr(placeholder);
}
如下
这里由于下面会用到,这里先直接列出
大部分知道contenteditable属性有 true 和 false。,但是不止这些
contenteditable属性值
contenteditable="" //表示元素是可编辑的
contenteditable="events"
contenteditable="caret"
//让div只能键入文本值
//兼容性不好,除了谷歌,火狐ie都不支持
contenteditable="plaintext-only"
contenteditable="true"//表示元素是可编辑的
contenteditable="false" //表示元素是不可编辑的
至于contenteditable=“events”,contenteditable="caret"我也没有查到是什么意思,但是下面用不上我们这里就不深挖了
双向绑定
我们都知道,div是无法使用 v-model,那么该如何实现双向绑定呢?
//html
<div id="id">
<div>请在下方的框中输入你喜欢的句子</div>
<div contenteditable placeholder='请输入文字' class="input" v-html="content" @input="content=$event.target.innerHTML"></div>
<div>{{content}}</div>
</div>
<div contenteditable placeholder='请输入文字' v-html="item.content"></div>
//js
var id = new Vue({
el: "#id",
data: {
content: "",
},
})
但是有时只想复制文本,却发现复制过来的是标签+标签样式,那么改如何处理?
这个时候就要用到contenteditable="plaintext-only"
但是实际使用上有很多问题,比如光标的问题,我们可以依靠组件来对这些问题进行处理
<div id="app">
<m-contenteditable :child="content"></m-contenteditable>
<m-contenteditable :child="content"></m-contenteditable>
<div><pre v-html="content.txt"></pre></div>
</div>
<script>
//定义一个全局组件
Vue.component("mContenteditable",{
props:{
child:{
type:Object,
default:{
txt:""
}
}
},
//数据
data:function(){
return {
innerText:this.child.txt,
lock:false
}
},
//侦听器
watch:{
child:{
handler(newValue, oldValue) {
if(!this.lock) {
this.innerText=this.child.txt;
};
},
deep:true
}
},
//改变的方法
methods:{
changeTxt:function(e){
this.child.txt=this.$el.innerHTML;
}
},
//模板
template:`<div class="box" contenteditable="true" v-html="innerText" @input="changeTxt" @focus="lock=true" @blur="lock=false"></div>`
});
new Vue({
el:"#app",
data:{
content:{
txt:"内容<img src=\"http://pub.idqqimg.com/lib/qqface/0.gif\" width=\"38\" height=\"38\">"
}
}
});