Vue学习笔记
基本介绍
对象属性配置表
Vue生命周期
Vue语法
插值绑定
- 1
只要使用双大括号(Mustache语法)将要绑定的变量、值、表达式括住就可以实现,Vue将会获取计算后的值,并以文本的形式将其展示出来。 - 2
无论变量、表达式、执行函数还是DOM代码,Vue都只能将结果当作文本处理。另外,若是插值绑定的内容是变量或与变量有关,当变量的值改变时,视图也会同步更新。 - 3
HTML插值可以动态渲染DOM节点。
语法:v-html="变量名“
属性绑定
- 1
指令 v-bind,DOM节点的属性基本都可以使用指令v-bind进行绑定。
省略缩写为 " :"
属性也可以绑定变量、表达式、执行函数等内容,但是都应该满足属性自身约束。 - 2
类名样式绑定:类名实际是由数组拼接而成,样式则是由对象键值对拼接而成。所以在Vue中,二者的绑定机制不同。
- 2.1
类名的动态绑定:
可以通过字符串、数组、对象三种方式为节点动态绑定类名属性。
<script type="text/javascript">
let vm = new Vue({
el:"#app",
data(){
return{
classStr:'color-gray size-18 style-italic', //拼接字符串
classArr:['color-gary', 'size-18', 'style-italic'], //数组
classObj1:{ //对象,绑定类名
'color-gray': true,
'size-18': true,
'style-italic': true
},
classObj2:{ //对象,未绑定类名
'color-gray': 0,
'size-18': '',
'style-italic': false
}
} //return
} //data
})
</script>
JS中的真假值问题:
当变量的值为 undefined、 null、 值为0的数字、空字符串(’ ')时,会判定为 false (假);
除一般值外,[ ]、 { }、 -1、 -0.1 会判定为 true(真)。
- 2.2
样式的绑定:
绑定样式的方式与类名相似,但是样式是以键值对的形式,所以不能像类名一样使用数组进行绑定。
<script type="text/javascript">
let vm = new Vue({
el:"#app",
data(){
return{
styleStr:'color: gray; font-size: 18px; font-style: italic;', //拼接字符串
styleArr:['color-gary', 'size-18', 'style-italic'], //数组
styleObj1:{ //对象,绑定样式
'color-gray': -1 ? 'gray' : 'black',
'size-18': '18px',
'style-italic': 'italic'
},
styleObj2:{ //对象,未绑定样式
'color-gray': 0 ? 'gray' : '',
'size-18': '' ? '18px' : '',
'style-italic': null ? 'talic' : ''
}
} //return
} //data
})
</script>
事件绑定
- 1
指令 v-on ,可以监听DOM事件,可以听过 v-on 指令将事件绑定到 DOM 节点上;
简写形式为: @
例如:
<button v-on:click="logInfo()">点击</button>
<button @click="logInfo()">点击</button>
获取事件对象:
<div id="app">
<!-- 1. 在事件函数不必传参时,可以这样写, 注意:不能带 () -->
<input type="text" @keyup="handleKeyUp">
<br>
<!-- 2. 手动传入 $event 对象 -->
<input type="text" @keyup="handleKeyUp($event)">
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.11"></script>
<script type="text/javascript">
let vm = new Vue({
el: "#app",
methods: {
handleKeyUp(event) {
console.log(event.key, event);
}
},
})
</script>
获取event对象:
- 2 常见修饰符
Vue将JS中处理DOM事件时常见的方法封装成简短易用的事件修饰符,可以后缀于事件名称之后。
例如:.prevent修饰符在表单提交时的表现。
<div id="app">
<!-- <form @submit="handleSubmit">
<h2>不使用修饰符时</h2>
<button type="submit">提交</button>
</form> -->
<form @submit.prevent="handleSubmit">
<h2>使用.prevent修饰符时</h2>
<button type="submit">提交</button>
</form>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.min.js"></script>
<script type="text/javascript">
let vm = new Vue({
el: '#app',
data () {
return {
counter: 0
}
},
methods: {
handleSubmit () {
console.log(`submit ${++this.counter} times`)
}
}
})
</script>
不使用 .prevent 修饰符:
多次点击”提交“按钮,控制台均是一闪而过打印信息,之后呈现空白。原因是因为当未指定form表单时,表单会被提交到当前的URL,对应的表现就是页面被重新加载。使用 .prevent 修饰符:
点击“提交”按钮之后,页面没有被重载。
注意: 当事件后缀多个修饰符时,要注意排列顺序,相应的代码会根据排列顺序依次产生。
- 3 按键修饰符
对于键盘事件,Vue允许将按键键值作为修饰符来使用。
<!-- 监听键盘事件 -->
<input type="text" @keyup.13="console.log($event)"> //使用按键键值
<input type="text" @keyup.enter="console.log($event)"> //使用按键别名,事件对象属性中的 key 值(不区分大小写)
鼠标事件修饰符:
修饰符 | 可用版本 | 对应按键 |
.left | 2.2.0 以上 | 左键 |
.right | 2.2.0 以上 | 右键 |
.middle | 2.2.0 以上 | 中键 |
- 4 组合修饰符
Vue提供了组合修饰符的机制,不过其必须配合系统按键修饰符方可生效。
例如:
<div id="app">
<h1 @click.ctrl="logWithCtrl" @click="logSingle">没有ctrl别来点我</h1>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.min.js"></script>
<script type="text/javascript">
let vm = new Vue({
el: '#app',
methods: {
logSingle (event) {
if (!event.ctrlKey) {
console.log('------------- 分割线 -------------')
console.log('$event.ctrlKey:', event.ctrlKey)
console.log('logSingle 点击事件!')
} else {
console.log('不错,进步很快呀!')
}
},
logWithCtrl (event) {
console.log('------------- 分割线 -------------')
console.log('$event.ctrlKey:', event.ctrlKey)
console.log('logWithCtrl 组合事件!')
}
}
})
</script>
第一次,使用鼠标点击节点,此时的事件对象的 ctrlKey 值为 false ,控制台 只打印了鼠标点击事件 的信息;
第二次,按住 Ctrl 键再次点击节点,此时事件对象的 ctrlKey 值为 true ,控制台 先打印了组合事件 的信息,之 后打印了鼠标点击事件 的信息。
综合结果发现,当 Ctrl 键被按下时,事件对象的 ctrlKey 的值被设为 true ;当鼠标点击事件触发时,若 ctrlKey 的值为 true ,则执行组合事件代码。
双向绑定
- 1 指令 v-model
v-model 和 v-show 是Vue的核心功能中内置的,开发者 不可自定义 的指令。
可以使用 v-model 为可输入元素(input & textarea)创建双向数据绑定,它会根据元素类型自动选取正确的方法来更新元素。
注意: v-model 会忽略所有表单元素的 value、checked、selected attribute 的初始值而 总是将 Vue 实例的数据作为数据来源 。你应该通过 JavaScript 在组件的 data 选项中声明初始值。
例如:
<div id="app">
<h3>单行文本框</h3>
<input type="text" v-model="singleText" style="width: 240px;">
<p>{{ singleText }}</p>
<h3>多行文本框</h3>
<textarea v-model="multiText" style="width: 240px;"></textarea>
<pre>{{ multiText }}</pre>
<h3>单选框</h3>
<!--
由于点击被选中的单选项无法取消其被选中状态,所以实战中基本没有使用单个单选项的场景。
这里,设置v-model共用同一个变量(radioValue)可实现RadioGroup的效果
-->
<input id="ra" type="radio" value="杨玉环" v-model="radioValue">
<label for="ra">A.杨玉环</label>
<input id="rb" type="radio" value="赵飞燕" v-model="radioValue">
<label for="rb">B.赵飞燕</label>
<p>{{ radioValue }}</p>
<h3>单个复选框</h3>
<!-- 单个复选框被用于true和false的切换 -->
<input id="c" type="checkbox" v-model="toggleValue">
<label for="c">天生丽质</label>
<p>{{ toggleValue }}</p>
<h3>多个复选框</h3>
<!-- 多个复选框, v-model接收数组类型变量 -->
<input id="ca" type="checkbox" value="漂亮" v-model="checkedValues">
<label for="ca">A.回眸一笑百媚生</label>
<input id="cb" type="checkbox" value="瘦弱" v-model="checkedValues">
<label for="cb">B.体轻能为掌上舞</label>
<input id="cc" type="checkbox" value="得宠" v-model="checkedValues">
<label for="cc">C.三千宠爱在一身</label>
<p>{{ checkedValues.join(',') }}</p>
<input type="checkbox" value="铁斧头" v-model="checks">铁斧头
<input type="checkbox" value="金斧头" v-model="checks">金斧头
<input type="checkbox" value="银斧头" v-model="checks">银斧头
<br>
<br>
樵夫选择了---{{checks}}
<br><br>
<!-- 复选框控制选中和未选中的值, 绑定true-value, false-value属性 -->
<!-- 这里的 true-value 和 false-value attribute 并不会影响输入控件的 value attribute,因为浏览器在提交表单时并不会包含未被选中的复选框。 -->
<input type="checkbox" v-model="toggle" :true-value="value_1" :false-value="value_2"><br>
toggle的值是---{{toggle}}
<br>
选中---{{toggle===value_1}}
<br>
未选中---{{toggle===value_2}}
<br>
<h3>单项下拉选择框</h3>
<!-- v-model一定是绑定在select标签上 -->
<!-- 在select标签上绑定value值对option并没有影响 -->
<select name="" id="" v-model="singleSelect">
<option value="">请选择</option>
<!-- 如果没有设置 value 则 option 节点的文本值会被当作 value 的值 -->
<!-- 如果 v-model 表达式的初始值未能匹配任何选项,<select> 元素将被渲染为“未选中”状态 -->
<option value="汉代">汉代</option>
<option value="">唐代</option>
<option value="">宋代</option>
</select>
<p>{{ singleSelect }}</p>
<h3>多项下拉选择框</h3>
<!-- 如果是多选,就需要v-model来配合value使用,v-model绑定一个数组,与复选框类似 -->
<!-- 注意: v-model一定是绑定在select标签上 -->
<select name="" id="" multiple v-model="multiSelect" style="width: 100px;">
<!-- 按住 ctrl 键,可执行多选 -->
<option value=1>出身傲寒</option>
<option value=2>饱受争议</option>
<!-- 把值绑定到 Vue 实例的一个动态 property 上,这时可以用 v-bind 实现,并且这个 property 的值可以不是字符串。 -->
<option :value="3">结局悲凉</option>
</select>
<p>{{ multiSelect.join(",") }}</p>
<h3>单选按钮</h3>
<div id="">
<input type="radio" id="one" value="One" v-model="picked">
<label for="one">One</label>
<br>
<input type="radio" id="two" value="Two" v-model="picked">
<label for="two">Two</label>
<br>
<span>Picked: {{ picked }}</span>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.min.js"></script>
<script type="text/javascript">
let vm = new Vue({
el: '#app',
data() {
return {
singleText: '',
multiText: '',
radioValue: '',
toggleValue: false,
checkedValues: [],
//根据 value 设置默认选项
singleSelect: '汉代',
multiSelect: [1, 3],
picked: '',
// 使用字符串时同时全部选中并显示 true 未选中则显示 false
checks: "",
//使用绑定数组时可以任意选中,并且显示 value 值
// checks:[]
toggle: false,
value_1: '被选中',
value_2: '未被选中'
};
}
})
</script>
- 2 v-model 与修饰符
例如:
<input type="text/javascript" v-model.trim.number="text" @keyup="handelKeyUp">
- 3 v-model 与自定义组件
<div id="app">
<!-- 自定义组件v-model -->
<custom-screen v-model="text"></custom-screen>
<br>
<!-- 原生元素v-model -->
<input type="text" v-model="text">
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.min.js"></script>
<script type="text/javascript">
Vue.component('custom-screen', {
// 使用value属性接收外部传入的值
props: ['value'],
methods: {
handleReset() {
console.log('重置为\'\'');
// 使用$emit发送input事件,并将目标值作为参数传出
this.$emit('input', '');
}
},
template: `
<div>
<h2>输入值为: {{ value }}</h2>
<button @click="handleReset">重置为空</button>
</div>
`
})
let vm = new Vue({
el: '#app',
data: () => ({
text: ''
})
})
</script>
value 属性用于 接收外部传入的值 以更新组件内部状态;
input 事件由开发者决定什么时候调用,并负责 将组件内部的状态同步到外部 。
条件渲染与列表渲染
- 1 指令 v-if 与 v-show
v-if 、v-else 、v-else-if。其中,v-else 、v-else-if 只能与 v-if 配合使用。使用它们可以对视图实现条件渲染。
v-show 也可以用于实现条件渲染,但是它只是简单地切换元素的 CSS 属性:display 。当条件判定为**假(false)**时,元素地 display 属性将被赋值为 none ; 反之,元素地 display 属性将被恢复为原有值。
但是,v-show 并不能算是真正地条件渲染,因为挂载它的多个元素之间没有条件上下文关系。
v-show 与 v-if对比:
<div id="app">
<h2 v-show="visible">v-show, visible = true</h2>
<h2 v-show="!visible">v-show, visible = false</h2>
<h2 v-if="visible">v-if, visible = true</h2>
<h2 v-else>v-if, visible = false</h2>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.min.js"></script>
<script type="text/javascript">
let vm = new Vue({
el: '#app',
data () {
return {
visible: false
}
}
})
</script>
由图中可以看到,v-show 判定为假的元素的 display 属性被赋值为 none ,但是其仍然保留在 DOM 中。
而 v-if 判定为假的元素则不会出现在 DOM 中。
注意:
a. v-if 会在切换中将组件上的事件监听器和子组件销毁和重建。当组件被销毁时将无法被任何方式获取,因为它已经不存在于DOM中;
b. 在创建父组件时,若是子组件的 v-if 被判定为假时,Vue在直到其第一次判定为真前都不会对子组件做任何事情;这在使用Vue生命周期钩子函数的时要尤为注意,若是生命周期已经走过了组件的创建阶段,却仍然无法获取组件对象,则需要思考是不是 v-if 的原因;
c. v-if 有更高的切换开销, v-show 有更高的初始渲染开销;这都与它们的实现机制有关。(即,v-if 初始渲染速度快,但是切换速度慢;v-show 初始渲染速度慢,但是切换速度快,初始时需要加载所有元素,但是修改时只需要修改display 样式即可。)
d. v-show 不支持 template 元素.
- 2 指令 v-for , 列表渲染
v-for 用于实现列表渲染, 可以使用 item in items 或者 item of items 的语法.
v-for 还可以渲染一个对象的键值对.
<div id="app">
<h2>用户列表</h2>
<ul>
<!-- index作为第二个参数,用以标识下标 -->
<li v-for="(user, index) in users">
用户{{ index + 1 }}
<ul>
<!-- key作为第二个参数,用以标识键名 -->
<li v-for="(value, key) of user">{{ key }}: {{ value }}</li>
</ul>
</li>
</ul>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.min.js"></script>
<script type="text/javascript">
let vm = new Vue({
el: '#app',
data() {
return {
users: [{
name: 'Clark',
age: 27,
city: 'Chicago'
},
{
name: 'Jackson',
age: 28,
city: 'Sydney'
}
]
}
}
})
</script>
- 3 数据的响应式表现
Vue 会把数组当作观察者加入响应式系统中,当调用一些方法修改数组时,对应的视图会同步更新。
例如:(这是一个用到了 push() 和 reverse() 方法的实例)
<div id="app">
<h2>用户列表</h2>
<button @click="createUser">创建用户</button>
<button @click="reverse">倒序数组</button>
<ul>
<!-- index作为第二个参数,用以标识下标 -->
<li v-for="(user, index) in users">
用户{{ index + 1 }}
<ul>
<!-- key作为第二个参数,用以标识键名 -->
<li v-for="(value, key) of user">
<strong style="display: inline-block;width: 60px;">{{ key }}:</strong>
<span>{{ value }}</span>
</li>
</ul>
</li>
</ul>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.min.js"></script>
<script type="text/javascript">
let vm = new Vue({
el: '#app',
data () {
return {
users: []
}
},
methods: {
random (factor, base) {
// 根据乘积因子和基数生成随机整数
// 使用Math.floor(Math.random())去获取你想要的一个范围内的整数。
// Math.random()*3.99 + 3 //现在这个数就 >=3 且 <(3.99+3) 再使用Math.floor取整(其余同理)
return Math.floor(Math.random() * (factor || 1)) + (base || 0)
},
createUser () {
// 获取 name 大写首字母
let fLetter = 'BJHK'[this.random(3.999)]
// 随机截取 name 字符串
let nameStr = 'abcdefghijklmnopqrstuvwxyz'
let bLetters = nameStr.substr(this.random(19.999), this.random(3.999, 3))
let user = {
name: fLetter + bLetters,
age: this.random(5.999, 25),
city: ['Chicago', 'Sydney', 'ShenZhen', 'HangZhou'][this.random(3.999)]
}
console.log('--------------- 创建用户 ---------------\n', user)
this.users.push(user)
},
reverse () {
console.log('--------------- 倒序列表 ---------------')
console.log('Before:', this.users.map(user => user.name))
this.users.reverse()
console.log('After:', this.users.map(user => user.name))
}
}
})
</script>
注意:
a. Math.floor() 返回小于或等于一个给定数字的最大整数。
Note: Math.floor() === 向下取整 ;
b. Math.random() 函数返回一个浮点, 伪随机数在范围从0到小于1,也就是说,从0(包括0)往上,但是不包括1(排除1),然后您可以缩放到所需的范围。
例如:*Math.random()52 + 1 //现在这个数就 >=1 且 <53,再使用Math.floor 取整 *Math.floor(Math.random()52 + 1)
- 4 列表渲染中的 key
当列表渲染被重新执行时(数组内容发生改变)时,若是不使用 key 的话,Vue会为数组成员 就近复用 已存在的DOM节点。
使用 key 时,Vue会根据 key 的变化重新排列节点顺序,并将移除 key 不存在的节点。