面板 / 侧面板

面板布局

让我们看看如何将侧面板添加到我们的应用中。我们可以将最多2个面板添加到我们的应用中,一个在左侧,另一个在右侧。我们应该在应用根元素的开头直接添加面板的HTML(或者<body>在没有使用根元素的情况下):

<body>
  <!-- App root element -->
  <div id="app">
    <!-- Left panel -->
    <div class="panel panel-left">
        ... panel content goes here ...
    </div>

    <!-- Right panel -->
    <div class="panel panel-right">
        ... panel content goes here ...
    </div>

    ...
  </div>
</body>

添加面板后,我们需要为每个面板选择打开效果。可以是以下效果之一:

如果你想使用"Reveal"效果,你应该向Panel添加额外的panel-reveal类,panel-cover对于覆盖效果,或者panel-push对于推挤效果:

<body>
  <!-- App root element -->
  <div id="app">
    <!-- Left panel, let it be with reveal effect -->
    <div class="panel panel-left panel-reveal">
        ... panel content goes here ...
    </div>

    <!-- Right panel, with cover effect -->
    <div class="panel panel-right panel-cover">
        ... panel content goes here ...
    </div>

    ...
  </div>
</body>

每个面板都可以调整大小。要使面板可调整大小,我们只需要向Panel元素添加panel-resizable类:

<body>
  <!-- App root element -->
  <div id="app">
    <!-- Make left panel resizable -->
    <div class="panel panel-left panel-resizable">
        ... panel content goes here ...
    </div>

    <!-- Make right panel resizable -->
    <div class="panel panel-right panel-resizable">
        ... panel content goes here ...
    </div>
    ...
  </div>
</body>

面板应用方法

让我们看看与应用面板相关的应用方法:

app.panel.create(参数)- 创建面板实例

  • 参数 - 对象. 带有面板参数的对象

方法返回创建的面板实例

app.panel.destroy(el)- 销毁面板实例

  • el - HTMLElement字符串(使用 CSS 选择器) 或对象. 要销毁的面板元素或面板实例。

app.panel.get(el)- 通过HTML元素获取面板实例

  • el - HTMLElement字符串(使用CSS选择器)。面板元素。

方法返回面板实例

app.panel.open(panel, animate)- 打开面板

  • 面板 - HTMLElement字符串(使用CSS选择器)的面板元素来打开
  • animate - 布尔值. 是否应该使用动画打开。可选,默认为true

app.panel.close(panel, animate)- 关闭面板

  • 面板 - HTMLElement字符串(使用CSS选择器)的面板元素来关闭
  • animate - 布尔值. 是否应该使用动画关闭。可选,默认为true

app.panel.toggle(panel, animate)- 切换面板

  • 面板 - HTMLElement字符串(使用CSS选择器)的面板元素来切换
  • animate - 布尔值. 是否应该使用动画打开/关闭。可选,默认为true

面板参数

如果我们使用app.panel.create方法手动创建面板,我们需要传递带有面板参数的对象:

参数类型默认描述
elHTMLElement
字符串
面板元素
resizable布尔值启用可调整大小的面板。如果没有传递,则将根据panel-resizable类。
visibleBreakpoint数字最小应用宽度(以像素为单位),当左侧面板始终可见时
collapsedBreakpoint数字最小应用宽度(以像素为单位),当左侧面板部分可见(折叠)时
滑动布尔值false如果你想启用用滑动打开/关闭面板的功能,请启用此选项
swipeNoFollow布尔值false对于旧设备/慢设备可能更好的性能的回退选项。如果你启用它,那么在触摸移动时,滑动面板将不会跟随你的手指,它将在滑动左右时自动打开/关闭。
swipeActiveArea数字0触屏屏幕上触发面板滑动的不可见边缘宽度(以像素为单位)
swipeOnlyClose布尔值false此参数允许用滑动关闭(但不能打开)面板。(应该也启用)swipe应该也启用
swipeThreshold数字0如果“触摸距离”小于此值(以像素为单位),面板将不会随着滑动而移动。
背景遮罩布尔值true启用面板背景(背后的深色半透明层)
backdropElHTMLElement
字符串
自定义背景元素的HTML元素或字符串CSS选择器
closeByBackdropClick布尔值true启用/禁用通过点击面板外部关闭面板的能力
containerElHTMLElement
字符串
允许将面板挂载到自定义元素,而不是应用根元素
on对象

带有事件处理程序的对象。例如:

var panel = app.panel.create({
  el: '.panel-left',
  on: {
    opened: function () {
      console.log('Panel opened')
    }
  }
})

例如:

var panel = app.panel.create({
  el: '.panel-left',
  resizable: true,
  visibleBreakpoint: 1024,
  collapsedBreakpoint: 768,
})

注意,所有以下参数都可以在panel属性为所有面板设置默认值。例如:

var app = new Framework7({
  panel: {
    swipe: true,
    visibleBreakpoint: 1024,
  }
});

面板方法和属性

创建面板实例(通过调用app.panel.create)后,或者获取面板实例(通过调用app.panel.get)后,我们可以使用其有用的方法和属性:

属性
panel.app链接到全局应用实例
panel.side面板侧面的字符串:leftright
panel.effect面板效果的字符串:cover, reveal, floatingpush
panel.opened指示是否打开的布尔属性
panel.el面板HTML元素
panel.$el带有面板HTML元素的Dom7实例
panel.backdropEl背景层 HTML 元素
panel.$backdropEl包含背景层 HTML 元素的 Dom7 实例
panel.params面板参数
panel.containerEl挂载面板的元素。(默认app.el- 根应用元素)
panel.$containerEl带有挂载面板元素的Dom7实例。(默认app.el- 根应用元素)
方法
panel.open(animate)打开面板。其中
  • animate - 布尔值(默认true) - 定义是否应该使用动画打开
panel.close(animate)关闭面板。其中
  • animate - 布尔值(默认true) - 定义是否应该使用动画关闭
panel.toggle(animate)切换面板。其中
  • animate - 布尔值(默认true) - 定义是否应该使用动画关闭
panel.enableVisibleBreakpoint()启用可见断点
panel.disableVisibleBreakpoint()禁用可见断点
panel.toggleVisibleBreakpoint()切换可见断点
panel.enableCollapsedBreakpoint()启用折叠断点
panel.disableCollapsedBreakpoint()禁用折叠断点
panel.toggleCollapsedBreakpoint()切换折叠断点
panel.enableResizable()启用可调整大小的面板
panel.disableResizable()禁用可调整大小的面板
panel.enableSwipe()启用可滑动的面板
panel.disableSwipe()禁用可滑动的面板
panel.destroy()销毁面板实例
panel.on(事件上触发, 处理程序)添加事件处理程序
panel.once(事件上触发, 处理程序)添加在触发后将被移除的事件处理程序
panel.off(事件上触发, 处理程序)移除事件处理程序
panel.off(事件上触发)移除指定事件的所有处理程序
panel.emit(事件上触发, ...args)在实例上触发事件

面板事件

面板将在面板元素上以及应用和面板实例上触发以下DOM事件:

DOM 事件

事件Target描述
panel:open面板元素<div class="panel">当面板开始其打开动画时将触发事件
panel:opened面板元素<div class="panel">当面板完成其打开动画后触发事件
panel:close面板元素<div class="panel">当面板开始其关闭动画时触发事件
panel:closed面板元素<div class="panel">当面板完成其关闭动画后触发事件
panel:backdrop-click面板覆盖元素<div class="panel-backdrop">当面板覆盖被点击时将触发事件
panel:swipeopen面板元素<div class="panel">在用滑动打开它的最开始时触发事件
panel:swipe面板元素<div class="panel">在触摸滑动操作期间将触发事件用于滑动面板
panel:collapsedbreakpoint面板元素<div class="panel">当应用宽度与其匹配时,它将变得可见/隐藏时触发事件collapsedBreakpoint
panel:breakpoint面板元素<div class="panel">当应用宽度与其匹配时,它将变得可见/隐藏时触发事件visibleBreakpoint
panel:resize面板元素<div class="panel">在可调整大小的面板调整大小时会触发事件
panel:beforedestroy面板元素<div class="panel">在Panel实例将被销毁之前会触发事件

应用和面板实例事件

面板实例在自身实例和应用程序实例上发出事件。应用程序实例事件具有以panel.

事件Target参数描述
open为前缀面板(面板)当面板开始其打开动画时将触发事件。作为参数,事件处理程序接收面板实例
panelOpenapp(面板)
opened面板(面板)当面板完成其打开动画时将触发事件。作为参数,事件处理程序接收面板实例
panelOpenedapp(面板)
close面板(面板)当面板开始其关闭动画时将触发事件。作为参数,事件处理程序接收面板实例
panelCloseapp(面板)
closed面板(面板)当面板完成其关闭动画时将触发事件。作为参数,事件处理程序接收面板实例
panelClosedapp(面板)
backdropClick面板(面板)当面板覆盖被点击时将触发事件。作为参数,事件处理程序接收面板实例
panelBackdropClickapp(面板)
swipeOpen面板(面板)在用滑动打开它的最开始会触发事件。作为参数,事件处理程序接收面板实例
panelSwipeOpenapp(面板)
滑动面板(面板, 进度)在滑动面板的触摸滑动操作期间会触发事件。作为参数,事件处理程序接收面板实例和打开进度(从0到1)
panelSwipeapp(面板, 进度)
collapsedBreakpoint面板(面板)当应用宽度与其匹配时,它将变得可见/隐藏时触发事件collapsedBreakpoint。作为参数,事件处理程序接收面板实例
panelCollapsedBreakpointapp(面板)
断点面板(面板)当应用宽度与其匹配时,它将变得可见/隐藏时触发事件visibleBreakpoint。作为参数,事件处理程序接收面板实例
panelBreakpointapp(面板)
resize面板(面板, 新面板宽度)在可调整大小的面板调整大小时会触发事件
panelResizeapp(面板)
beforeDestroy面板(面板)在Panel实例将被销毁之前会触发事件
panelBeforeDestroyapp(面板)

面板自动初始化

如果你不需要使用Panel API并且你的Panel在应用初始化时位于其中或在页面中并且在页面初始化时在DOM中呈现,那么它可以通过仅添加额外的panel-init class:

<!-- Add panel-init class -->
<div class="panel panel-left panel-cover panel-init">
  ...
</div>

在这种情况下,如果你需要访问创建的面板实例,你可以使用app.panel.get app method:

var panel = app.panel.get('.panel-left');

if (panel.opened) {
  // do something
}

当使用自动初始化时,你可能需要传递额外的参数。这可以通过面板元素的data-属性来完成。

<!-- parameters set via data- attributes -->
<div
  class="panel panel-left panel-reveal panel-init"
  data-collapsed-breakpoint="768"
  data-visible-breakpoint="1024"
  data-swipe="true"
>
  ...
</div>

参数使用 camelCase,例如visibleBreakpoint,在data-属性中应使用kebab-case作为data-visible-breakpoint

可以使用特殊类和数据属性在链接上打开和关闭所需的面板(如果你在DOM中拥有它们):

  • 要打开面板,我们需要向任何HTML元素(首选链接)添加panel-open

  • 要关闭面板,我们需要向任何HTML元素(首选链接)添加panel-close

  • 要切换面板,我们需要向任何HTML元素(首选链接)添加panel-toggle

  • 如果你想指定应该打开/关闭哪个面板,那么可以通过在这个HTML元素上的附加data-panel=".panel-left"属性来完成。这个属性也可以只接收leftright值,如果DOM中只有一个这样的侧面板。

根据上述说明:

<body>
  <div id="app">
    <!-- Left Panel with Reveal effect -->
    <div class="panel panel-left panel-reveal panel-init">
      <div class="block">
        ...
        <!-- Clicking on link with "panel-close" class will close panel -->
        <p><a href="#" class="panel-close">Close me</a></p>
        <!-- Click on link with "panel-open" and data-panel=".panel-right" attribute will open Right panel -->
        <p><a href="#" data-panel=".panel-right" class="panel-open">Open Right Panel</a></p>
      </div>
    </div>

    <!-- Right Panel with Cover effect -->
    <div class="panel panel-right panel-cover panel-init">
      <div class="block">
        ...
        <!-- Click on link with "panel-close" class will close panel -->
        <p><a href="#" class="panel-close">Close me</a></p>
        <!-- Click on link with "panel-open" and data-panel=".panel-left" attribute will open Left panel -->
        <p><a href="#" data-panel=".panel-left" class="panel-open">Open Left Panel</a></p>
      </div>
    </div>

    ...
    <div class="page-content">
      <div class="block">
        <!-- Click on link with "panel-open" and data-panel=".panel-left" attribute will open Left panel -->
        <p><a href="#" data-panel=".panel-left" class="panel-open">Open Left Panel</a></p>
        <!-- Click on link with "panel-open" and data-panel=".panel-right" attribute will open Right panel -->
        <p><a href="#" data-panel=".panel-right" class="panel-open">Open Right Panel</a></p>
      </div>
    </div>
  </div>
  ...
</body>

可路由面板

面板也可以像可路由的模态和页面一样进行路由:

routes = [
  ...
  // Creates Panel from passed HTML string
  {
    path: '/left-panel/',
    panel: {
      content: `
        <div class="panel panel-left panel-cover">
          <div class="view">
            <div class="page">
              ...
            </div>
          </div>
        </div>
      `
    }
  },
  // Load Panel from file via Ajax
  {
    path: '/right-panel-ajax/',
    panel: {
      url: './right-panel.html',
      /* right-panel.html contains:
      <div class="panel panel-right panel-reveal">
        <div class="view">
          <div class="page">
            ...
          </div>
        </div>
      </div>
      */
    },
  },
  // Load Panel from component file
  {
    path: '/panel-component/',
    panel: {
      componentUrl: './panel-component.html',
      /* panel-component.html contains:
      <template>
        <div class="panel panel-left panel-cover">
          <div class="view">
            <div class="page">
              ...
            </div>
          </div>
        </div>
      </template>
      <style>...</style>
      <script>...</script>
      */
    },
  },
]

根据上面的示例:

嵌套面板

除了主应用面板外,还可以有嵌套面板,例如在页面内。要使Panel嵌套,我们需要指定其containerEl参数指向父容器(例如Page元素),并将其放在page-contentelement:

<div class="page" id="panel-page">
  <div class="navbar">
    <!-- ... -->
  </div>

  <!-- Nested panel has parent page specified in containerEl parameter -->
  <div class="panel panel-left panel-cover panel-init dark" id="panel-nested" data-container-el="#panel-page">
    <div class="page">
      <!-- ... -->
    </div>
  </div>

  <!-- Rest of the page -->
  <div class="page-content">
    <!-- ... -->
  </div>
</div>

CSS 变量

以下是相关CSS 变量(CSS 自定义属性) 的列表。

注意,注释掉的变量默认未指定,其值在这种情况下是它们回退到的值。

:root {
  --f7-panel-width: 260px;
  --f7-panel-backdrop-bg-color: rgba(0, 0, 0, 0.3);
  /*
  --f7-panel-left-width: var(--f7-panel-width);
  --f7-panel-right-width: var(--f7-panel-width);
  --f7-panel-left-collapsed-width: var(--f7-panel-collapsed-width);
  --f7-panel-right-collapsed-width: var(--f7-panel-collapsed-width);
  */
  --f7-panel-bg-color: #fff;
}
:root .dark,
:root.dark {
  --f7-panel-bg-color: #000;
}
.ios {
  --f7-panel-collapsed-width: 58px;
  --f7-panel-transition-duration: 400ms;
  --f7-panel-transition-timing-function: initial;
}
.md {
  --f7-panel-collapsed-width: 60px;
  --f7-panel-transition-duration: 400ms;
  --f7-panel-transition-timing-function: cubic-bezier(0, 0.8, 0.34, 1);
}

示例

panel.html
<div class="page" id="panel-page">
  <div class="navbar">
    <div class="navbar-bg"></div>
    <div class="navbar-inner sliding">
      <div class="title">Panel / Side panels</div>
    </div>
  </div>
  <div class="panel panel-left panel-cover panel-init" id="panel-nested" data-container-el="#panel-page">
    <div class="page">
      <div class="page-content">
        <div class="block block-strong-ios block-outline-ios">
          <p>This is page-nested Panel.</p>
          <p><a class="panel-close">Close me</a></p>
        </div>
      </div>
    </div>
  </div>

  <div class="page-content">
    <div class="block block-strong-ios block-outline-ios">
      <p>Framework7 comes with 2 panels (on left and on right), both are optional.
        You can put absolutely anything inside: data lists, forms, custom content, and even other isolated app view
        (like in right panel now) with its own dynamic navbar.</p>
    </div>
    <div class="block block-strong-ios block-outline-ios">
      <p class="grid grid-cols-2 grid-gap">
        <a class="button button-raised button-fill panel-open">Open left panel</a>
        <a class="button button-raised button-fill panel-open" data-panel="right">Open right panel</a>
      </p>
      <p>
        <a class="button button-raised button-fill panel-open" data-panel="#panel-nested">Open nested panel</a>
      </p>
    </div>
  </div>
</div>