十、练习的解决方案

第一章练习

在第一章末尾,进行了以下练习:

毫无疑问,我们在前几章中构建的 Pomodoro 计时器非常棒,但它仍然缺少一些好的特性。它能提供的一件非常好的事情是展示中的随机小猫 http://thecatapi.com/ 休息时间。你能实现这个吗?你当然可以!但请不要混淆休息和工作时间!我几乎可以肯定,如果你不工作,而是盯着小猫看,你的项目经理会不太喜欢:)

让我们来解决它。

检查处的 Pomodoro 代码 https://jsfiddle.net/chudaol/b6vmtzq1/

检查http://thecatapi.com/ 网站。

让我们从添加 well Bootstrap 元素开始,该元素带有一个源指向 cat API 的映像:

<div id="app" class="container">
  <...>
  <div class="well">
    <img :src="’ http://thecatapi.com/aimg/get?
 type=gif&size=med’" />
  <div>
</div>

如果打开页面,您将看到图像始终可见。这不是我们想要的,我们想要的,只有当我们在波莫多罗休息的时候才看得见。你已经知道怎么做了。有几种方法可以实现这一点;让我们使用类绑定方法绑定一个在状态工作时隐藏的类:

<div class="well" :class="{ 'hidden': pomodoroState === 'work' }">
  <img :src="'http://thecatapi.com/api/
    img/get?type=gif&size=med'" />
</div>

现在,如果您打开页面,您将看到图像仅在工作完成后显示。

然而,问题是,在我们休息的所有时间里,图像都是一样的。如果我们能每 10 秒更新一次就好了。

为此,让我们使用缓存清除机制。如果我们在 URL 上附加一些属性,并每 10 秒更改一次,URL 就会更改,因此我们将获得另一个随机猫。让我们在 Vue 应用中添加一个timestamp变量,并在_tick函数中对其进行更改:

<...>
new Vue({
  el: "#app",
  data: {
    <...>
    timestamp: 0
  },
  <...>
  methods: {
    <...>
    _tick: function () {
      //update timestamp that is used in image src
      if (this.second % 10 === 0) {
        this.timestamp = new Date().getTime();
      }
      <...>
    }
  }
});

创建和更新时间戳后,我们可以在图像源 URL 中使用它:

<div class="well" :class="{ 'hidden': pomodoroState === 'work' }">
  <img :src="'http://thecatapi.com/aimg/get?
    type=gif&size=med&ts=' + timestamp" />
</div>

这就是全部!在处检查此 JSFIDLE 中的整个代码 https://jsfiddle.net/chudaol/4hnbt0pd/2/

第二章练习

增强功能插件

用三角函数(正弦、余弦和切线)增强我们的MathPlugin

实际上,它只是添加缺少的指令并在其中使用Math对象的函数。打开VueMathPlugin.js并添加以下内容:

//VueMathPlugin.js
export default {
  install: function (Vue) {
    Vue.directive('square', function (el, binding) {
      el.innerHTML = Math.pow(binding.value, 2);
    });
    Vue.directive('sqrt', function (el, binding) {
      el.innerHTML = Math.sqrt(binding.value);
    });
    Vue.directive('sin', function (el, binding) {
      el.innerHTML = Math.sin(binding.value);
    });
    Vue.directive('cos', function (el, binding) {
      el.innerHTML = Math.cos(binding.value);
    });
    Vue.directive('tan', function (el, binding) {
      el.innerHTML = Math.tan(binding.value);
    });
  }
};

您可以检查此指令在 HTML 文件中的工作方式:

//index.html 
<div id="app">
  <input v-model="item"/>
  <hr>
  <div><strong>Square:</strong> <span v-square="item"></span></div>
  <div><strong>Root:</strong> <span v-sqrt="item"></span></div> <div><strong>Sine:</strong> <span v-sin="item"></span></div>
  <div><strong>Cosine:</strong> <span v-cos="item"></span></div>
  <div><strong>Tangent:</strong> <span v-tan="item"></span></div>
</div>

就这样!

创建 Pomodoro 定时器的 Chrome 应用

请结合使用 Vue.js 的 SCP 兼容版本引导应用的解决方案,以及我们在第 1 章中创建的简单 Pomotoro 应用与 Vue.js一起购物。检查chrome-app-pomodoro文件夹中的代码。

第三章练习

练习 1

当我们使用简单的组件重写购物清单应用时,我们失去了应用的功能。本练习建议使用事件发射系统来恢复功能。

我们在本节中使用的代码与第 3 章/vue 购物清单简单组件文件夹中的代码类似。

为什么不起作用?检查 devtools 错误控制台。它声明如下:

[Vue warn]: Property or method "addItem" is not defined on the instance but referenced during render. Make sure to declare reactive data properties in the data option.
(found in component <add-item-component>)

啊哈!这是因为在add-item-template内部我们调用的addItem方法不属于该组件。此方法属于父组件,当然,子组件无权访问它。我们该怎么办?让我们发射事件!我们已经知道怎么做了。所以,我们不必做太多。实际上,我们必须做三件小事:

  • addItem方法附加到add-item-component中,我们将在其中发出一个事件,并将此组件的newItem属性传递给它。
  • 修改/简化父组件的addItem方法。它现在应该只接收一个文本并将其添加到它的items属性中。
  • 将带有事件名称的v-on修饰符附加到主标记内的组件调用,主标记将在每次发出事件时调用addItem方法。

让我们从将addItem方法添加到add-item-component开始。每次点击添加按钮或输入时都会调用该按钮。此方法应检查newItem属性,如果它包含文本,则应发出事件。让我们把这个事件称为add。因此,我们组件的 JavaScript 代码将如下所示:

//add item component
Vue.component('add-item-component', {
  template: '#add-item-template',
  data: function () {
    return {
      newItem: ''
    }
  },
  methods: {
    addItem: function () {
      var text;

      text = this.newItem.trim();
      if (text) {
        this.$emit('add', this.newItem);
        this.newItem = '';
      }
    }
  }
});

当发出add事件时,应该以某种方式调用主组件的addItem方法。让我们通过将v-on:add修饰符附加到add-item-component调用,将add事件绑定到addItem

<add-item-component v-on:add="addItem" :items="items">
</add-item-component>

那好吧。正如您所看到的,这个方法与主组件的addItem方法几乎相同。它只是没有将newItem推送到items阵列。让我们修改主组件的addItem方法,使其只接收已处理的文本并将其推送到项目数组中:

new Vue({
  el: '#app',
  data: data,
  methods: { addItem: function (text) {
      this.items.push({
        text: text,
        checked: false
      });
    } }
});

我们完了!此练习的完整解决方案可在附录/第 3 章/vue 购物清单简单组件文件夹中找到。

练习 2

第 3 章组件——理解和使用中名为使用单文件组件重写购物清单应用的章节中,我们使用单文件组件对购物清单应用进行了很好的修改,但剩下的东西仍然很少。我们缺少两个功能:将项目添加到项目列表和更改标题。

为了实现第一个功能,我们必须从AddItemComponent发出一个事件,并将v-on修饰符附加到带有主App.vue组件的add-item-component调用,就像我们处理简单组件时所做的那样。您基本上可以复制并粘贴代码。

更改标题功能也是如此。我们还应该发出一个input事件,就像我们在简单组件示例中所做的那样。

不要忘记将样式添加到App.vue组件,使其看起来与以前一样。

检查附录/第 3 章/购物清单单文件组件文件夹中的完整代码。

总结

在本章中,您学习了如何使我们的应用可供所有人使用。您还学习了如何使用 Heroku 与 GitHub 存储库集成来部署它们。您还学习了如何在每次提交和推送时自动执行此操作。我们还使用 Travis 对每个部署进行自动构建。现在,我们的应用正在接受全面测试,并在每次提交更改时自动重新部署。祝贺

你可能认为这是旅程的终点。不,不是。这只是开始。在下一章中,我们将看到您可以从 Pomodoro 和 shopping list 应用中学到什么,以及接下来可以做些什么。跟我来!