vue2 实现 div contenteditable="true" 类似于 v-model 的效果_weixin_34088598的博客-程序员宅基地

技术标签: ViewUI  javascript  

问题

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 传送门 使用自定义事件的表单输入组件,那一章节。

问题解决。

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

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

<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)的子元素,父元素的大小即为子元素的大小。
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/weixin_34088598/article/details/89080302

智能推荐

设置Vlan配置Hybrid端口_weixin_33774615的博客-程序员宅基地

配置Hybrid端口 使用eNSO搭建实验环境,见下图! &lt;sw1&gt;用户模式下输入system view进入特权模式[sw1]vlan batch 5 10 50 批量设置交换机的Vlan分别为5 10 50[sw1]interface Ethernet0/0/1 进入接口视图[sw1-Ethernet0/0/1]port ...

Flask部署机器学习模型---基于线性回归模型的销售预测系统实现简易版代码_就是求关注的博客-程序员宅基地

目录摘要线性回归线性回归理论推导FLASK特性项目结构代码依赖库GUI界面实现代码序列化/反序列化GUI显示界面运行总结摘要本此演示了一种非常简单的方法来部署机器学习模型。利用线性回归使用前两个月的利率和销售额来预测第三个月的销售值。大家在进行算法研究与实现之后,可以此方法来将自己研究的模型赋予应用实现,以便他人更方便的了解你的研究性工作。...

PX、DP和SP之间的换算_四级五次郎的博客-程序员宅基地_dp和sp换算

在Android开发中,尺寸换算可以说既简单又复杂,而且还比较碎,特别是屏幕适配的时候肯定会用到他们。今天就来总结一下他们三者的关系,首先说下他们都是什么。px:像素单位。最基础的图像构成元素单位 dp:与密度无关的像素,这是一个基于屏幕物理密度的抽象单位。 这里要解释一下密度的概念,密度(dpi):每英寸包含的像素个数(单位是dpi),1dp实际上相当于密度为160dpi的屏上的一个点。可否理

[记录]EggJs初始化项目_Lytis的博客-程序员宅基地_初始化egg项目

egg框架的初始化、搭建,使用sequelize框架连接数据库,并使用简单的例子来介绍基础的业务流程。

《Squeeze-and-Excitation Networks(SENet)》_jiyeyong的博客-程序员宅基地

解读Squeeze-and-Excitation Networks(SENet)动机卷积神经网络已被证明是解决各种视觉任务的有效模型。对于每个卷积层,沿着输入通道学习一组滤波器来表达局部空间连接模式。换句话说,期望卷积滤波器通过融合空间信息和信道信息进行信息组合,而受限于局部感受野。通过叠加一系列非线性和下采样交织的卷积层,CNN能够捕获具有全局感受野的分层模式作为强大的图像描述。最...

无线通讯 - 5G芯片和5G模组区别_何以解忧唯有写!的博客-程序员宅基地

5G模组:基带芯片,射频芯片,存储芯片,电阻电容组成。5G芯片,即基带芯片。5G模组和其他通信模组类似,都是将基带芯片、射频芯片、存储芯片、电容电阻等各类元器件集成到一块电路板上,提供标准接口,各类物联网终端通过嵌入物联网通信模块快速实现通信功能。参考:https://baijiahao.baidu.com/s?id=1664217508217073604&amp;wfr=spider&amp;for=pc...

随便推点

物化视图的快速刷新_cuibarong6878的博客-程序员宅基地

原文出处http://yangtingkun.itpub.net/post/468/14245物化视图有三种刷新方式:COMPLETE、FAST和FORCE。完全刷新(COMPLETE)会删除表中所有的记录(如果是单表刷新,可能...

【Android应用开发】-(18)静默方式实现批量安装卸载应用程序_EvoShark的博客-程序员宅基地

前段时间做了一个批量安装卸载应用程序的小应用,由于安装卸载应用程序的部分API是隐藏的,所以必须在ubuntu下下载Android系统源码,并编译之后使用MM命令编译生成APK文件,其实也难。思路是这样的,在XX/packages/apps目录下有一个PackageInstaller的应用程序,Android机器中安装卸载都是由这个应用程序完成的。但是它没有批量安装和卸载的功能,如果要在自己的应用

Apache服务器默认配置的一些基本信息_Tony0520.的博客-程序员宅基地

配置文件:/etc/httpd/conf/http.conf1)"/etc/httpd/conf主要存放了配置文件httpd.conf,这个是最重要的配置文件,Apache的所有主要权限和功能都在这个文件中进行了详细的设置。 (2) "/etc/httpd/conf.d" 里面存放的是一些额外的参数档,比如php.conf,或者一些自己设定的额外参数等信息。这个目录最大的好处就

git常用命令总结_weixin_30823833的博客-程序员宅基地

一、 Git 常用命令速查git branch 查看本地所有分支git status 查看当前状态git commit 提交git branch -a 查看所有的分支git branch -r 查看远程所有分支git commit -am "init" 提交并且加注释git remote add origin [email protected]:ndshowgit push ori...

centos下安装MySQL-python_feifeilyj的博客-程序员宅基地

1) 下载MySQL-pythonwget https://pypi.python.org/packages/a5/e9/51b544da85a36a68debe7a7091f068d802fc515a3a202652828c73453cad/MySQL-python-1.2.5.zip#md5=654f75b302db6ed8dc5a898c625e030c2) 解压缩unz

JavaScript的组成部分之操作对象与表单_I'm sure ok!的博客-程序员宅基地

文章目录1.JavaScript的组成部分2.操作BOM对象1).Window2).Navigato(导航)3).screen4).location5).document6).history3.操作DOM对象1).获得dom节点1.JavaScript的组成部分javascript组成一个完整的 JavaScript 实现是由以下 3 个不同部分组成的:核心(ECMAScript)、文档对象模...

推荐文章

热门文章

相关标签