资讯专栏INFORMATION COLUMN

HTML组件的交互事件设计

Faremax / 2949人阅读

摘要:传统的事件监听方式通常使用对元素添加事件监听,比如很自然的,用户在使用组件时也会想到这种用法,试图直接在上添加监听,结果出现问题,正确的写法应该是这样组件的交互事件设计思路这样设计的目的,是保持模型与视图的分离,在组件中对象是,,则是,原则

传统的HTML事件监听方式

通常使用on***对HTML元素添加事件监听,比如

button.onclick = function(evt){
  console.log(evt);
}

很自然的,用户在使用Qunee组件时也会想到这种用法,试图直接在Node上添加onclick监听,结果出现问题,正确的写法应该是这样

graph.onclick = function(evt){
  var element = evt.getData();
  Q.log(element);
}
组件的交互事件设计思路

这样设计的目的,是保持模型与视图的分离,在Qunee组件中Graph对象是View,Node,Edge则是Model,原则上Model部分应该保持纯粹的数据,不知道View的存在,同一个Model可能绑定多个View,如果直接在Model层添加监听,该对哪个View起作用呢?交互依赖于View,所以交互应该在View层面上处理

MVP设计模式

自然引申到一个更高级的话题——设计模式,不在Node上提供onclick监听的根本原因是设计模式,从下面的示意图可以看出,交互是View层面的东西

组件交互设计实践 原生HTML事件现存的问题

原生的HTML事件存在些问题,比如单击与双击不区分,没有拖拽事件,手持设备上,Touch事件与传统的桌面事件不统一,以拖拽交互为例,桌面版需要监听mousedown, mousemove, mouseup,手机版则需要监听touchdown, touchmove, touchend, touchcancel等,且MouseEvent与TouchEvent属性也很不一样,造成麻烦。此外手持设备上提供的事件太原始,没有双击事件,手势支持非常有限,几乎所有的Web APP应用都会对事件做些处理,也有第三方实现的,如:hammer.js

设计新的事件类型

为了解决不统一的问题,Qunee组件时对事件类型做了封装,定义了一套统一的事件类型

以拖拽为例,事件派发顺序为:onstart -> startdrag -> ondrag -> enddrag -> onrelease,桌面鼠标操作也会派发同样的事件,start, release这样的命名不是首创,参照了hammer.js的命名

事件属性

新的事件类型,带来新的属性,比如drag操作时,可以直接从事件对象中获取拖拽偏移量,拖拽速度等,双指捏合分开时,可以获取中心点以及缩放变化量

使用示例

介绍一个弹出菜单的例子,桌面环境通常使用右键菜单,但手持设备中并没有右键,所以统一改用长按弹出的方式,下面的例子就是通过监听长按事件(onlongpress),显示一个面板

var graph = new Q.Graph("canvas");

var hello = graph.createNode("Hello", -100, -50);
hello.image = Q.Graphs.server;
var qunee = graph.createNode("Qunee", 100, 50);
var edge = graph.createEdge("Hello
Qunee", hello, qunee);

function getPageXY(evt){
    if (evt.touches && evt.touches.length) {
        evt = evt.touches[0];
    }
    return {x: evt.pageX, y: evt.pageY};
}
var menu = document.createElement("div");
menu.style.position = "absolute";
menu.style.width = "100px";
menu.style.padding = "10px";
menu.style.backgroundColor = "#EEE";
menu.style.display = "none";
document.body.appendChild(menu);

graph.onlongpress = function (evt) {
    var data = evt.getData();
    if(!data){
        return;
    }
    var xy = getPageXY(evt);
    menu.style.left = xy.x + "px";
    menu.style.top = xy.y + "px";
    menu.innerHTML = data.name;
    menu.style.display = "block";
}
graph.onstart = function(){
    menu.style.display = "none";
}
运行效果

运行效果可参考demo.qunee.com

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/49497.html

相关文章

  • 理解vue中组件(二)

    摘要:往往定义组件的构造器后,不需要手动的进行初始化,而是在其他组件的模板中当成标签来使用,这时候需要调用注册成组件。这样设计的目的是防止从子组件意外改变父级组件的状态,从而导致应用的数据流向难以理解。 上节说到组件https://segmentfault.com/a/1190000009236700,这一节继续来学习组件: 原文博客地址,欢迎学习交流:点击预览从github上获取本文代码:...

    Nino 评论0 收藏0
  • 我是如何设计 Upload 上传组件

    摘要:组件设计的目标是解决用户上传文件的便利性,但是中后台组件的场景是多种多样的,所以可扩展能力是组件不可忽视的另一方面。我们可能的期望是在任何浏览器下交互和都一致的组件。由此我们做出了两个通用的组件文件选择器。 Upload 组件设计的目标是解决用户上传文件的便利性,但是中后台 Upload 组件的场景是多种多样的,所以可扩展能力是 Upload 组件不可忽视的另一方面。 同样为了大家能够...

    malakashi 评论0 收藏0
  • 微信小程序初探

    摘要:在微信小程序中,要更新视图就只能修改,而视图层也只能通过事件向逻辑层传递交互信息。页面移植到微信小程序要修改的地方也还比较多,主要是标签和的交互及小程序提供的功能部分。 小程序是一种不需要下载安装即可使用的应用,它实现了应用「触手可及」的梦想,用户扫一扫或搜一下即可打开应用。也体现了「用完即走」的理念,用户不用关心是否安装太多应用的问题。应用将无处不在,随时可用,但又无需安装卸载。 —...

    teren 评论0 收藏0
  • 【译】前端练级攻略

    摘要:由于系统变得越来越复杂,人们提出了称为预处理器和后处理器的工具来管理复杂性。后处理器在由预处理器手写或编译后对应用更改。我之前建议的文章,,也涵盖了预处理器相关的知识。 译者:前端小智 原文:medium.freecodecamp.org/from-zero-t… medium.freecodecamp.org/from-zero-t… 我记得我刚开始学习前端开发的时候。我看到了很多文章及...

    wuyumin 评论0 收藏0

发表评论

0条评论

Faremax

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<