Framework7

framework7(简称f7)是一个用于构建iOS和Android应用程序的全功能Web框架,也就是说使用Web技术构建与原生应用类似的手机应用。

f7主要包括应用中常用的各种组件的样式和功能代码。

组件分为三大部分:core、react、vue,其中 core 为原生组件,react和vue为第三方组件,源代码使用phenome来自动生成 react和vue组件。

移动应用开发框架

移动应用开发框架

原生 => 桥接 => Web(小程序、PWA渐进、Hybrid混合)

Web App中的UI库非常多,让人眼花缭乱,该如何选择。

当前流行的UI库

部分UI对比图:

UI比较

为何选择f7

前端UI库看起来很多,实际上可使用的并不是很多。

选择UI的标准:

根据以上标准,反复对比,f7比较适合移动Web App开发。
f7专为移动应用打造,体积不大,可根据项目裁剪打包,基本包压缩后只有10K,同时支持Dom、React和Vue。并且社区非常活跃,更新很快。

wia开发框架,同时支持Dom、React和Vue,目前先支持Dom。
因此wia选择f7的UI部分作为UI组件,基于Dom方式有分离的js集成。

采用Dom方式有如下好处:

F7网址

官方发布的样式文件:

css 语法

f7 在less中使用了一些css的变量语法,通过定义变量来改变各个具体定义里面的颜色。

我们先熟悉一下css中的变量,这样看f7的less源代码就比较容易理解。

  1. 变量的声明

CSS变量声明是字母前加两个横线(--)如:

body{
 --Colors:#dfdfdf;
 --fS16px:16px;
}

上述代码中,body选择器中声明了Colors和fS16px两个变量。而使用‘--’是因为$被Sass占用了,@被Less占用了,所以是为了区分它们。

同时,你也可以用--root{}来存放所有变量,在下边使用的时候直接调用即可。如:

--root{
 --Colors:#dfdfdf;
 --fS16px:16px;
}
  1. var()函数 var函数用来读取变量
a{
  color:var(--Colors)      
}

var()函数还可以使用第二个参数,表示变量的默认值。如果该变量不存在,就会使用这个默认值。

color: var(--Colors, #e5e5e5);

第二个参数不处理内部的逗号或空格,都视作参数的一部分。

var(--fontF, "Roboto", "Helvetica");
var(--Margins, 15px 20px 25px);

var()函数还可以用在变量声明中

--root{
  --bgcolors:red;
  --fColor:var(--bgcolors)

注意:变量只能作为属性值,不能作为属性名

  1. 变量值的类型

如果变量值是字符串,则可以与其他字符串拼接

--far:'hello';
--foo:var(--far)',world';

如果是数值,则不可以拼接

--far:20;
--foo:var(--far)'px'; //无效

但可以通过calc()函数,将他们拼接起来

--far:20;
--foo:calc(var(--far)*1px);

如果变量值带单位,则不能写成字符串形式

--far:'20px';
margin-top:var(--far); //无效

--far:20px;
margin-top:var(--far); //有效
  1. 作用域
<style>
  :root { --color: blue; }
  div { --color: green; }
  #alert { --color: red; }
  * { color: var(--color); }
</style>

<p>蓝色</p>
<div>绿色</div>
<div id="alert">红色</div>

上面代码中,三个选择器都声明了--color变量。不同元素读取这个变量的时候,会采用优先级最高的规则,因此三段文字的颜色是不一样的。

这就是说,变量的作用域就是它所在的选择器的有效范围。

所以一些通用的变量值,最好声明在--root{}内。

  1. :root

css 伪类匹配文档的根元素。 对于 HTML 来说, :root 表示元素,除了优先级更高之外,与 html 选择器相同。

在声明全局 css 变量时 :root 会很有用:

:root {
  --ck-highlight-pen-red: #e91314;
  --ck-highlight-pen-blue: dodgerblue;
}

.pen-black {
  color: var(--ck-highlight-pen-black);
  background-color: transparent;
}
.pen-red {
  color: var(--ck-highlight-pen-red);
  background-color: transparent;
} 

生成项目所需的样式

在实际项目使用中,一般不会直接使用官方发布的样式文件,而是根据项目来生成需要的样式内容,这样可减少css文件大小。

缺省基本样式

wia/ui/f7/f7.less

@import (reference) './less/mixins.less';
@import (reference) './less/vars.less';

@includeIosTheme: $includeIosTheme;
@includeMdTheme: $includeMdTheme;
@includeAuroraTheme: $includeAuroraTheme;

@includeDarkTheme: $includeDarkTheme;
@includeLightTheme: $includeLightTheme;

@themeColor: $themeColor;

@colors: $colors;

@rtl: $rtl;

// Core
@import url('./components/app/app.less');
@import url('./components/statusbar/statusbar.less');
@import url('./components/view/view.less');
@import url('./components/page/page.less');
@import url('./components/link/link.less');
@import url('./components/navbar/navbar.less');
@import url('./components/toolbar/toolbar.less');
@import url('./components/subnavbar/subnavbar.less');
// @import url('./components/block/block.less');
// @import url('./components/list/list.less');
// @import url('./components/badge/badge.less');
// @import url('./components/button/button.less');
// @import url('./components/touch-ripple/touch-ripple.less');
// @import url('./components/icon/icon.less');
// @import url('./components/modal/modal.less');

该文件与用户配置文件一起,生成f7.css基本样式文件,压缩只有10k。
其他组件,需要根据项目在 f7.config.js中配置。

缺省可选组件样式

wia/ui/f7/f7.part.less

@import (reference) './less/mixins.less';
@import (reference) './less/vars.less';

@includeIosTheme: $includeIosTheme;
@includeMdTheme: $includeMdTheme;
@includeAuroraTheme: $includeAuroraTheme;

@includeDarkTheme: $includeDarkTheme;
@includeLightTheme: $includeLightTheme;

@themeColor: $themeColor;

@colors: $colors;

@rtl: $rtl;

// part
@import url('../../part-vars.less');

//IMPORT_COMPONENTS

这个 //IMPORT_COMPONENTS 会被项目中的 f7.config.js里面的组件所替代。
生成项目所需的组件样式文件。如:hello项目,则生成 f7.hello.css 样式文件。

该样式文件与f7.css一起加载,即可展示当前项目样式。

按需加载的好处是能实现应用秒开。所有f7样式文件需要74k,采用分离动态加载,应用启动只需加载10k,启动后,根据页面具体使用的组件,动态按需加载,压缩后的动态样式1k左右,能实现应用的秒开(1秒首次打开应用)和秒切(1秒切换界面)。

配置文件

wia工作空间中,已经将其源代码拷贝到 wia的 ui/f7 目录,该目录中有个 config.js 是所有wia项目默认全局配置。

生成项目所需要样式文件,只需配置项目目录中的 f7.config.js 文件即可。

文件内容如下:


/**
* F7 Build Configuration
*/

const config = {
  rtl: false, // 从右到左,少数国家是从右向左阅读
  // 根据项目需要,选择需要的组件
    components: [
    // Appbar
    'appbar',

    // Modals
    'dialog',
    'popup',
    'login-screen',
    'popover',
    'actions',
    'sheet',
    'toast',

    // Loaders
    'preloader',
    'progressbar',

    // List Components
    'sortable',
    'swipeout',
    'accordion',
    'contacts-list',
    'virtual-list',
    'list-index',

    // Timeline
    'timeline',

    // Tabs
    'tabs',

    // Panel
    'panel',

    // Card
    'card',

    // Chip
    'chip',

    // Form Components
    'form',
    'input',
    'checkbox',
    'radio',
    'toggle',
    'range',
    'stepper',
    'smart-select',

    // Grid
    'grid',

    // Pickers
    'calendar',
    'picker',

    // Page Components
    'infinite-scroll',
    'pull-to-refresh',
    'lazy',

    // Data table
    'data-table',

    // FAB
    'fab',

    // Searchbar
    'searchbar',

    // Messages
    'messages',
    'messagebar',

    // Swiper
    'swiper',

    // Photo Browser
    'photo-browser',

    // Notifications
    'notification',

    // Autocomplete
    'autocomplete',

    // Tooltip
    'tooltip',

    // Gauge
    'gauge',

    // Skeleton
    'skeleton',

    // Menu
    'menu',

    // Color Picker
    'color-picker',

    // Tree View
    'treeview',

    // WYSIWYG Editor
    'text-editor',

    // Elevation
    'elevation',

    // Typography
    'typography',

    // VI Video Ads
    'vi',
  ],
  darkTheme: true, // 夜晚主题,屏幕变暗
  lightTheme: true,
  themes: [
    'ios', // ios苹果手机样式
    'md',  // 安卓md样式
    'aurora', // 桌面样式
  ],
  themeColor: '#007aff', // 默认蓝色主题,f7内置15个颜色主题
    // 基本css中已经内置15个颜色主题,可在页面中引用
  colors: {
    red: '#ff3b30',
    // green: '#4cd964',
    // blue: '#2196f3',
    // pink: '#ff2d55',
    // yellow: '#ffcc00',
    // orange: '#ff9500',
    // purple: '#9c27b0',
    // deeppurple: '#673ab7',
    // lightblue: '#5ac8fa',
    // teal: '#009688',
    // lime: '#cddc39',
    // deeporange: '#ff6b22',
    // gray: '#8e8e93',
    // white: '#ffffff',
    // black: '#000000',
  },
};

module.exports = config;

配置参数说明

  const lessBundleContent = lessContent
    .replace('//IMPORT_COMPONENTS', components.map(
      component => `@import url('./components/${component}/${component}.less');`).join('\n'));
:root {
  each(@colors, {
    @themeColorRed: red(@value);
    @themeColorGreen: green(@value);
    @themeColorBlue: blue(@value);
    --f7-color-@{key}: @value;
    --f7-color-@{key}-rgb: @themeColorRed, @themeColorGreen, @themeColorBlue;
    --f7-color-@{key}-shade: darken(@value, 8%);
    --f7-color-@{key}-tint: lighten(@value, 8%);
  });
}

在 mixins.less 中定义风格判断函数:

.if-ios-theme(@ruleset) {
  & when (@includeIosTheme) {
    @ruleset();
  }
}
.if-md-theme(@ruleset) {
  & when (@includeMdTheme) {
    @ruleset();
  }
}
.if-aurora-theme(@ruleset) {
  & when (@includeAuroraTheme) {
    @ruleset();
  }
}
.if-dark-theme(@ruleset) {
  & when(@includeDarkTheme) {
    @ruleset();
  }
}
.ios-vars(@ruleset) {
  & when (@includeIosTheme) {
    .ios {
      @ruleset();
    }
  }
}
.md-vars(@ruleset) {
  & when (@includeMdTheme) {
    .md {
      @ruleset();
    }
  }
}
.aurora-vars(@ruleset) {
  & when (@includeAuroraTheme) {
    .aurora {
      @ruleset();
    }
  }
}

每个组件有4个less文件,比如按钮button,基本的button.less 部分内容如下:

.if-ios-theme({
  @import url('./button-ios.less');
});
.if-md-theme({
  @import url('./button-md.less');
});
.if-aurora-theme({
  @import url('./button-aurora.less');
});

根据函数来判断是否包含配置的风格less。

在 mixins.less 中定义rtl判断函数:

// RTL, LTR
.ltr(@ruleset) {
  & when not (@rtl) {
    @ruleset();
  }
}
.rtl(@ruleset) {
  & when (@rtl) {
    @ruleset();
  }
}

- dark/light:黑夜、白天模式。
  darkTheme: true, // 夜晚主题,屏幕变暗
  lightTheme: true,

在 mixins.less 中定义判断函数:

```less
.dark-vars(@ruleset) {
  & when (@includeDarkTheme) {
    .theme-dark, &.theme-dark {
      @ruleset();
    }
  }
}
.light-vars(@ruleset) {
  & when (@includeLightTheme) {
    & {
      @ruleset();
    }
  }
}

### 局部改变颜色主题

除配置中配置缺省颜色主题外,应用中也可以局部改变颜色主题。 只需要向需要的父元素添加color-theme- [color]类即可。 它可以是正文,应用程序根目录,视图,页面,导航栏,工具栏,列表块等。
使用这些颜色主题时,配置文件中的 colors 需配置该颜色才能生效。

颜色主题相关页面:https://framework7.io/docs/color-themes.html

例如:

```html
<body class="color-theme-red">
    ...
</body>

<div class="page color-theme-green">
    ...
</div>

<div class="list-block color-theme-pink">
    ...
</div>

<div class="navbar color-theme-orange">
    ...
</div>

<div class="segmented color-theme-yellow">
    ...
</div>

辅助颜色定义

还有其他辅助类,可以在没有/没有颜色主题的情况下使用:

<a class="button color-red">Red button</a>

<p class="text-color-red">Red color text</p>

<span class="badge bg-color-pink">14</span> - pink badge

<div class="button border-color-red">...</div>

当然,您可以混合使用这些帮助程序类:

<a class="button bg-color-blue text-color-white border-color-gray">...</a>

使用主题颜色

助手类支持与上下文颜色主题相同的其他原色。

自定义颜色主题

要设置自定义颜色主题,我们需要指定如下四个CSS变量:

例如,如果自定义主题颜色为#f00(红色),则只需在CSS中添加以下变量:

:root {
  --f7-theme-color: #f00;
  --f7-theme-color-shade: #d60000;
  --f7-theme-color-tint: #ff2929;
  --f7-theme-color-rgb: 255, 0, 0;
}

在less中定义则比较简单,只需指定一个主题颜色即可:

:root {
  @themeColor: #f00;
  @themeColorRed: red(@themeColor);
  @themeColorGreen: green(@themeColor);
  @themeColorBlue: blue(@themeColor);
  --f7-theme-color: @themeColor;
  --f7-theme-color-rgb: @themeColorRed, @themeColorGreen, @themeColorBlue;
  --f7-theme-color-shade: darken(@themeColor, 8%);
  --f7-theme-color-tint: lighten(@themeColor, 8%);
}

编译为css样式文件

less是CSS的高级版本,浏览器无法直接使用,实际使用时,需要将Less编译成浏览器能识别的CSS。
f7源代码中的编译过程非常复杂,包含core、react、vue等各种形式的编译,我们先从core入手,将core部分的编译抽离出来,放到 ui/f7/f7.js 中。

f7.js的编译原理也非常简单,步骤如下:

  1. 读取项目 f7.config.js 配置文件。
  2. 与ui/f7/config.js 的缺省配置文件进行合并。
  3. 根据配置文件中的变量,替换 ./ui/f7/f7.less./ui/f7/f7.part.less 中的字符串。
  4. 生成项目所需的less文件:dist/${prj}/f7.lessdist/${prj}/f7.${prj}.less,引用生成f7.项目名.css之前,需引用基本f7.css,否则项目f7.css不起作用。
  5. 根据 f7.less 和 f7.项目名.less生成 f7.css 和 f7.项目名.css文件。该css发布后,项目首页引用该css文件即可。
  6. 除非需要修改基本css,否则标准的基本css直接直接引用已经发布的f7.css CDN版本即可,只需生成项目所需的 f7.项目名称.css。
  7. 生成指令为:gulp --gulpfile gulpf7.js
  8. 一般来说,项目还有其他样式文件,可将组件样式文件与其他样式文件一起生成。

修改f7中的源文件

由于wia将f7作为wia ui的一部分,因此编译less时,个别源文件路径需修改。
目前发现需修改的路径是两个字体引用,用于图标,建议使用淘宝的iconfont生成自己需要的图标字体,屏蔽f7内置字体。

或者直接屏蔽: const iconsFontBase64 = ''; const iconsFontBase64 = '';

也就是说,将整各F7集成到wia中,只需将最新版本framework7中的src源代码目录拷贝到wia\ui\f7目录,修改/src/core/less/plugin.js中如上两行即可。

wia集成F7后,将继续集成支持vue、react的其他UI库。

基于F7的基本页面布局

<!DOCTYPE html>
<html>
  <head>
    <!-- Required meta tags-->
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no, minimal-ui, viewport-fit=cover">
    <meta name="apple-mobile-web-app-capable" content="yes">
    <!-- Color theme for statusbar (Android only) -->
    <meta name="theme-color" content="#2196f3">
    <!-- Your app title -->
    <title>My App</title>
    <!-- Path to Framework7 Library Bundle CSS -->
    <link rel="stylesheet" href="path/to/framework7.bundle.min.css">
    <!-- Path to your custom app styles-->
    <link rel="stylesheet" href="path/to/my-app.css">
  </head>
  <body>
    <!-- App root element -->
    <div id="app">

      <!-- Your main view, should have "view-main" class -->
      <div class="view view-main">
        <!-- Initial Page, "data-name" contains page name -->
        <div data-name="home" class="page">

          <!-- Top Navbar -->
          <div class="navbar">
            <div class="navbar-bg"></div>
            <div class="navbar-inner">
              <div class="title">Awesome App</div>
            </div>
          </div>

          <!-- Bottom Toolbar -->
          <div class="toolbar toolbar-bottom">
            <div class="toolbar-inner">
              <!-- Toolbar links -->
              <a href="#" class="link">Link 1</a>
              <a href="#" class="link">Link 2</a>
            </div>
          </div>

          <!-- Scrollable page content -->
          <div class="page-content">
            <p>Page content goes here</p>
            <!-- Link to another page -->
            <a href="/about/">About app</a>
          </div>
        </div>
      </div>
    </div>
    <!-- Path to Framework7 Library Bundle JS-->
    <script type="text/javascript" src="path/to/framework7.bundle.min.js"></script>
    <!-- Path to your app js-->
    <script type="text/javascript" src="path/to/my-app.js"></script>
  </body>
</html>