美文网首页
vue2 实现 div contenteditable="tru

vue2 实现 div contenteditable="tru

作者: 九千_ | 来源:发表于2019-04-09 08:17 被阅读0次

问题

点击跳转到原文

在vue2中对表单控件有着良好的双向数据绑定机制,但是对于要特定实现某些功能的输入时,我们就不得不使用到contenteditable="true"的div,而在这个div上是使用v-model是没有效果的。那么问题就来了,输入是非常需要双向绑定的,这里的双向数据绑定该如何实现?

解决思路一:自定义指令

当然,说在这一段的前面,这种解决方式在vue2中是不行的,为什么这么说,因为现在去搜索这个问题绝大多数的搜索结果是这个,所以放在前面。

实现的原理以及为什么不能用了

原理:自定义一个双向数据绑定的指令,代码如下:

Vue.directive('demo', {

twoWay:true,

bind:function(){

this.handler =function(){

this.set(this.el.innerHTML)

}.bind(this)

this.el.addEventListener('input',this.handler)

    },

update:function(newValue, oldValue){

this.el.innerHTML = newValue ||''

    },

unbind:function(){

this.el.removeEventListener('input',this.handler)

    }

})

至于this下的这些方法,在vue官网上可能不太容易找到,因为这些是vue1中的内容,而在vue2中已经被移除了。所以在vue2中我们是不能这么干的,当然如果你使用的是vue1那么完全没问题,直接拿去用即可。

解决思路二:使用组件

单独声明一个组件,在组件内部处理数据(也就是innerHTML),并将数据返回给父组件。

代码如下:

v-html="innerText"

@input="changeText">

exportdefault{

props: ['value'],

        data(){

return{innerText:this.value}

        },

methods:{

            changeText(){

this.innerText =this.$el.innerHTML;

this.$emit('input',this.innerText);

            }

        }

    }

然后在父组件中直接使用v-model就可以了(这里我把组件名称定义成了 v-edit-div)。

{{text}}

exportdefault{

        data(){

return{

text:'改一下试一试',

            }

        }

    }

至于为什么可以直接用v-model,看官网的 API 吧。

v-model 传送门使用自定义事件的表单输入组件,那一章节。

问题解决。

=============== 分割线:更新于17-08-25 =====================

忙的不行,之前在评论区也有发现这个例子其实会有不少的问题,包括如何实现异步数据的刷新,更新值之后光标定位的问题等等,在考虑了异步数据和光标问题后,有了以下的这个版本

<template>

v-html="innerText"

:contenteditable="canEdit"

@focus="isLocked = true"

@blur="isLocked = false"

@input="changeText">

    </div>

</template>

exportdefault{

name:'editDiv',

        props: {

            value: {

                type: String,

default:''

            },

            canEdit: {

type:Boolean,

default:true

            }

        },

data(){

return{

innerText:this.value,

isLocked:false

            }

        },

        watch: {

'value'(){

if(!this.isLocked || !this.innerText) {

this.innerText =this.value;

                }

            }

        },

        methods: {

            changeText(){

this.$emit('input',this.$el.innerHTML);

            }

        }

    }

</script>

    .edit-div {

width:100%;

height:100%;

        overflow: auto;

word-break:break-all;

        outline: none;

        user-select: text;

        white-space: pre-wrap;

        text-align: left;

&[contenteditable=true]{

            user-modify: read-write-plaintext-only;

            &:empty:before {

                content: attr(placeholder);

                display: block;

                color: #ccc;

            }

        }

    }

</style>

这个版本是在项目中最终使用的版本,需要用的直接拿走用即可。

注:

canEdit标志这个div是否是可编辑的,在父组件直接使用v-model即可。

该组件应该是一个div元素(也不一定非要是div)的子元素,父元素的大小即为子元素的大

相关文章

网友评论

      本文标题:vue2 实现 div contenteditable="tru

      本文链接:https://www.haomeiwen.com/subject/bejviqtx.html