Vue.js
是一个构建数据驱动的web界面的库。核心概念:插值语法、插值表达式、v-model双向绑定、监听器 $watch、计算属性computed、动态绑定class、动态绑定内联样式、指令、过滤器等
MVVM
1 | MVVM模式可以极大的简化我们开发的工作量 |
插值语法
- 语法
{{}}
实现将模型中的数据渲染到视图中 v-text='js环境'
渲染数据v-html='js环境'
可以将标签和数据渲染出来 注意: 写在里面的不需要{{}}
插值表达式
插值的语法的本质上是提供了一个js环境,在js环境中我们可以使用js表达式(变量,运算符,方法等),但不能写语句和if判断条件
1
2
3
4
5
6
7<div>{{msg.toUpperCase()}} {{width*height}}</div>
nue Vue({
data () {
return { msg: 'tew', width: 20, height: 2}
}
}
// <div>TEW 40</div>
表单元素的v-model双向绑定
使用v-model指令在表单 input、textarea及select元素上创建双向数据绑定,v-model的属性值是一个js作用域(一般用于表单元素中)
通过data属性实现数据模型到vue实例化对象的绑定(通过属性的特性实现)
通过v-model指令,实现视图到vue实例化对象的绑定(通过事件实现、input或change事件)
v-model在表单中的使用
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
31<div>
<!-- 文本框 v-model -->
<p>当行输入框: <input v-model="msg" /></p>
<!-- 多行文本(文本域) textarea 通过添加v-model属性实现文本域双向绑定 -->
<textarea v-model="multiMsg"></textarea>
<!-- 复选框 checkbox v-model绑定一个数组变量(多个复选框)或布尔值变量(单个复选框) -->
<input type="checkbox" v-model="fruitArr" value="apple">苹果
<input type="checkbox" v-model="fruitArr" value="banana">香蕉
<input type="checkbox" v-model="fruitArr" value="pear">梨
<!-- 单选框 v-model要设置同一个变量 -->
<input type="radio" v-model="sex" value="0">男
<input type="radio" v-model="sex" value="1">女
<!-- 下拉框 通过给select设置v-model属性实现下拉框双向绑定 -->
<select v-model="selectText">
<option v-for="option in options" :value="option:value">{{option.text}}</option>
</select>
</div>
<script>
new Vue({
data () {
return {
msg: '单行文本框',
multiMsg: '多行文本',
fruitArr: ['apple'],
sex: '1',
selectText: 'A',
options: [{ text: 'One', value: 'A'}, {text: 'Two', value: 'B'}]
}
}
})
</script>v-model修饰符
1
2
3
4// v-model默认在每次input事件触发后将输入框的值与数据进行同步
// v-model.number='' 输入内容转化为数值类型
// v-model.trim = '' 自动过滤(去除)用户输入的首尾空格
// v-mode.lazy='' 使用lazy修饰符后转化为change事件进行同步
监听器 $watch
$watch 用于观察Vue实例上的数据变动 回调函数得到的参数为新值和旧值
watch 一个对象,键是需要观察的表达式,值是对应回调函数。值也可以是方法名,或者包含选项的对象。
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// $watch 或 watch 值变化时才执行 加上 immediate:true 绑定之后立即执行handle
// deep:true 会遍历监听对象下所有属性开销较大时, 可以写成字符串监听对象具体的属性
// $watch
vm.$watch(
'a', // 监听的值 或 函数的计算结果
function(newval, oldVal){ // 回调函数
console.log(newVal+'--'+oldVal)
},
{
deep: true, // 深度监听对象内部值的变化
immediate: true // 立即执行回调函数
}
)
// watch
new Vue({
watch: {
a: {
handle () {
console.log(newVal+'--'+oldVal)
},
deep: true, //任何被侦听的对象的 property 改变时被调用,不论其被嵌套多深
immediate: true // 侦听开始之后被立即调用
}
}
})
计算属性 computed
在插值前对数据进行处理,vue提供了动态插值语法,允许在插值前调用一个函数来处理数据,动态函数要定义在computed属性中,属性值是一个对象,返回值就是插入视图中的数据
计算属性与methods普通方法好处: 计算属性中的计算结果会被缓存,多次使用时,计算属性只会调用一次。减少模板的复杂度,节省性能
计算属性依赖data数据只要有一个发生改变就会重新计算 计算的结果会被缓存 计算属性会挂载所在的实例上私有属性上 值是函数的返回值1
2
3
4
5
6
7
8
9
10
11
12
13
14
15// <li v-fot="(item, index) in limtList" :key="item">{{item}}</item>
nue Vue({
data () {
return { list: [1,2,3,4,5,6,7,8,9] }
}
computed: {
limtList () {
return this.list.filter(item => item > 7)
}
}
})
/*
<li>8</li>
<li>9</li>
*/
:class绑定HTML Class类
v-bind:class 简写 (:class) 动态的渲染元素上的类 只需要计算出表达式的最终的字符串 可以与普通的class特性共存
对象方式绑定类
1
2
3
4// 对象中的每个属性名称代表一个类的名称 属性值只能是布尔值
// true 表示保留这个属性类名 false 表示删除这个类名
// 属性中出现特殊字符 需要加上引号,
<div v-bind:class="{acitve: isActive, 'has-bg':hasBg}"></div>数组方式绑定类
1
2
3
4
5// 数组每个成员是变量,一旦加上引号就将变量转化成字符串 每个成员只能代表一个类
<div v-bind:class="[activeClass, errorClass]"></div>
<div v-bind:class="[isActive ? activeClass : '', errorClass]"></div>
// 数组语法中也可以使用对象语法:
<div v-bind:class="[{ active: isActive }, errorClass]"></div>
:style绑定内联样式
对象语法
1
2
3
4// CSS 属性名可以用驼峰式 (camelCase) 或短横线分隔 (kebab-case,记得用引号括起来) 来命名:
// 对象的属性名称 表示css的属性名称
// 对象的属性值 表示css的样式属性值
<div v-bind:style="{ color: textColor, 'font-size': fontSize + 'px' }"></div>数组语法
<div v-bind:style="[baseStyles, overridingStyles]"></div>
指令
指令(Directives)是特殊的带有前缀v-的特性.指令就是扩展html标签功能和属性的
v-once
只绑定一次 只渲染一次 保留在内存中 后续改变不会再渲染v-text 插值
<span v-text="msg"></span> 等同于 <span>{{msg}}</span>
v-html 避免html元素被编译
<div v-html="html"></div>
v-bind
动态地绑定一个或多个 attribute,或一个组件 prop 到表达式 可简写成:
1
2
3<img v-bind:src="imageSrc">
<img :src="imageSrc"> <!-- 缩写 -->
<my-component :prop="someThing"></my-component>v-model
在表单控件或者组件上创建双向绑定v-pre
跳过这个元素和它的子元素的编译过程v-cloak
可以隐藏未编译的 Mustache 标签直到实例准备完毕。1
2<div id='app' v-cloak><div>{{text}}</div></div>
<style>[v-cloak] { display: none }</style>v-show
切换元素的 display CSS 属性。v-show是简单的切换元素的CSS display属性, 有v-show的元素会始终渲染到并保持在dom中,只是隐藏了而已,不支持template, 也不支持v-else
<h1 v-show="isShow">Hello!</h1>
v-if
动态渲染一个元素1
2
3
4
5
6
7
8
9// v-if的属性值是true 会将这个元素渲染到页面中
// v-if的属性自是false 会将这个元素从页面中删除
// 切换多个元素,可以把多个元素放入template中,为其添加v-if指令,而最终的渲染结果并不会包含它
<div id='app'>
<template v-if="isShowDetail">
<sapn>姓名: tew</span>
<sapn>性别: 男</sapn>
</template>
</div>v-else
为 v-if 或者 v-else-if 添加“else 块”。v-else元素必须紧跟v-if或v-show元素的后面 否则它不能被识别
1
2
3
4
5
6<div v-if="Math.random() > 0.5">
Now you see me
</div>
<div v-else>
Now you don't
</div>v-else-if
注: v-if是真实的条件渲染,它会在切换当中销毁与重建条件块内的事件监听器和子组件,有更高的切换消耗. v-show只是简单的基于css切换,有更高的初始渲染消耗,如果需要频繁的切换 使用v-show更好,如果条件不大可能改变则用v-if
v-on
绑定事件监听器, 事件类型由参数指定 简写@
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
31
32
33
34
35
36
37<button v-on:click="doThis"></button>
// <!-- 内联语句 -->
<button v-on:click="doThat('hello', $event)"></button>
// <!-- 缩写 -->
<button @click="doThis"></button>
// <!-- 停止冒泡 -->
<button @click.stop="doThis"></button>
// <!-- 阻止默认行为 -->
<button @click.prevent="doThis"></button>
// <!-- 阻止默认行为,没有表达式 -->
<form @submit.prevent></form>
// <!-- 串联修饰符 -->
<button @click.stop.prevent="doThis"></button>
// <!-- 键修饰符,键别名 -->
<input @keyup.enter="onEnter">
// <!-- 键修饰符,键代码 -->
<input @keyup.13="onEnter">
// <!-- 阻止单击事件冒泡 -->
<a v-on:click.stop="doThis"></a>
// <!-- 提交事件不再重载页面 -->
<form v-on:submit.prevent="onSubmit"></form>
// <!-- 修饰符可以串联 -->
<a v-on:click.stop.prevent="doThat"></a>
// <!-- 只有修饰符 -->
<form v-on:submit.prevent></form>
// <!-- 添加事件侦听器时使用事件捕获模式 -->
<div v-on:click.capture="doThis">...</div>
// <!-- 只当事件在该元素本身(而不是子元素)触发时触发回调 -->
<div v-on:click.self="doThat">...</div>
// <!--只触发一次-->
<a v-on:click.once="doThis"></a>
// passive 会告诉浏览器你不想阻止事件的默认行为, 不用执行是否有preventDefault事件查询了
<div v-on:scroll.passive="onScroll">...</div
// 全部的按键别名:
// @keyup.enter="" .tab .delete .esc .space .up .down .left .right .ctrl .alt .shift .meta
// 给组件绑定事件 需要事件加修饰符 @click.native=’handleClick’
<Child @click.native='test'/>获取事件对象的两种方式
1
2
3
4
5
6
7
8
9
10
11
12// 方式一 带括号 固定参数 $event
// 如果带括号而不传$event参数 则获取不到事件对象event
<button @click="btnClick(1, $event)">事件对象1</button>
btnClick(a, ev) {
console.log(a)
console.log(ev)
}
// 方式二 不带括号
<button @click="btnClick">事件对象1</button>
btnClick(ev) {
console.log(ev)
}绑定多个事件处理程序
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18<!-- 方式一 使用逗号分隔多个事件处理程序 -->
<button @click="one($event), two($event)">
触发多个事件
</button>
<!-- 方式二 使用@xxx 和 v-on:xxx -->
<button @click="one" v-on:click="two">
触发多个事件
</button>
<script>
methods: {
one(event) {
console.log('one')
},
two(event) {
console.log('two')
}
}
</script>v-for
指令基于一个数组会对象来渲染一个列表。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16// v-for 也可以接受一个整数,此时他将重复数次
<div>
<span v-for="n in 3">{{ n }} </span>
</div>
// <span>1</span><span>2</span><span>3</span>
// items 是源数据数组 item 迭代元素的别名 index 当前迭代元素的索引
// 可以使用 of 替代 in 如 v-for="(item, index) of items"
// :key 提升循环显示的性能 表示唯一key属性 可以避免重用或重排 2.2.0+以后key是必须的
// 当v-for与v-if处于同一节点,v-for 的优先级比 v-if 更高,v-if // 将分别重复运行于每个 v-for 循环中,可实现渲染部分项节点
<ul id="example-1">
<li v-for="(item, index) in items" :key="item.message">
{{ item.message }}
</li>
</ul>
<div v-for="(val, key) of object"></div>
<div v-for="(val, name, index) of object"></div>
过滤器
过滤器可以用在两个地方:双花括号插值和v-bind表达式
在双花括号中
<div v-bind:id="rawId | formatId"></div> 在v-bind中
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21// {{ message | capitalize }}
// 全局过滤器
Vue.filter('capitalize', function (value) {
if (!value) return ''
value = value.toString()
return value.charAt(0).toUpperCase() + value.slice(1)
})
// 局部过滤器
new Vue({
filters: {
capitalize: function (value) {
if (!value) return ''
value = value.toString()
return value.charAt(0).toUpperCase() + value.slice(1)
}
}
})
// 多个过滤器 {{ message | filterA | filterB }}
// 表达式 message 的值将作为参数传入到函数A中处理完成。然后继续调用filterB,将 filterA 的结果传递到 filterB 中
// 过滤器参数 {{ message | filterA('arg1', arg2) }}
// filterA 被定义为接收三个参数的过滤器函数。其中 message的值作为第一个参数,普通字符串 'arg1' 作为第二个参数,表达式 arg2 的值作为第三个参数。
数组或对象值的更新问题
因为 JavaScript 的限制,Vue.js 不能检测到下面数组变化:不会触发视图更新
直接用索引设置元素,如 vm.items[0] = {};
修改数据的长度,如 vm.items.length = 0。
数组变异方法会触发试图更新push() pop() shift() unshift() splice() sort() reverse()
1
2
3
4
5
6
7
8
9
10
11
12
13// 改变数组或对象的某一项值时,试图未更新, 触发试图更新的方法如下
// 1. 改变数组或对象的引用 重新为其赋值
// 2. 使用数组的变异方法 或 对象拷贝 新对象替换老对象
vm = { list: [{id: '11', name: 'bob'},{id: '22', name: 'tom'}] }
vm.list.splice(1,1, {id: '33', name: 'tew'})
// { list:[{id: "11", name: "bob"}, {id: "33", name: "tew"}] }
// 新对象 替换 旧对象
obj = Object.assign({}, this.obj, { a: 1, e: 2 })
obj = {...this.obj, { a: 1, e: 2 }}
// 3. 使用 Vue.set()或者 vm.$set()
Vue.set(vm.list,'name','tew')
vm.$set(vm.list,'name','tew')
// 4. 使用 this.$forceUpdate() 强制组件重新渲染
props 参数校验 与非props特性
- props值方式一:
字符串数组,数组中的字符串就是传父组件传递的名称
- props值方式二:
对象,对象可以设置传递时的类型, 默认值,是否必须等
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24// 非props 特性
// 如果子组件没有用props接受 会报错
// 父组件的属性会展示在子组件最外层的元素属性中
// props参数校验
Vue.comonent('child', {
props: {
content: {
type: String, // String Number Boolean Array Object Date Function Symbol
required: false, // 必填
default: '默认值', // 字符串的默认值
validator(value){ // 自定义验证函数
return value.length > 5
}
},
person: {
type: Object,
// 对象或数组 默认值 必须从一个工厂函数获取
default: function (){
return {name: 'tew'}
}
}
}
template: '<div>{{person.name}}--{{content}}</div>'
})
Vue-cli2 脚手架
npm install vue-cli -g
安装 vue命令环境 脚手架工具 验证安装ok? vue –V- 生成项目模板
vue init <模板名> 本地文件夹名称 vue list 查看官方提供模板
模块名 webpack 大型项目 Eslint 检测代码规范 单元测试
webpack-simple simple browserify browserify-simple - 进入到生成目录里面 cd xxx npm install 安装项目依赖
- npm run dev 启动项目
注: 使用npm init 初始化项目的时候 路径不能有中文 不能有大写字母
vue-cli2 初始化项目过程
vue-cli2 项目目录结构