Vue2.x-03使用vue-cli搭建Vue开发环境搭建好了开发环境,也看了下项目结构,接下来继续来分析下创建的项目吧。
Vue 实例启动入口 的是main.js ,那就先看看main.js吧
import Vue from 'vue'
import App from './App.vue'
new Vue({
el: '#app',
render: h => h(App)
})
Vue2必须通过 Render 方法来实现渲染 ,h => h(App) 这种写法其实是ES6的写法,当我们渲染的函数里只有一个参数的时候,可以通过 =>的方式来复制 ,等同于
render: function(h) {
return h(App);
}
分析main.js的代码可知,main.js完成的主要工作是: 通过 import 将一个 Vue .js 的组件文件引入,并创建一个 Vue 对象的实例,在 Vue 实例中用 Render 方法来绘制这个 Vue 组件( App )完成初始化。
el: '#app'
将 Vue 实例绑定到一个页面上,真实存在的元素 App Vue 程序就引导成功了。
打开 index.html 文件可以看到 Vue 实例与页面的对应关系
也就是说, 一个 Vue 实例必须与一个页面元素绑定。
我们通过脚手架为我们创建的这个 App 组件,其主要的结构如下:
<template>
<div id="app">
</div>
</template>
<script type="text/ecmascript-6">
export default{
name:'app'
}
</script>
<style></style>
主要有三部分组成:
Vue 的视图模板是基于 DOM 实现的,这意味着所有的 Vue 模板都是可解析的有效的HTML。比如我们在模板上定义一个标题,并通过数据绑定语法将App组件上定义的数据模型绑定到模板上。
首先,在组件脚本定义中使用 data 定义用于内部访问的数据模型:
export default{
....
data () {
return {
title: "artisan learn vue"
}
}
}
以上方式 data返回了 Object 对象的函数, 使用函数返回是为了可以具有更高的灵活性,例如对内部数据进行一些初始化的处理,推荐使用。
当然了,data也可返回一个对象属性,如下所示:
export default{
...
data : {
title: "artisan learn vue"
}
}
在模板中引用 data.title 数据时我们并不需要写上 data,这只是 Vue 定义时的一个内部数据容器,通过 Vue 模块的插值方式直接写上 title 即可
<h1>{{ title }}</h1>
用双大括号{{}}引住的内容被称为“Mustache ” 语法, Mustache 标签会被相应数据对象的 title 属性的值替换。每当这个属性变化时它也会更新。
插值是 Vue 模板语言的最基础用法,很多的变量输出都会采用插值的方式,而且插值还可以支持 JavaScript 表达式运算和过滤器。
从 Vue2 开始,组件模板必须且只能有一个顶层元素,如果在组件模块内设直多个顶层元素将会引发编译异常 。
在上述代码中 template 属性是 V,也就是视图, title 属性是 M,也就是模型。
举个例子,我们先约定一个数据模型来表述 Todo, 定义结构如下
{
value: '任务1', //待办事项的文字内容
done: false // 标记该事项是否已完成
}
由于是多个事项,那么这个数据模型应该是一个数组,为了能先显示这些待办事项,先设定一些样本数据。在 Vue 实例定义中的 data 属性中加入以下代码 :
export default {
data () {
return {
title : "TodoList",
todos: [
{
value:'任务一',
done:true
},
{
value:'任务二',
done:false
},
{
value:'任务三',
done:true
}
]
}
}
}
data干啥用的呢 ? 可以将 Vue 实例定义看作一个类的定义,data相当于这个类的内部字段属性的定义区域。在 Vue 实例内的其他地方可以直接用 this 引用data 内定义的任何属性,比如 this.title 就是引用了 data.title
要显示 todos 的数据就需要使用 Vue 模板的一个最常用 的 v-for 指令标记,它可以用于枚举一个数组并将对象渲染成一个列表.这个指令使用与 JS 类似的语法对 items 进行枚举,形式为 item in items
, items 是数据数组 , item 是当前数组元素的别名
<ul>
<li v-for="todo in todos">
<lable>{{ todo.value }}</lable>
</li>
</ul>
如果要输出待办事项的序号,可以用 v-for 中 隐藏的一个 index 值来进行输出,
<ul>
<li v-for="(todo,index) in todos" :id="index">
<lable>{{ index + 1 }}.{{ todo.value }}</lable>
</li>
</ul>
索引是由 0 开始计数的,要输出的序号应该从 1 开始,所以这里是index + 1.
这里除了用插值绑定,还使用了属性绑定语法,就是上面的:id="index"
,意思是将 index 的值输出到 DOM 的 id 属性上,如果没有在 id 前面加上“:”,那么 Vue 就会认为我们正在为 id属性赋予一个字符串。
v-for 不仅可以循环渲染数组,还可以渲染对象属性.
<li v-for="info in obj">
{{ info }}
</li>
data () {
return {
obj: {
name:"小工匠1",
sex:'男',
age:20
}
}
}
在 Vue 的代码中不推荐直接操作 DOM,并不像Jquery那样。 DOM 是被 Vue 直接托管的,所有“绑定”到 DOM 上的变量一旦发生变化, DOM 所对应的属性就会被 Vue 自动重绘而不需要像 jQuery那样通过编码来显式地操作,这才是绑定的意义所在。
没有样式的输出结果样子很丑,一般都是用 css 来美化. 这里我们使用less
Step1: 安装 webpack 支持 less 编译的包的方法:
npm i less style-loader css-loader less-loader - D
Step2: 安装完成后在 webpack.config.js 的 modules 设置内加入以下的配置:
{
test: /\.less$/,
loader:"style-loader!css-loader!less-loader"
}
Step3: 在/assets/中添加一个 todos.less 文件,并在 App.vue 的组件定义内引入 less 样式表
import './assets/todos.less'
export default{
.....
}
需要注意的是,不过这样引用是全局的。
Step4: 通过class使用样式
所有的待办事项都没有显示任何的状态,此时就需要使用 Vue的样式绑定功能了 。
将 done=true的待办事项绑定一个 checked 的样式类:
:class="{'checked':todo.done}"
完整代码如下
<li v-for="(todo,index) in todos" :class="{'checked':todo.done}">
<label>{{ index + 1 }}.{{ todo.value }}</label>
</li>
Vue 的属性绑定语法是通过 v-bind 实现的,完整的写法是这样
<li v-for="(todo,index) in todos" v-bind:class="{'checked':todo.done}">
但 v-bind 可以采用缩写方式“:”表示,采用完整写法又将出现各种重复,所以建议还是直接使用缩写方式,这样会更直观。
总结一下:
Vue 的属性绑定语法是 attribute=”expression”, attribute 就是元素接收的属性值(既可以是原生的也可以是自定义的) , expression 则是在 Vue 组件内由 data 或props性值(既可以是原生的也可以是自定义的),expression 则是在 Vue 组件内由 data 或 props
元素属性中必须加上: ,否则Vue认为是向这个属性赋上字符串值而不是Vue 组件上定义的属性引用
Vue 的样式绑定,无论绑定的是样式类还是样式属性,:class 和:style 表达式内 一定是一个 JSON 对象
:class 的 JSON 对象的值一定是布尔型的, true 表示加上样式, false 表示移除样式类
:style 的 JSON 对象则像是一个样式配置项, key 声明属性名, value 则是样式属性的具体值。
现在我们打算在待办事项的右侧增加一个时间字段 createTime,并用元素表示。
很明显,时间的输出的是一个整数,不是我们想要的结果。因为将 Date 对象直接输出的话, JavaScript 引擎会将其时间戳作为值输出 ,所以我们需要对这个时间戳进行格式化 。
这时候我们需要依赖先安装 moment.js , 先安装 moment.js :
npm i moment -S
Step1:引入 moment,并设定 moment 的区域为中国:
import moment from 'moment'
import 'moment/locale/zh-cn'
moment.locale('zh-cn')
Step2:加入一个 date 的过滤器:
filters:{
date(val){
return moment(val).calendar()
}
}
Step3:模板上应用这个过滤器:
<time>{{ todo.createTime | date }}</time>
在所有的过滤器中是没有 this 引用的,过滤器内的 this 是一个 undefined 的值,所以不要在过滤器内尝试引用组件实例内的变量或方法,否则会引发空值引用的异常 。
<template>
<div id="app">
<h1>{{ title }}</h1>
<ul class="todos">
<li v-for="(todo,index) in todos" :class="{'checked':todo.done}">
<label>{{ index + 1 }}.{{ todo.value }}</label>
<time>{{ todo.createTime | date }}</time>
</li>
</ul>
</div>
</template>
<script type="text/ecmascript-6">
import './assets/todos.less'
import moment from 'moment'
import 'moment/locale/zh-cn'
moment.locale('zh-cn')
export default {
name: 'app',
data () {
return {
title : "TodoList",
todos: [
{
value:'任务一',
done:true,
createTime:Date.now()
},
{
value:'任务二',
done:false,
createTime:Date.now() - 300000
},
{
value:'任务三',
done:true,
createTime:Date.now() + 300000
}
]
}
},
filters:{
date(val){
return moment(val).calendar()
}
}
}
</script>
<style>
</style>