Editable non-input, texrarea+vue realizes two-way binding (take div tag as an example)

source of ideas

Regarding input, input tags and textarea tags can meet more than 90% of our needs, but sometimes there are some special needs, or when changing other people's projects, it is inconvenient to change tags. In this case, the needs cannot be met.
At this point, we can use some tags such as div to achieve

This article involves knowledge points

Attribute: contenteditable is an enumeration attribute that indicates whether the element can be edited by the user. If it can, the browser modifies the element's components to allow editing.
When this attribute is added to the tag, the content can be edited to achieve the input effect. And achieve the placeholder effect, as follows

//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);
        }
       

as follows
Insert image description here

Since it will be used below, we will list it directly here.
Most of us know that the contenteditable attribute has true and false. , but more than that

contenteditable attribute value

contenteditable="" //表示元素是可编辑的
contenteditable="events"
contenteditable="caret"
//让div只能键入文本值
//兼容性不好,除了谷歌,火狐ie都不支持
contenteditable="plaintext-only"
contenteditable="true"//表示元素是可编辑的
contenteditable="false" //表示元素是不可编辑的

As for contenteditable="events" and contenteditable="caret", I haven't found out what they mean, but we won't dig into it here since it won't be used below.

Two-way binding

We all know that div cannot use v-model, so how to achieve two-way binding?

//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: "",
            },
        })

But sometimes I just want to copy the text, but I find that the copied text is label + label style. So how to deal with the change? At this time , contenteditable="plaintext-only"
will be used , but there are many problems in actual use, such as cursor problems. We can rely on components to deal with these problems.

<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\">"
        }
    }
});

Guess you like

Origin blog.csdn.net/Yannnnnm/article/details/112250985