https://medium.com/@FezVrasta/popper-js-v1-5e8b3acd888c

https://survivejs.com/blog/popper-interview/

本文译自popper.js作者的一篇博客

在过去,我为了在web app中更好地定位我的tooltips和popover,我会花几个小时写同样的一段代码,不断进行微调。每次我开始一个新的项目,总会根据不同的环境对定位有不同的需求。这种繁琐直到我用emberjs开发一个大型应用时达到极致,这个项目中由于比较烂的UX设计决定,几乎她想在每个元素上都支持hover出现一个popover!

在这个大项目中,我们开始使用bootstrap3的tooltip,并不断地通过hack代码来实现新的功能。

在这个大项目中,一个重要的需求是:不允许将tooltip元素移动到body元素的直接儿子,因为如果这样的话,我们的代码就会broken.

几乎经过一年的项目开发并且维护我们的定制化实现,我决定使用Tetcher,因为他貌似非常强大和稳定。。不幸的是,玩了几个小时后,发现他有一个重要的缺陷或者说限制:他会自动地修改dom节点,将popper移动到body的儿子位置。他会增加一些classes并且增加一些inline style,而这你几乎无法控制!

于是我又到github上花了很多时间去查找有没有备选的方案,但是我最终一无所获。难道是没有人需要一个类似的library?或者还没有人能够比较好的抽象出来并实现一个可以单独发布的lib?

我决定花一个周末的事件重写我们自己项目中使用的定位engine,这就是popper.js的又来。

在v0.x时代,popper仅仅是一个js文件,谢了几个函数,聚焦在保持lib小巧轻量级。我希望popperjs能够有很好的扩展性,所以我决定使用middleware system.主要的想法是:计算元素的位置并且允许middleware来根据特定的需求来修改这个位置。

比如:一旦我们有了popper的position,并给了一些边界约束,那么modifier就可以检查popper是否会overflow并且自动反转位置以确保popper不会被视窗cut off.

在工作了一段时间 后,我发现我们需要更好的代码结构以便更好地能够维护使用他,这就是v1.0版本发布的初衷。

为了管理好代码,我决定切换到es6模块上来。我引入了rollup作为code bundler并使用babel作为transpiler,我也将自动化测试引擎从一个无头的chrome setup切换到saucelabs cross-browser test suite上来。

在开发过程中,我决定各个功能模块一级modifier/middleware都放到他们自己的文件中,这样能在Libray中重用。

update流程:

我也重构了整个update流程,也就是每次popper需要更新元素的位置时需要调用的代码。

这个update process会在每一frame都被调用,也就是说大概60fps,这样能够保证位置修改的流畅连贯。为了实现这个连贯流畅的目标,整个update process的代码必须简练,并且尽可能地避免直接访问dom.下面是其工作流程

React, Vuejs等第三方view library的集成

我必须考虑为了支持react或者vuejs需要做些什么,由于这些view library都会直接做dom操作,那么popperjs应该做什么设计的思考呢?v1.0将所有的dom操作都集中到一个modifier中,applyStyle

这将允许使用vuejs,react的用户简单地disable掉applyStyle并且替换为vuejs,或者react兼容的函数。

Popper.js是如何工作的?

popper.js使用一个reference element(通常是一个button或者一个link)和一个popper element(任何你需要position的元素),popper.js找到这两个元素的common offset parent,计算reference element相对于这个parent的位置,然后产生出一个坐标集用于设置popper元素的position.就这么简单。

最困难的地方在于必须考虑到一些边界条件,比如跨浏览器的兼容性,box model的能力,必须考虑scrollable element等。简单的用法:

new Popper(referenceElement, popperElement)

这段代码将会把popperElement放置到referenceElement的下发。而且,通过这段代码,你就可以访问所有的内置功能。

1. 如果referenceElement非常靠近了viewport的底部,那么popperElement将会被定位放置到referenceElement的上面,否则会出现popper部分不可见的问题;

2. 如果这两个元素位于两个不同的parents,那么popper.js也将会对这种情况考虑周全,也能很好的定位放置popper元素。

3. 它能够有效地处理scrollable elements和页面的resize场景.

Popper.js和其他类似的解决方案有什么不同呢?

主要的不同点在于该库不需要直接操作dom。这有两个好处:1.他不需要将popper节点移动到另外的context中,比如body的儿子,2.这样很容易将popper.js集成到react,angular,vuejs等view library中。你可以像下面的代码一样轻松地将dom manipulation delegate给vuejs:

new Popper(referenceElement, popperElement, {
modifiers: {
applyStyle: { enabled: false },
updateReactData: {
order: 900,
fn(data) {
this.setState({ data }); return data;
}
},
},
});

上面的代码中,我们关闭了内置的applyStyle modifier,并且定义了我们客制化的modifier,该函数代理获取计算出来的popper坐标而将坐标输出到react组件中。

既然你具有了关于popper.js的所有knowledge,那么你就可以对popper element施加任何你想要的样式。

你可能注意到我的定制modifier返回data对象。这个对象是必须的,因为其他的modifier可能会在这个custom modifier之后执行,它们也需要使用这个data对象。这种链条方式的调用使得popper.js非常易于扩展。你可以注入任何定制化的函数在存续modifer之前或者之后运行,或者关闭部分modifer,或者修正其他的modifer的行为,而这只需要通过修改这个data对象数据就可以了。

popup定位引擎popper.js介绍的更多相关文章

  1. 模板引擎doT.js介绍及如何判断对象为空、如何嵌套循环···

    doT.js 灵感来源于搜寻基于 V8 和 Node.js ,强调性能,最快速最简洁的 JavaScript 模板函数 引入 javascript 文件: <script type=" ...

  2. JavaScript模板引擎Template.js使用详解

    这篇文章主要为大家详细介绍了JavaScript模板引擎Template.js使用方法,具有一定的参考价值,感兴趣的小伙伴们可以参考一下   template.js 一款 JavaScript 模板引 ...

  3. Fixflow引擎解析(一)(介绍) - Fixflow开源流程引擎介绍

    Fixflow引擎解析(四)(模型) - 通过EMF扩展BPMN2.0元素 Fixflow引擎解析(三)(模型) - 创建EMF模型来读写XML文件 Fixflow引擎解析(二)(模型) - BPMN ...

  4. 利用开源HTML5引擎lufylegend.js结合javascript实现的五子棋人机对弈

    前言     本文主要介绍利用开源引擎 lufylegend.js开发基于Html5的游戏--五子棋,主要叙述其详细开发过程. 游戏规则 玩过五子棋的都应该知道五子棋的规则,这里就简单介绍其规则. 1 ...

  5. 模板引擎mustache.js

    Javascript模板引擎mustache.js详解   阅读目录 1. 从一个简单真实的需求讲起 2. mustache的用法 3. mustache的思想 4. {{prop}}标签 5. {{ ...

  6. node.js介绍和npm的使用

    Node.js介绍 打开Nodejs英文网:https://nodejs.org/en/ 中文网:http://nodejs.cn/ 我们会发现这样一句话: 翻译成中文如下: Node.js 是一个基 ...

  7. Node.js 介绍及安装

    Node.js是一个Javascript运行环境(runtime environment),发布于2009年5月,由Ryan Dahl开发,实质是对Chrome V8引擎进行了封装.本文详细介绍了No ...

  8. HTML5游戏开发引擎Pixi.js新手入门讲解

    在线演示 本地下载 ​这篇文章中,介绍HTML5游戏引擎pixi.js的基本使用. 相关代码如下: Javascript 导入类库:(使用极客的cdn服务:http://cdn.gbtags.com) ...

  9. 1. vue.js介绍

    1. 什么是vue.js Vue.js 是目前最火的一个前端框架,React是最流行的一个前端框架(React除了开发网站,还可以开发手机App, Vue语法也是可以用于进行手机App开发的,需要借助 ...

随机推荐

  1. PHP中 LFI Local File Include,本地文件包 漏洞

    在allow_url_include=On就是远程文件包含了,假设这里为off,那就只能本地包含了. 1.       包含上传文件 只要目标服务器支持上传,不管是jpg,txt,gif等都可以,在其 ...

  2. javascript字符串拼接

    var c='../Project/SelectPerson.aspx?personList='+'"'+personListValue+'"' X('Window2').x_sh ...

  3. C/C++ -- Gui编程 -- Qt库的使用 -- Qt窗体的类型状态布局

    -----工程WindowTest----- 1.-----窗体类型type.cpp----- #include <QtGui> int main(int argc, char * arg ...

  4. 9-lvs-lvs集群-及keepalived健康检查

    注意: 配置前需要将上一篇的配置都清除掉 ifconfig eth1: down service ipvsadm restart nginx作为请求分发服务器时, 有健康检查机制, 挂了的服务器不会在 ...

  5. 面试题22:有序数组生成不同结构BST

    对于一个含有n个数的有序数组1~N,能够产生多少种不同结果的二叉搜素树BST? 如何生成这些不同结构的BST? 有序数组如何生成平衡二叉搜索树? class Solution { public: in ...

  6. [HAOI 2015]树上染色

    Description 题库链接 给出一棵 \(n\) 个节点的树,边有权值.让你将树上 \(k\) 个点染黑,剩余 \(n-k\) 个点染白.染色后记一种染色方案的价值为黑点间两两距离和以及白点间两 ...

  7. 求两个Linux文本文件的交集、差集、并集

    一.交集 sort a.txt b.txt | uniq -d 二.并集 sort a.txt b.txt | uniq 三.差集 a.txt-b.txt: sort a.txt b.txt b.tx ...

  8. awk去重以某列重复的行

    [root@localhost cc]# cat 2.txt adc 3 5 a d aa 3 adfa d ba 3 adf 去重第一列重复的行: [root@localhost cc]# cat ...

  9. .net mvc Razor 三元运算判断赋值 ?:

    预期效果: 当Model中的Age数字列值为0时,不显示该值. <input type="text" class="form-control onlyPositiv ...

  10. 以中间件,路由,跨进程事件的姿势使用WebSocket

    通过参考koa中间件,socket.io远程事件调用,以一种新的姿势来使用WebSocket. 浏览器端 浏览器端使用WebSocket很简单 // Create WebSocket connecti ...