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. 我与GitHub的第一次——自制音乐文件修改器

    背景: 随机播放,所有的音乐播放器里面现在几乎都有这个功能吧.但是有没有发现,自己的播放器在选择随机播放的时候,经常会听到重复顺序的歌曲呢?反正我是有这样的感觉,无耐自己平时下的歌曲都是“歌手名—歌曲 ...

  2. 自定义针对Product Key处理的TextBox

    代码: using System; using System.Collections.Generic; using System.Linq; using System.Text; using Syst ...

  3. 微信公众号H5支付

    微信支付说明1.统一下单接口 统一支付接口: url: https://api.mch.weixin.qq.com/pay/unifiedorder 目的:通过此接口来创建预支付订单,获取订单支付需要 ...

  4. 设计模式学习--面向对象的5条设计原则之依赖倒置原则--DIP

    一.DIP简介(DIP--Dependency Inversion Principle): 1.高层模块不应该依赖于低层模块,二者都应该依赖于抽象.2.抽象不应该依赖于细节,细节应该依赖于抽象.   ...

  5. iOS 关于Xcode上的Other linker flags

    Targets选项下有Other linker flags的设置,用来填写XCode的链接器参数,如:-ObjC -all_load -force_load等.还记得我们在学习C程序的时候,从C代码到 ...

  6. 【转】SpringBoot系列之—瘦身部署

    一.前言 SpringBoot部署起来虽然简单,如果服务器部署在公司内网,速度还行,但是如果部署在公网(阿里云等云服务器上),部署起来实在头疼: 编译出来的 Jar 包很大,如果工程引入了许多开源组件 ...

  7. 【原】使用Builder模式替代构造参数传参

    前言:关于传递参数,当参数过多的时候我们可以考虑使用建造者模式. #没用 Builder模式 之前是这样传参的: 如下所示,构造方法里面的参数一大堆,看起来就非常的混乱. 用了Builder模式之后是 ...

  8. mysql网页客户端工具

    mysql数据库的远程管理,云服务器数据库的管理监控等都可以使用 TreeSoft,  TreeSoft数据库管理系统使用JAVA开发,采用稳定通用的springMVC +JDBC架构,实现基于WEB ...

  9. POJ2251(KB1-B 三维BFS)

    Dungeon Master Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 40872 Accepted: 19936 Desc ...

  10. ID3决策树算法实现(Python版)

    # -*- coding:utf-8 -*- from numpy import * import numpy as np import pandas as pd from math import l ...