摘要:傳統(tǒng)的事件監(jiān)聽方式通常使用對元素添加事件監(jiān)聽,比如很自然的,用戶在使用組件時也會想到這種用法,試圖直接在上添加監(jiān)聽,結(jié)果出現(xiàn)問題,正確的寫法應(yīng)該是這樣組件的交互事件設(shè)計思路這樣設(shè)計的目的,是保持模型與視圖的分離,在組件中對象是,,則是,原則
傳統(tǒng)的HTML事件監(jiān)聽方式
通常使用on***對HTML元素添加事件監(jiān)聽,比如
button.onclick = function(evt){ console.log(evt); }
很自然的,用戶在使用Qunee組件時也會想到這種用法,試圖直接在Node上添加onclick監(jiān)聽,結(jié)果出現(xiàn)問題,正確的寫法應(yīng)該是這樣
graph.onclick = function(evt){ var element = evt.getData(); Q.log(element); }組件的交互事件設(shè)計思路
這樣設(shè)計的目的,是保持模型與視圖的分離,在Qunee組件中Graph對象是View,Node,Edge則是Model,原則上Model部分應(yīng)該保持純粹的數(shù)據(jù),不知道View的存在,同一個Model可能綁定多個View,如果直接在Model層添加監(jiān)聽,該對哪個View起作用呢?交互依賴于View,所以交互應(yīng)該在View層面上處理
MVP設(shè)計模式自然引申到一個更高級的話題——設(shè)計模式,不在Node上提供onclick監(jiān)聽的根本原因是設(shè)計模式,從下面的示意圖可以看出,交互是View層面的東西
組件交互設(shè)計實踐 原生HTML事件現(xiàn)存的問題原生的HTML事件存在些問題,比如單擊與雙擊不區(qū)分,沒有拖拽事件,手持設(shè)備上,Touch事件與傳統(tǒng)的桌面事件不統(tǒng)一,以拖拽交互為例,桌面版需要監(jiān)聽mousedown, mousemove, mouseup,手機(jī)版則需要監(jiān)聽touchdown, touchmove, touchend, touchcancel等,且MouseEvent與TouchEvent屬性也很不一樣,造成麻煩。此外手持設(shè)備上提供的事件太原始,沒有雙擊事件,手勢支持非常有限,幾乎所有的Web APP應(yīng)用都會對事件做些處理,也有第三方實現(xiàn)的,如:hammer.js
設(shè)計新的事件類型為了解決不統(tǒng)一的問題,Qunee組件時對事件類型做了封裝,定義了一套統(tǒng)一的事件類型
以拖拽為例,事件派發(fā)順序為:onstart -> startdrag -> ondrag -> enddrag -> onrelease,桌面鼠標(biāo)操作也會派發(fā)同樣的事件,start, release這樣的命名不是首創(chuàng),參照了hammer.js的命名
事件屬性新的事件類型,帶來新的屬性,比如drag操作時,可以直接從事件對象中獲取拖拽偏移量,拖拽速度等,雙指捏合分開時,可以獲取中心點以及縮放變化量
使用示例介紹一個彈出菜單的例子,桌面環(huán)境通常使用右鍵菜單,但手持設(shè)備中并沒有右鍵,所以統(tǒng)一改用長按彈出的方式,下面的例子就是通過監(jiān)聽長按事件(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"; }運(yùn)行效果
運(yùn)行效果可參考demo.qunee.com
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/49497.html
摘要:往往定義組件的構(gòu)造器后,不需要手動的進(jìn)行初始化,而是在其他組件的模板中當(dāng)成標(biāo)簽來使用,這時候需要調(diào)用注冊成組件。這樣設(shè)計的目的是防止從子組件意外改變父級組件的狀態(tài),從而導(dǎo)致應(yīng)用的數(shù)據(jù)流向難以理解。 上節(jié)說到組件https://segmentfault.com/a/1190000009236700,這一節(jié)繼續(xù)來學(xué)習(xí)組件: 原文博客地址,歡迎學(xué)習(xí)交流:點擊預(yù)覽從github上獲取本文代碼:...
摘要:組件設(shè)計的目標(biāo)是解決用戶上傳文件的便利性,但是中后臺組件的場景是多種多樣的,所以可擴(kuò)展能力是組件不可忽視的另一方面。我們可能的期望是在任何瀏覽器下交互和都一致的組件。由此我們做出了兩個通用的組件文件選擇器。 Upload 組件設(shè)計的目標(biāo)是解決用戶上傳文件的便利性,但是中后臺 Upload 組件的場景是多種多樣的,所以可擴(kuò)展能力是 Upload 組件不可忽視的另一方面。 同樣為了大家能夠...
閱讀 2901·2021-11-24 09:39
閱讀 2470·2019-08-30 15:53
閱讀 3038·2019-08-30 13:47
閱讀 1327·2019-08-30 12:50
閱讀 1491·2019-08-29 16:31
閱讀 2653·2019-08-29 13:14
閱讀 1571·2019-08-29 10:55
閱讀 804·2019-08-26 13:32