vue2 实现 div contenteditable=true 类似于 v-model双向数据绑定的效果

更新日期: 2018-04-20阅读: 4.5k标签: 双向绑定

问题

在 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),并将数据返回给父组件。
代码如下:

<template>
    <div contenteditable="true"
         v-html="innerText"
         @input="changeText"></div>
</template>
<script>
    export default {
        props: ['value'],
        data(){
            return {innerText:this.value}
        },
        methods:{
            changeText(){
                this.innerText = this.$el.innerHTML;
                this.$emit('input',this.innerText);
            }
        }
    }
</script>

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

<template>
    <div>
        <v-edit-div v-model='text'></v-edit-div>
        <span>{{text}}</span>
    </div>
</template>
<script>
    export default {
        data(){
            return {
                text:'改一下试一试',
            }
        }
    }
</script>

至于为什么可以直接用 v-model ,看官网的 api 吧。v-model 传送门 使用自定义事件的表单输入组件,那一章节。


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

<template>
    <div class="edit-div"
         v-html="innerText"
         :contenteditable="canEdit"
         @focus="isLocked = true"
         @blur="isLocked = false"
         @input="changeText">
    </div>
</template>
<script type="text/ecmascript-6">
    export default{
        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>
<style lang="scss" rel="stylesheet/scss">
    .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>

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

  1. canEdit 标志这个div是否是可编辑的,在父组件直接使用 v-model 即可。
  2. 该组件应该是一个div元素(也不一定非要是div)的子元素,父元素的大小即为子元素的大小。


转载来源:https://segmentfault.com/a/1190000008261449


链接: https://www.fly63.com/article/detial/683

原生js实现数据双向绑定的三种方式总汇

前端的视图层和数据层有时需要实现双向绑定(two-way-binding),例如mvvm框架,数据驱动视图,视图状态机等,研究了几个目前主流的数据双向绑定框架,总结了下。目前实现数据双向绑定主要有以下三种。

Vue双向绑定的实现原理

vue.js 采用数据劫持的方式,结合发布者-订阅者模式,通过Object.defineProperty()来劫持各个属性的setter,getter以监听属性的变动,在数据变动时发布消息给订阅者,触发相应的监听回调.

vue双向数据绑定失效_解决vue添加新属性实现双向绑定

vue框架目前在前端开发使用比较广了,但是又很多同学发现vue创建对象之后添加新的属性实现不了双向绑定,下面就简单介绍如何解决vue双向绑定出现失效的问题

自定义 Vue 中的 v-model 双向绑定

v-model 双向绑定实际上就是通过子组件中的 $emit 方法派发 input 事件,父组件监听 input 事件中传递的 value 值,并存储在父组件 data 中;然后父组件再通过 prop 的形式传递给子组件 value 值,再子组件中绑定 input 的 value 属性即可。

vue双向绑定原理分析

当我们学习angular或者vue的时候,其双向绑定为我们开发带来了诸多便捷,今天我们就来分析一下vue双向绑定的原理。vue.js 则是采用数据劫持结合发布者-订阅者模式的方式,通过Object.defineProperty()来劫持各个属性的setter,getter

简单实现一个vue的双向绑定

首先我们来看一些,vue的基本使用方法;然后我们根据使用方法,来设计一个类和一些基础的声明周期;获取根元素;生命周期 beforeCreate;获取初始数据;获取渲染函数

React input表单双向数据绑定仿Vue v-model实现

用过Vue的同学都知道,Vue里<input> 、 <textarea> 及 <select>等表单元素可以通过v-model指令实现双向数据绑定,也就是说,当用户通过交互改变表单的值时,表单绑定的数据也会同步响应,这一点也是Vue对开发人员非常友好的点之一。

js 超浓缩 双向绑定

绑定确实是个有趣的话题。现在我的绑定器有了不少的功能1. 附着在Object对象上,一切以对象为中心2. 与页面元素进行双向绑定

Vue - 自定义组件双向绑定

无论在任何的语言或框架中,我们都提倡代码的复用性。对于Vue来说也是如此,相同的代码逻辑会被封装成组件,除了复用之外,更重要的是统一管理提高开发效率。我真就接手过一个项目,多个页面都会用到的列表

VUE:computed 和 v-model 配合使用,双向绑定失效

今天在实现一个表单赋值并修改的功能时,由于其中数值直观显示不美观,所以使用了 computed 计算属性,同时使用 v-model 的双向绑定,来处理显示。但却发现 v-model 的双向绑定失效了,控制台警告信息如下:

点击更多...

内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权或违规,请与小编联系!情况属实本人将予以删除!