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. Form表单如何可以传递多个值传递List数组对象到后台的解决办法

    举例说明: 后台有一个对象 User ,结构如下: 后台有一个对象 User ,结构如下: public class User{ private String username; private Li ...

  2. Android 开发工具类 06_NetUtils

    跟网络相关的工具类: 1.判断网络是否连接: 2.判断是否是 wifi 连接: 3.打开网络设置界面: import android.app.Activity; import android.cont ...

  3. Jar包的格式

    jar包目录格式: |-- com | |-- test.class |-- META-INF | |-- MAINFEST.MF 一个正常的jar包下必有META-INF/MANIFEST.MF清单 ...

  4. #define a int[10]与 typedef int a[10]用法

    // #define a int[10] #include <stdio.h> #include <stdlib.h> #define a int[10] int main() ...

  5. 解决ssh登陆超时方案

    ssh登陆一般默认3分钟无操作则断开连接,有时候还是很烦的,于是解决这个问题. sudo修改/etc/ssh/sshd_conf文件 #sudo vim /etc/ssh/sshd_config #在 ...

  6. Java虚拟机(一):JVM简介

    JVM简介 Java虚拟机(JVM)是由Java虚拟机规范定义的,其上运行的是字节码指令集.这种字节码指令集包含一个字节的操作码(opcode),零至多个操作数(oprand),虚拟机规范明确定义了每 ...

  7. Redis持久化配置-AOF

    redis的持久化有rdb和aof两种. rdb是记录一段时间内的操作,一般的配置是一段时间内操作超过多少次就持久化.aof可以实现每次操作都持久化. 这里我们使用aof. 配置方式,打开redis的 ...

  8. SPP(Spatial Pyramid Pooling)详解

    一直对Fast RCNN中ROI Pooling层不解,不同大小的窗口输入怎么样才能得到同样大小的窗口输出呢,今天看到一篇博文讲得挺好的,摘录一下,方便查找. Introduction 在一般的CNN ...

  9. javascript快速入门1--JavaScript前世今生,HelloWorld与开发环境

    JavaScript历史 大概在1992年,一家称作Nombas的公司开始开发一种叫做C--(C-minus-minus,简称Cmm)的嵌入式脚本语言. Cmm背后的理念很简单:一个足够强大可以替代宏 ...

  10. GreenPlum:基于PostgreSQL的分布式关系型数据库

    GreenPlum是一个底层是多台PostgreSQL分表分库的分布式数据库,它有如下特点 支持标准SQL,几乎所有PostgreSQL支持的SQL,greenplum都支持 支持ACID.分布式事务 ...