better-scroll 源码分析(一):概览

1,598 阅读2分钟

初衷

黄奕大佬的开源项目 better-scroll 写挺好的,不过用起来总是感觉不太方便。为了知道原因,有必要去深究一下。 由于篇幅原因,本篇将只对源码做一个简单的概览,具体实现将在后面进行分析。

better-scroll版本为 2.0.5.

整体架构

cd packages && tree -L 1

├── better-scroll
├── core
├── infinity
├── mouse-wheel
├── movable
├── nested-scroll
├── observe-dom
├── pull-down
├── pull-up
├── scroll-bar
├── shared-utils
├── slide
├── vuepress-docs
├── wheel
└── zoom

采用了可插拔式架构,core是插座,infinity/mouse-wheel等是插件。

better-scroll

先来看 better-scroll 文件夹下的实现。

import BScroll from '@better-scroll/core'
import MouseWheel from '@better-scroll/mouse-wheel'
// ...

export {
  createBScroll,
  BScrollInstance,
  Options,
  CustomOptions,
  TranslaterPoint,
  MountedBScrollHTMLElement,
  Behavior,
  Boundary,
  CustomAPI
} from '@better-scroll/core'

export {
  MouseWheel,
  // ...
}

BScroll.use(MouseWheel)
// ...

export default BScroll

整体上是起着一个统一导出的作用,注意 BScroll.use() 的使用,说明该包具备完整的插件能力,当然整体体积也偏大,如果不需要插件能力或者只需要使用到部分插件,那么不推荐使用该包。

core

这是 better-scroll 的核心代码,承载了 better-scroll 的核心滚动能力。

core源码结构

cd packages/core && tree -L 3 -I '__mocks__|__tests__'

src
├── BScroll.ts
├── Instance.ts
├── Options.ts
├── animater
│   ├── Animation.ts
│   ├── Base.ts
│   ├── Transition.ts
│   └── index.ts
├── base
│   └── ActionsHandler.ts
├── index.ts
├── scroller
│   ├── Actions.ts
│   ├── Behavior.ts
│   ├── DirectionLock.ts
│   ├── Scroller.ts
│   └── createOptions.ts
├── translater
│   └── index.ts
└── utils
    ├── bubbling.ts
    ├── compare.ts
    └── typesHelper.ts

core源码入口

// index.ts

import { BScroll } from './BScroll'

export { BScrollInstance } from './Instance'
export { Options, CustomOptions } from './Options'
export { TranslaterPoint } from './translater'
export { MountedBScrollHTMLElement } from './BScroll'
export { Behavior, Boundary } from './scroller/Behavior'
export { createBScroll, CustomAPI } from './BScroll'

export default BScroll

可以看到核心代码位于BScroll.ts,该文件主要作用便是导出BScrollConstructor

// BScroll.ts
export class BScrollConstructor<O = {}> extends EventEmitter {
  static plugins: PluginItem[] = []
  static pluginsMap: PluginsMap = {}
  scroller: Scroller
  options: OptionsConstructor
  hooks: EventEmitter
  plugins: { [name: string]: any }
  wrapper: HTMLElement
  content: HTMLElement
  [key: string]: any

  static use(ctor: PluginCtor) {}
  constructor(el: ElementParam, options?: Options & O) {}
  init() {}
  refresh() {}
  enable() {}
  disable() {}
  destroy() {}
  eventRegister() {}
  // ...
}

值得注意的是 BScrollConstructor 继承了 EventEmitter,它位于 shared-utils文件夹下,是作者自行实现的一个事件类,用于事件注册和监听,后面将进行讲解。

插件

根据 core 中的源码来看,一个 better-scroll 插件必须包含一个静态属性 pluginName,用于作为插件的唯一标识。当然这篇文章不会重点去研究插件的实现,感兴趣的小伙伴可以自己研究。

export default class MouseWheel {
  static pluginName = 'mouseWheel'
}

shared-utils

这是公用的一些工具,后面会结合源码一起享用。

小结

那我们现在应该清楚了better-scroll基本架构,core作为滚动的核心部分,扮演着重要的角色,接下来的文章将会终点分析改目录下的源码~