添加 Foundation 和 Motion UI

Foundation 是一个用于创建响应式网站的前端框架。它附带了用于网格布局、排版、按钮、表格、导航、表单等等的 HTMLCSS 模板,以及可选的 JavaScript 插件。它适用于任何设备,无论是移动设备还是桌面设备,并且是另一个流行的前端框架 Bootstrap (https://getbootstrap.com/) 的替代品。本书我们将重点介绍 Foundation。因此,正如上一章一样,当使用 create-nuxt-app 脚手架来安装你的 Nuxt 项目的骨架时,我们提供了一个建议的 UI 框架列表供你选择。我们应该选择 None,以便我们可以将 Foundation 添加为 UI 框架:

? Choose UI framework (Use arrow keys)
❯ None
Ant Design Vue
Bootstrap Vue
...

一旦你完成了安装过程中的问题,导航到你的项目目录,然后你就可以在你的 Nuxt 应用程序中安装和集成 Foundation。最简单的方法是使用内容分发网络 (CDN),但这并不推荐。最简单的原因是,如果你离线开发,CDN 链接将无法工作。此外,你将失去对源文件的控制,因为它们由大型网络公司(如 GoogleMicrosoftAmazon)处理。但是,如果你想在你的 Nuxt 项目中使用 CDN 进行快速入门,只需将 CDN 源代码添加到 Nuxt 配置文件的 head 选项中,如下所示:

// nuxt.config.js
export default {
  head: {
    script: [
      { src: 'https://cdn.jsdelivr.net/.../foundation.min.js' },
    ],
    link: [
      { rel: 'stylesheet', href:
        'https://cdn.jsdelivr.net/.../foundation.min.css' },
    ],
  },
}

你可以在 Foundation 官方网站 https://get.foundation/sites/docs/installation.html#cdn-links 上找到最新的 CDN 链接。

这很简单,不是吗?但如果你想在本地托管源文件,这并不是理想的选择。让我们在以下步骤中了解与 Nuxt 集成的正确方法:

  1. 在你的终端上通过 npm 安装 Foundation 及其依赖项(jQuerywhat-input):

    $ npm i foundation-sites
    $ npm i jquery
    $ npm i what-input
  2. Foundation CSS 源代码从 /node_modules/ 文件夹添加到 Nuxt 配置文件的 css 选项中,如下所示:

    // nuxt.config.js
    export default {
      css: [
        'foundation-sites/dist/css/foundation.min.css'
      ],
    }
  3. /plugins/ 目录中创建一个 foundation.client.js 文件,其中包含以下代码:

    // plugins/client-only/foundation.client.js
    import 'foundation-sites'

    此插件将确保 Foundation 仅在客户端运行。我们将在第六章 “编写插件和模块” 中更详细地介绍插件。

  4. Nuxt 配置文件的 plugins 选项中注册上述 Foundation 插件,如下所示:

    // nuxt.config.js
    export default {
      plugins: [
        '~/plugins/client-only/foundation.client.js',
      ],
    }
  5. 然后你可以在任何需要它们的页面中使用 FoundationJavaScript 插件,例如:

    // layouts/form.vue
    <script>
    import $ from 'jquery'
    export default {
      mounted () {
        $(document).foundation()
      }
    }
    </script>

就这样。你已成功在你的 Nuxt 项目中安装并集成了 Foundation。现在,让我们在下一节中探讨如何使用 Foundation 创建网格结构的布局和网站导航,以加速前端 Web 开发。

使用 Foundation 创建网格布局和网站导航

好的,我们首先要了解的是 Foundation 的网格系统,它被称为 XY Grid。在 Web 开发中,网格系统是一种将我们的 HTML 元素组织成基于网格的布局的系统。Foundation 提供了一些 CSS 类,我们可以使用这些类轻松地构建我们的 HTML 元素,例如:

<div class="grid-x">
  <div class="cell medium-6">left</div>
  <div class="cell medium-6">right</div>
</div>

这段代码在大型屏幕(例如 iPad、Windows Surface)上会将元素响应式地排列成两列,但在小型屏幕(例如 iPhone)上则会排列成单列。让我们在 create-nuxt-app 脚手架工具生成的默认 index.vue 页面中创建一个响应式布局,并在默认的 default.vue 布局中创建网站导航,步骤如下:

  1. 删除 /components/ 目录下的 Logo.vue 组件。

  2. 移除 /pages/ 目录下 index.vue 页面中的 <style><script> 块,但将 <template> 块替换为以下元素和网格类:

    // pages/index.vue
    <template>
      <div class="grid-x">
        <div class="medium-6 cell">
          <img src="~/assets/images/sample-01.jpg">
        </div>
        <div class="medium-6 cell">
          <img src="~/assets/images/sample-02.jpg">
        </div>
      </div>
    </template>

    在这个模板中,当页面在大型屏幕上加载时,图片会并排显示。但是当页面调整到小型屏幕尺寸或在小型屏幕上加载时,它们会响应式地堆叠在一起。

  3. 移除 /layouts/ 目录下 default.vue 布局中的 <style><script> 块,但将 <template> 块替换为以下导航:

    // layouts/default.vue
    <template>
      <div>
        <ul class="menu align-center">
          <li><nuxt-link to="/">Home</nuxt-link></li>
          <li><nuxt-link to="/form">Form</nuxt-link></li>
          <li><nuxt-link to="/motion-ui">Motion UI</nuxt-link></li>
        </ul>
        <nuxt />
      </div>
    </template>

    在这个新的布局中,我们通过向 <ul> 元素添加 .menu 类,创建了一个包含三个 <li> 元素和 <nuxt-link> 组件的基本网站水平菜单。我们还通过在 .menu 类之后添加 .align-center,将菜单项居中对齐。

就是这样。你现在拥有了一个在任何设备上都能完美运行的响应式布局和导航。你可以看到,无需编写任何 CSS 样式,你就可以如此快速地完成这些工作。这不是很棒吗?但是 JavaScript 呢?Foundation 也提供了一些我们可以使用的 JavaScript 实用程序和插件。让我们在下一节中了解一下。

有关 FoundationXY 网格和导航的更多信息,请访问 https://get.foundation/sites/docs/xy-grid.htmlhttps://get.foundation/sites/docs/menu.html。

使用 Foundation 的 JavaScript 实用工具和插件

好的,Foundation 提供了许多有用的 JavaScript 实用程序,例如 MediaQuery。这个 MediaQuery 实用程序可以用来获取屏幕尺寸的断点(小、中、大、特大),以便在你的应用程序中创建响应式布局。让我们通过以下步骤了解如何使用它:

  1. /plugins/ 目录下创建一个用于存放自定义全局实用程序的 utils.js 文件,并添加以下代码:

    // plugins/utils.js
    import Vue from 'vue'
    Vue.prototype.$getCurrentScreenSize = () => {
      window.addEventListener('resize', () => {
        console.log('Current screen size: ' +
          Foundation.MediaQuery.current)
      })
    }

    在这段代码中,我们创建了一个全局插件(一个 JavaScript 函数),它将从 MediaQuery 实用程序的 current 属性中获取当前的屏幕尺寸,并在浏览器屏幕尺寸改变时记录输出。通过使用 JavaScriptEventTarget 方法 addEventListener,一个 resize 事件监听器被添加到 window 对象上。然后,通过将其命名为 $getCurrentScreenSize,这个插件被注入到 Vue 实例中。

  2. 如下所示在默认布局中调用这个 $getCurrentScreenSize 函数:

    // layouts/default.vue
    <script>
    export default {
      mounted () {
        this.$getCurrentScreenSize()
      }
    }
    </script>

因此,如果你打开 Chrome 浏览器的控制台选项卡,当你调整屏幕大小时,你应该会看到当前屏幕尺寸的日志,例如 Current screen size: medium。

除了 JavaScript 实用程序之外,Foundation 还附带了许多 JavaScript 插件,例如用于创建下拉导航的 Dropdown Menu,用于表单验证的 Abide,以及用于在 HTML 页面中的元素上显示扩展信息的 Tooltip。这些插件可以通过简单地将它们的类名添加到你的元素上来激活。此外,你可以像我们在本节中向你展示的那样,通过编写 JavaScript 来修改它们并与之交互。让我们在以下步骤中看一下 Abide 插件:

  1. /pages/ 目录下创建一个 form.vue 页面,其中包含以下 HTML 元素,以创建一个包含两个 .grid-container 元素块的表单:

    // pages/form.vue
    <template>
      <form data-abide novalidate>
        <div class="grid-container">
          <div class="grid-x">
            <div class="cell small-12">
              <div data-abide-error class="alert callout"
                   style="display: none;">
                <p><i class="fi-alert"></i> There are errors in your
                  form.</p>
              </div>
            </div>
          </div>
        </div>
        <div class="grid-container">
          <div class="grid-x">
            //...
          </div>
        </div>
      </form>
    </template>

    在这个表单中,第一个网格容器包含一般的错误消息,而第二个容器将包含表单输入字段。我们仅仅通过向 form 元素添加 data-abide 就激活了 Abide 插件。我们还向 form 元素添加了一个 novalidate 属性,以阻止浏览器的原生验证,这样我们就可以将验证工作交给 Abide 插件。

  2. 创建一个包含带有 email 类型的 <input> 元素和两个默认错误消息的 <span> 元素的 <div> 块,并添加 .cell.small-12 类,如下所示:

    // pages/form.vue
    <div class="cell small-12">
      <label>Email (Required)
        <input type="text" placeholder="hello@example.com" required
               pattern="email">
        <span class="form-error" data-form-error-on="required">
          Sorry, this field is required.
        </span>
        <span class="form-error" data-form-error-on="pattern">
          Sorry, invalid Email
        </span>
      </label>
    </div>

    在这个单元格块中,有三个来自 Foundation 的自定义属性:pattern 属性用于验证电子邮件字符串,data-form-error-on 属性用于响应 requiredpattern 属性显示输入错误,而 placeholder 属性用于在输入字段中显示输入提示。请注意,required 属性是一个 HTML5 的默认属性。

  3. 创建两个包含两个用于收集密码的 <input> 元素的 <div> 块,其中第二个密码通过向第二个密码 <input> 元素添加 Foundationdata-equalto 属性来匹配第一个密码,如下所示:

    // pages/form.vue
    <div class="cell small-12">
      <label>Password Required
        <input type="password" placeholder="chewieR2D2" required >
        <span class="form-error">
          Sorry, this field is required.
        </span>
      </label>
    </div>
    <div class="cell small-12">
      <label>Re-enter Password
        <input type="password" placeholder="chewieR2D2" required
               pattern="alpha_numeric"
               data-equalto="password">
        <span class="form-error">
          Sorry, passwords are supposed to match!
        </span>
      </label>
    </div>
  4. 创建包含提交按钮和重置按钮的最后一个 <div> 块,如下所示:

    // pages/form.vue
    <div class="cell small-12">
      <button class="button" type="submit"
              value="Submit">Submit</button>
      <button class="button" type="reset" value="Reset">Reset</button>
    </div>
  5. Vue 组件挂载时,在 <script> 块中初始化 Foundation JavaScript 插件:

    // pages/form.vue
    <script>
    import $ from 'jquery'
    export default {
      mounted () {
        $(document).foundation()
      }
    }
    </script>

就是这样。无需编写任何 JavaScript,你仅仅通过添加带有类和属性的 HTML 元素就创建了一个漂亮的前端表单验证。这非常有用!

有关 FoundationAbide 插件的更多信息,请访问 https://get.foundation/sites/docs/abide.html。

除了 JavaScript 实用程序和插件之外,Zurb Foundation 还提供了一些有用的库,我们可以从中受益:用于创建 Sass/CSS 动画的 Motion UI,用于使用可重用 partials 创建页面和布局的 Panini,以及用于为你的代码库创建样式指南的 Style Sherpa。我们将在下一节探讨如何使用 Motion UI 创建 CSS 动画和过渡效果。让我们拭目以待!

使用 Motion UI 创建 CSS 动画和过渡

好的,Motion UI 是 Zurb Foundation 提供的一个方便的 Sass 库,用于快速创建 CSS 过渡和动画。你可以从 Motion UI 网站下载 Starter Kit 并进行尝试,但这缺乏你自己的控制,因为它带有许多你必须使用的内置默认值和效果。因此,如果你想拥有更多控制并充分利用 Motion UI,你必须知道如何自定义和编译 Sass 代码。让我们通过以下步骤了解如何编写你的 Sass 动画:

  1. 在你的终端上通过 npm 安装 Motion UI 及其依赖项(SassSass loader):

    $ npm i motion-ui --save-dev
    $ npm i node-sass --save-dev
    $ npm i sass-loader --save-dev
  2. /assets/ 目录下创建一个 /css/ 文件夹,并在其中创建一个 main.scss 文件,并按如下方式导入 Motion UI

    // assets/scss/main.scss
    @import 'motion-ui/src/motion-ui';
    @include motion-ui-transitions;
    @include motion-ui-animations;
  3. 接着是自定义 CSS 动画,如下所示:

    // assets/scss/main.scss
    .welcome {
      @include mui-animation(fade);
      animation-duration: 2s;
    }
  4. Nuxt 配置文件中的 css 选项中注册自定义 Motion UI CSS 资源:

    // nuxt.config.js
    export default {
      css: [
        'assets/scss/main.scss'
      ]
    }
  5. 通过使用其类名将动画应用于任何元素,例如:

    // pages/index.vue
    <img class="welcome" src="~/assets/images/sample-01.jpg">

    然后你应该看到,每当页面加载时,前面的图像都会花费 2 秒逐渐淡入。

Motion UI 还提供了两个我们可以与之交互以触发其内置动画和过渡的公共函数:animationInanimateOut。让我们通过以下步骤了解如何使用它们:

  1. /plugins/ 目录下创建一个 motion-ui.client.js 文件,其中包含以下代码:

    // plugins/client-only/motion-ui.client.js
    import Vue from 'vue'
    import MotionUi from 'motion-ui'
    Vue.prototype.$motionUi = MotionUi

    这个插件将确保 Motion UI 仅在客户端运行。我们将在第 6 章 “编写插件和模块” 中更详细地介绍插件。

  2. 如下所示,在 Nuxt 配置文件的 plugins 选项中注册前面的 Motion UI 插件:

    // nuxt.config.js
    export default {
      plugins: [
        '~/plugins/client-only/motion-ui.client.js',
      ],
    }
  3. 在模板中的任何地方使用 Motion UI 函数,例如:

    // pages/motion-ui.vue
    <template>
      <h1 data-animation="spin-in">Hello Motion UI</h1>
    </template>
    <script>
    import $ from 'jquery'
    export default {
      mounted () {
        $('h1').click(function() {
          var $animation = $('h1').data('animation')
          this.$motionUi.animateIn($('h1'), $animation)
        })
      }
    }
    </script>

在这个页面中,我们将过渡名称 spin-in 存储在元素的 data 属性中,然后将其传递给 Motion UIanimateIn 函数,以便在单击该元素时应用动画。请注意,我们使用 jQuerydata 属性获取数据。

如果你想了解其余的内置过渡名称,请访问 https://get.foundation/sites/docs/motion-ui.html#built-intransitions。

这不是很酷吗?如果你需要在你的元素上使用 CSS 动画或过渡,并且不想自己编写大量的 CSS 代码,这将非常方便。这可以使你的 CSS 样式保持简洁,并专注于模板的主要和自定义呈现。说到节省时间和不必自己编写通用代码,值得一提的是 Zurb Foundation 也提供的通用图标字体 – Foundation Icon Font 3。让我们在下一节中了解如何从中受益。

使用 Foundation Icon Fonts 3 添加图标

好的,Foundation Icon Fonts 3 是一套非常有用的图标字体集,我们可以在前端开发的项目中通过 CSS 使用它。它可以让你免于自己创建常见的图标,例如社交媒体图标(FacebookTwitterYouTube)、箭头图标(向上箭头、向下箭头等等)、无障碍图标(轮椅、电梯等等)、电子商务图标(购物车、信用卡等等)和文本编辑器图标(粗体、斜体等等)。让我们通过以下步骤了解如何在你的 Nuxt 项目中安装它:

  1. 通过 npm 安装 Foundation Icon Fonts 3

    $ npm i foundation-icon-fonts
  2. Nuxt 配置文件中全局添加 Foundation Icon Fonts 的路径:

    // nuxt.config.js
    export default {
      css: [
        'foundation-icon-fonts/foundation-icons.css',
      ]
    }
  3. 使用 fi 前缀加上图标名称,将图标应用于任何 <i> 元素,例如:

    <i class="fi-heart"></i>

你可以在 https://zurb.com/playground/foundation-icon-fonts-3 找到其余的图标名称。

做得好!在本节以及前面关于向你的 Nuxt 项目添加 Foundation 的章节中,你已经成功地使用网格系统来构建你的布局,并使用 SassMotion UI 创建 CSS 动画。但是,仅仅添加网格系统和编写 CSS 动画不足以构建一个应用程序;我们还需要特定的 CSS 来描述我们 Nuxt 应用程序中 HTML 文档和 Vue 页面的呈现。我们可以直接在整个项目中使用 Sass 来创建仅使用 Foundation 无法实现的自定义样式,但让我们尝试另一个流行的样式预处理器并将其添加到你的 Nuxt 项目中 – Less。让我们在下一节中了解一下。

你可以在我们的 GitHub 存储库的 /chapter-3/nuxt-universal/adding-foundation/ 中找到你目前所学到的所有关于 Foundation 的示例代码。