该篇为翻译文章:原文为:Intro to Vue.js: Vue-cli and Lifecycle Hooks
该系列文章目录:
Vue.js #1-渲染、指令、事件(原文)Vue.js #3-Vue-cli及生命周期 (当前)
Vue-cli和构建
如果你没有读过上一篇「Vue.js #2-组件、属性、Slots」或者你不了解关于Vue组件、属性状态的一些东西,那么建议你最好回去补一下再来看这篇。
Vue提供了一个很好用的 cli工具。首先确保你已经安装了node,然后通过$ npm install -g vue-cli
来进行全局安装vue-cli
。
有许多的构建工具可供选择,而在我们这里使用的是webpack,在命令行输入以下命令:
$ vue init webpack <project -name>
然后根据提示一步一步往下走:
可以看到,最后它会让你通过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
, beforeDestroy
和 destroyed
,详情请到官方文档查看。下面,我们来举一个小例子(观察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
注意,我们使用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>
这样的动画组件,关于动画我们在后面会讲的。