该篇为翻译文章:原文为:Intro to Vue.js: Vue-cli and Lifecycle Hooks

该系列文章目录:
Vue.js #1-渲染、指令、事件(原文)

Vue.js #2-组件、属性、Slots(原文)

Vue.js #3-Vue-cli及生命周期 (当前)

Vue.js #4-Vuex(原文)

Vue.js #5-动画(原文)

Vue-cli和构建

如果你没有读过上一篇「Vue.js #2-组件、属性、Slots」或者你不了解关于Vue组件、属性状态的一些东西,那么建议你最好回去补一下再来看这篇。

Vue提供了一个很好用的 cli工具。首先确保你已经安装了node,然后通过$ npm install -g vue-cli来进行全局安装vue-cli

有许多的构建工具可供选择,而在我们这里使用的是webpack,在命令行输入以下命令:

$ vue init webpack <project -name>

然后根据提示一步一步往下走:

Jietu20170303-151313

可以看到,最后它会让你通过npm run dev来开启开发测试环境,运行这个命令后,浏览器会自动打开localhost:8080,其实它是一个webpack dev server.

打开我们刚才生成的项目文件夹,你会看到/src/下面有一个App.vue文件,在/src/components下面有一个hello.vue文件。

现在,让我们来看一下这种扩展名为.vue的新型文件。在.vue文件当中,你可以写所有在组件当中你需要的东西。需要注意的是,我们不再需要在模板外面套上之前的<script type="text/x-template">标签了,现在我们一个文件模块可以这样来写:

<template>
  <div>
     <!-- Write your HTML with Vue in here -->  
  </div>
</template>

<script>
  export default {
     // Write your Vue component logic here
  }
</script>

<style scoped>
  /* Write your styles for the component in here */
</style>

这里有一些Vue在不同编辑器下的代码片段:vue-sublime-snippets,vue-snippets for atom,vscode-VueHelper

注意,Vue和React有一点是一样的,那就是你只能返回一个闭合的标签,可以看到上面,我返回了一个闭合的<div>。如果是SVG的话,我会把它们放到一个<g>当中。

我们在script当中使用export default来把我们的数据函数或者方法进行了导出。

另外,你会看到一个特殊的scoped属性加在了style标签上。这个属性可以让你随心所欲的写样式,因为它就是让你的样式只在这个组件当中起作用。如果把它去掉,那么你写的样式将会对整个应用当中起作用。我一般会把一些公用的样式放到App.vue普通的style标签里面,当然,这需要vue-style-loader的帮忙。而针对组件特有的样式,则使用<style scoped>

我觉得,.vue文件的这种通过把HTML、Styles和JS写在一起的方式非常的方便有效。因为基本上每一个模块都拥有这些东西,清晰明了。

下面是一个最基本的导入、导出组件的例子:

import New from './components/New.vue';

export default {
  components: {
    appNew: New
  }
}

让我们把上次的那个「酒瓶标签生成器」来改成一个更真实的例子:

App.vue:

<template>
  <div class="container">

  <main>
      <component :is="selected">
        <svg class="winebottle" aria-labelledby="title" xmlns="http://www.w3.org/2000/svg" viewBox="0 155 140 300">
          ...
      </svg>
      </component>
    </main>

    <aside>
      <h4>Name your Wine</h4>
      <input v-model="label" maxlength="18">
      <div class="button-row">
        <h4>Color</h4>
        <button @click="selected ='appBlack', labelColor = '#000000'">Black Label</button>
        <button @click="selected ='appWhite', labelColor = '#ffffff'">White Label</button>
        <input type="color" v-model="labelColor" defaultValue="#ff0000">
      </div>
    </aside>

  </div>
</template>

<script>
  import Black from './components/Black.vue'
  import White from './components/White.vue'
  ...
  export default {
      data: function () {
        return {
          selected: 'appBlack',
          label: 'Label Name',
          ...
        };
      },
      components: {
          appBlack: Black,
          appWhite: White,
          ...
      }
  }
</script>

<style>
  @import "./assets/style.css";
</style>

「黑」组件:

<template>
  <div>
    <slot></slot>
  </div>
</template>

<style scoped>
  .label {
    fill: black;
  }
  .bottle, .wine-text {
    fill: white;
  }
  .flor {
    fill: #ccc;
  }
  .bkimg {
    filter:url(#inverse)
  }
</style>

具体,请到GitHub上面进行查看:vue-wine-label

生命周期

在我们讨论「生命周期」之前,我们要来回顾一下「虚拟DOM」,我记得我在第一篇文章的时提到过「虚拟DOM」,但只是提了一下…

当你在使用类似于jQuery这类东西的时候,你一直是在跟DOM打交道,比如通过监听这些DOM的改变来改变其它的东西,总之,我们花了很多的时间在DOM身上。而「虚拟DOM」可以认为是DOM的抽象表现。在底层,它针对DOM使用数据的方式进行了一个复制,当检测到需要更新时,它会把新的「DOM数据」和旧的「DOM数据」(这里的DOM数据就是指虚拟DOM)进行对比,如果不同,那么才会根据这些不同对真实的DOM进行更新。而在Vue当中,则是检测它内部的数据状态来进行后续操作。

译者:关于「虚拟DOM」,原文和我上面的翻译说的也不是特别清楚,所以这里推荐一篇网友写的文章,「深度剖析:如何实现一个 Virtual DOM 算法」

Vue在它的生命周期的不同阶段提供了不同的方法来供我们使用。比如:beforeCreate, created, beforeMount, mounted, beforeUpdate, updated, activated, deactivated, beforeDestroydestroyed,详情请到官方文档查看。下面,我们来举一个小例子(观察console):

const Child = {
  template: '#childarea',
  beforeCreate() {
    console.log("beforeCreate!");
  }, 
 ...
};

new Vue({
  el: '#app',
  data() {
    return {
      isShowing: false 
    }
  },
  methods: {
    toggleShow() {
      this.isShowing = !this.isShowing;
    }
  },
  components: {
    appChild: Child
  }
});

<div v-if="isShowing">
  <app-child></app-child>
</div>

结果:http://codepen.io/sdras/pen/28d3a5b277ada8f9d1b0b34a2d73831c

lifecycle

注意,我们使用v-if代替了v-show,因为v-if是真正的把组件「安装」和「卸载」掉,而v-show只是控制组件是否可见,并没有真正的「安装」和「卸载」。

就像组件当中的其它方法一样,生命周期方法也会自动的绑定组件的this。正是因为这个,你不应该对生命周期方法使用箭头函数的方式(这里如果你不懂的话,可以看 一起学习ES2015(ES6入门)-「箭头函数」一文)。

下面这个例子当中,每个组件在被加载的时候都会很加入很多元素,所以每次加载组件的时候都会触发对应的动画:Vue Weather Notifier

 mounted() {
    let audio = new Audio('https://s3-us-west-2.amazonaws.com/s.cdpn.io/28963/rain.mp3'),
        tl = new TimelineMax();

    audio.play();
    tl.add("drops");

    //drops in
    tl.staggerFromTo("#droplet-groups g path", 0.3, {
      drawSVG: "0% -10%"
    }, {
      drawSVG: "100% 110%",
      repeat: 3,
      repeatDelay: 1,
      ease: Sine.easeIn
    }, 0.5, "drops");
 …
}

例子当中使用了像<transition></transition><transition -group>这样的动画组件,关于动画我们在后面会讲的。