Vuejs上手

前段时间用Vue写了一个 todo list ,发现Vue确实是一个上手简单,可以很快搭建一个webapp的前端框架。今天先来简单的介绍一下vuejs,过几天如果有空再来解析一下那个todo list。

使用vue-cli创建项目

在开始之前,要安装nodejs环境

首先,将vue-cli安装至系统全局目录:

1
$ npm install -g vue-cli

然后使用vue-cli创建一个新的项目,这里我们选择官方提供的webpack模板:

1
$ vue init webpack vue-todo

在安装过程中,会依次要求你输入项目名、介绍、作者等内容。这里需要注意的是项目名称中不能有大写。之后会让你选择是否安装一些插件,例如vue-routerESLint之类的。在这里你需要多页面路由则在Install vue-router选项中选择YES,其他全部选NO即可。

安装完成后,按照屏幕上的指令,以此执行cd vue-todonpm inpm run dev就可以在本地服务的8080端口中运行你新建的项目了。

当然大家都知道我们的8080端口经常被tomcat占用,所以如果有冲突的话可以在config/index.js文件中修改dev.port为自己想要的端口。另外,在使用npm run build命令生成生产环境的文件时,可以在build.assetsPublicPath中指定项目的URL根目录。

在哪里写代码

使用vue-cli创建了新的项目后,我们可以在src文件夹中发现App.vue这个文件。打开App.vue,可以看到它向html一样定义了三个标签: <template></template><script></script><style></style>

template

template标签用来写我们当前组件的html模板,里面的语法和html是一致的但是要注意,template中只能有一个根标签。

script

script标签里面的内容和我们平时写在.html文件中的js不大一样。我们往里面写的应该是模块化的js。使用import from来导入一个模块,使用 export default { /* vue实例 */} 来导出当前这个模块。这一点可能刚接触vue或者js的人比较难以理解。这也是为什么我觉得看React的JSX语法更爽的原因,因为ReactJSX写的更像模块化的js,而不是vue这样的xml中套js

export default { /* vue实例 */}中,我们会使用vue的一些已经定义好的对象,例如data()methodsprops等。只需要往里面填入我们自己项目会用上的内容即可。

style

style标签顾名思义,就是放那些css文件,在这里我就不再多赘述。

一些最常用的东西

声明式渲染

这是vue最核心的内容之一。官方介绍是

允许采用简洁的模板语法来声明式的将数据渲染进 DOM

例如我们现在打开src/app.vue,在templetescript标签中分别声明:

1
2
3
4
5
6
7
8
9
10
11
12
<template>
<h1>{{message}}</h1>
</template>
<script>
export default {
data() {
return {
message: 'Hello World '
};
}
}
</script>

即可将data中的message内容填充到h1中去。

这里要特别注意的是,data是一个方法而并非一个对象

另外,除了文本差值,我们还可以使用v-bind方式绑定 DOM 元素属性,例如

1
2
3
4
5
6
7
8
9
10
11
12
<template>
<input v-bind:placeholder="placeholder"></input>
</template>
<script>
export default {
data() {
return {
placeholder: 'Hello World '
};
}
}
</script>

即可当input框中的placeholder属性绑定为Hello World。在代码中我们可以将v-bind:简写成:

如果要自定义控制class属性,也可以使用v-bind方法。例如

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<template>
<span :class="{highlight: isImportant}"></span> /* class="highlight" */
<span :class="class"></span> /* class="className" */
<span :class="[{highlight: isImportant}, class]"></span> /* class="hightlight className" */
</template>
<script>
export default {
data() {
return {
isImportant: true,
class: 'className'
};
}
}
</script>

详情参见vue官方文档 Class与Style绑定

表单和应用间的双向数据绑定

我们使用v-model属性来完成表单输入和应用状态间的双向绑定。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<template>
<div>
<p>{{ message }}</p>
<input v-model="message">
</div>
</template>
<script>
export default {
data() {
return {
message: 'Hello World '
};
}
}
</script>

当你更改input中的内容时,data中的message也会随之改变。

事件监听

我们在写html + javascript 代码时,会使用onclick等属性来完成对DOM事件的监听处理。在vue中,我们使用v-on属性来完成。我们可以在methods对象中新建方法,使用this可以访问当前组件中data里的对象。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<template>
<div>
<p>{{ message }}</p>
<button v-on:click="printMessage">打印消息</button>
</div>
</template>
<script>
export default {
data() {
return {
message: 'Hello World '
};
},
methods: {
printMessage(){
console.log(this.message);
}
}
}
</script>

v-on:可以简写为@

###循环和条件 我们使用v-for属性来循环输出DOM。用v-if属性来控制是否渲染某DOM。在下面的实例中,会循环输出前3句话。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<template>
<div>
<ol>
<li v-for="todo in todos" key="todo.index" v-if="todo.hidden">
{{ todo.text }}
</li>
</ol>
</div>
</template>
<script>
export default {
data() {
return {
todos: [
{ index: 1, text: '我爱学习', display: true },
{ index: 2, text: '学习使我快乐', display: true },
{ index: 3, text: '优秀是一种习惯', display: true },
{ index: 4, text: '学习使我更优秀', display: false }
]
};
}
</script>

此外,使用v-show属性也可以控制是否将某DOM展示出来。它与v-if属性用法一样,但是仍会将DOM渲染出来,只是加了display: hidden样式。

##组件

这是前端框架最重要的优势之一。我们可以将页面拆分成一个个vue组件,然后把他们按照不同的需要组合起来。例如,我已经写了一个Hello组件,可以在页面中渲染一句Hello World出来。我们的引入方式是:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<template>
<div>
<hello></hello>
<h1>{{ message }}</h1>
</div>
</template>
<script>
import Hello from './components/Hello.vue'
export default {
components: {
Hello
},
data() {
return {
message: 'this text randered on this page'
};
}
}
</script>

注意,components不是一个数组。另外,在template中,所有驼峰式的组件名会自动转换成减号式的命名,并作为标签引入。

父组件使用v-bind向子组件传递参数。子组件使用props对象来接受参数。父组件用v-on来接受子组件传来的事件,并用methods中定义的方法来处理,子组件用methods中定义的方法调用this.$emit(functionName[, arg])来传递事件和参数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
// father
<template>
<div id="father">
<hello :todos="todos" @finished="handleFinished(item)"></hello>
</div>
</template>
<script>
import Hello from './components/Hello.vue'
export default {
name: 'App',
components: {
Hello
},
data() {
return {
todos: [
{ index: 1, text: '我爱学习', finished: false },
{ index: 2, text: '学习使我快乐', finished: false },
{ index: 3, text: '优秀是一种习惯', finished: false },
{ index: 4, text: '学习使我更优秀', finished: false }
]
};
},
methods: {
handleFinished(item) {
item.finished = !item.finished;
}
}
}
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// child
<template>
<div id="child">
<ul>
<li v-for="item in todos" key="item.index" @click="handleFinished(item)"> {{ item.text }} </li>
</ul>
</div>
</template>
<script>
export default {
name: 'hello',
props: [
'todos'
],
methods: {
handleFinished(item){
this.$emit('handleFinished', item);
}
}
}
</script>

注意,props字符串数组this.$emit中第一个参数是父组件中定义来接受这个事件的方法名字符串

计算和监视

使用在computed定义计算方法,用来对data中的属性进行一些比较简单的计算。例如我们可以用下面的方式让h1只在message有内容时显示。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<template>
<h1 v-if="ifMessage">{{message}}</h1>
</template>
<script>
export default {
data() {
return {
message: 'Hello World '
};
},
computed: {
ifMessage(){
return (this.message.length == 0)
}
}
}
</script>

watch中加入要监视的data中的内容,可以帮助我们在内容改变时完成一些动作。下面的例子中,当message的值改变时,就会自动打印出来。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<template>
<div>
<p>{{ message }}</p>
<input v-model="message">
</div>
</template>
<script>
export default {
data() {
return {
message: 'Hello World '
};
},
watch: {
message(){
console.log(this.message)
}
}
}
</script>

要注意,如果监听的对象是一个对象数组之类的东西,记得这么定义:

1
2
3
4
5
6
7
8
watch: {
message: {
handler(){
//do something
},
deep: true
}
}

嗯,今天就先写这么多,很多详细的方法可以参考vue的官方入门指南中的介绍页面。 哦对了,如果你不想那么麻烦的新建一个vue项目,你可以选择在html中用