类似于 Vue.js
这种前端框架,提倡的是减少开发人员对 DOM 的直接操作,而是只关心对数据的操作,不用关心 DOM 元素的渲染。
v-cloak、v-text、v-bind、v-on 和 v-html
v-cloak
:用于解决差值表达式闪烁问题v-text
:没有闪烁问题的,会覆盖元素中原本的内容,但是插值表达式 只会替换自己的这个占位符,不会把整个元素的内容清空v-html
:能够渲染html
标签元素,而不是将其当做字符串渲染v-bind
:用于绑定属性v-on
:绑定事件
示例:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<style>
/*v-cloak 需要指定 css 属性,即在渲染完成之前隐藏标签元素*/
[v-cloak] {
display: none;
}
</style>
</head>
<body>
<div id="app">
<p v-cloak>{{ msg }}</p> <!--{{ }} 即为插值表达式-->
<p v-text="msg">===</p>
<p v-html="msg2"></p>
<input type="button" v-bind:title="mytitle" value="按钮">
<input type="button" value="按钮" v-on:click="show">
</div>
<script src="./lib/vue-2.4.0.js"></script>
<script>
var vm = new Vue({
el: '#app',
data: {
msg: '123',
msg2: '<h1>标题一</h1>',
mytitle: '自定义title'
},
methods: {
show: function() {
alert('Hello v-on!')
}
}
})
</script>
</body>
</html>
v-on 和 跑马灯效果
效果:前后循环
步骤:
- 截取第一个字符,和后面的字符,进行后前拼接,实现前面的在后面,后面的在前面
- 开启定时器,循环跑
- 关闭定时器
知识点:
v-on
:绑定点击事件substring
:字符串截取- 定时器实现循环
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<div id="app">
<input type="button" value="运行" @click="run">
<input type="button" value="停止" @click="stop">
<h4>{{ msg }}</h4>
</div>
<script src="./lib/vue-2.4.0.js"></script>
<script>
var vm = new Vue({
el: '#app',
data: {
msg: '猥琐发育,别浪!!',
intervalId: null, // 计时器 ID
},
methods: {
// 运行事件,截取字符串
run() {
// 若 定时器 ID不为 null,说明是不是重新开始的计时器,直接返回,不需要重新开启一个新的计时器
if (this.intervalId !== null) return;
// 箭头函数中没有 this,即函数内的 this 和函数外的 this 一致
this.intervalId = setInterval(()=>{
var start = this.msg.substring(0, 1);
var end = this.msg.substring(1);
this.msg = end + start;
}, 400)
},
// 停止计时器
stop() {
clearInterval(this.intervalId);
// 重新赋值为 null,避免因停止后再启动,不能开启定时器
this.intervalId = null;
}
}
})
</script>
</body>
</html>
Tips:在 vm 实例中,若要访问 data 中的数据,只需调用 this.属性即可,this 便代表 vm 实例!
v-on 和事件修饰符
.stop
:阻止冒泡.prevent
:阻止默认事件.capture
:添加事件侦听器时使用事件捕获模式.self
:只当事件在该元素本身(比如不是子元素)触发时触发回调.once
:事件只触发一次
示例:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<style>
.inner {
height: 150px;
background-color: darkcyan;
}
.outer {
padding: 40px;
background-color: red;
}
</style>
</head>
<body>
<div id="app">
<!-- 阻止向外层元素冒泡 -->
<!-- <div @click="divhandle" class="inner">
<input type="button" @click.stop="btnhandle" value="按钮">
</div> -->
<!-- 阻止默认行为 -->
<!-- <a href="https://www.baidu.com" @click.prevent="linkClick">百度</a> -->
<!--实现捕获触发事件的机制 -->
<!-- <div @click.capture="divhandle" class="inner">
<input type="button" @click="btnhandle" value="按钮">
</div> -->
<!-- .self 只有点击自己才会触发 -->
<!-- <div @click.self="divhandle" class="inner">
<input type="button" @click="btnhandle" value="按钮">
</div> -->
<!-- .once 只触发一次, 事件修饰符可以嵌套,第一次点击会阻止 a 标签跳转,第二次点击就会跳转-->
<!-- <a href="https://www.baidu.com" @click.prevent.once="linkClick">百度</a> -->
<!-- .stop 与 .self 的区别 -->
<div class="outer" @click="div2handle">
<div @click.self="divhandle" class="inner">
<!-- <input type="button" @click.stop="btnhandle" value="按钮"> -->
<input type="button" @click="btnhandle" value="按钮">
</div>
</div>
</div>
<script src="./lib/vue-2.4.0.js"></script>
<script>
var vm = new Vue({
el: '#app',
data: {},
methods: {
divhandle() {
console.log('div handle 触发')
},
btnhandle() {
console.log('btn handle 触发')
},
linkClick() {
console.log('跳转链接!')
},
div2handle() {
console.log('外层 div');
},
}
})
</script>
</body>
</html>
概念
- 冒泡:当点击以上
div
中的按钮时,同时也会触发div
的事件,即同时会输出div
和input
的值,从里向外冒泡 - 捕获:从外向里
.stop
与 .self
的区别:
.self
:只会阻止自己身上冒泡行为的触发,并不会真正阻止冒泡的行为。.stop
:会阻止事件向其外层冒泡的行为
v-model 和数据双向绑定
v-bind
只能进行单向数据绑定,v-model
可以实现表单元素和 Model
中数据的双向数据绑定。常见的表单的空间元素:input、select、textarea
等。
所谓的双向数据绑定即修改表单空间元素的值会更改 Vue
实例的值,更改 Vue
实例的值,相应地表单空间元素的值也会发生改变。
示例一:
<div id="app">
<input type="text" v-model="msg">
<h4>{{ msg }}</h4>
</div>
<script src="./lib/vue-2.4.0.js"></script>
<script>
var vm = new Vue({
el: '#app',
data: {
msg: '123'
},
methods: {
}
})
</script>
示例二:简易计算器
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<div id="app">
<input type="text" v-model="n1">
<select v-model="opt">
<option value="+">+</option>
<option value="-">-</option>
<option value="*">*</option>
<option value="/">/</option>
</select>
<input type="text" v-model="n2">
<input type="button" value="=" @click="calc">
<input type="text" v-model="result">
</div>
<script src="./lib/vue-2.4.0.js"></script>
<script>
var vm = new Vue({
el: '#app',
data: {
n1: 0,
n2: 0,
opt: '+',
result: 0
},
methods: {
calc() {
switch (this.opt) {
case '+':
this.result = parseInt(this.n1) + parseInt(this.n2);
break;
case '-':
this.result = parseInt(this.n1) - parseInt(this.n2);
break;
case '*':
this.result = parseInt(this.n1) * parseInt(this.n2);
break;
case '/':
this.result = parseInt(this.n1) / parseInt(this.n2);
break;
}
}
}
})
</script>
</body>
</html>
v-bind 修改样式
class 样式
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<style>
.red {
color: red;
}
.thin {
font-weight: 200;
}
</style>
</head>
<body>
<div id="app">
<!-- 传递一个数组 -->
<!-- <p :class="['red', 'thin']">Vue 中 css 样式</p> -->
<!-- 三元表达式,flag 为 true 应用 thin 样式 -->
<!-- <p :class="['red', flag?'thin':'']">Vue 中 css 样式</p> -->
<!-- 使用对象替换三元表达式,提高代码可读性 -->
<!-- <p :class="['red', {'thin': flag}]">Vue 中 css 样式</p> -->
<!-- 直接使用对象 -->
<p :class="classObj">Vue 中 css 样式</p>
</div>
<script src="./lib/vue-2.4.0.js"></script>
<script>
var vm = new Vue({
el: '#app',
data: {
flag: false,
classObj: {red: true, thin: false}
}
})
</script>
</body>
</html>
- 传递一个数组
- 三元表达式,不够灵活,不推荐使用
- 直接使用对象形式,键需要单引号扩起来
v-bind
:引用对象方法,放在Vue
实例data
属性中
内联样式
<body>
<div id="app">
<!-- 直接在元素上通过 `:style` 的形式,书写样式对象 -->
<!-- 若样式中间有横杠 -,则必须用单引号包裹 -->
<!-- <p :style="{color: 'red', 'font-size': '40px'}">Vue 中 css 样式</p> -->
<!-- data 中定义样式,再 :style 中引用对象 -->
<!-- <p :style="styleObj1">Vue 中 css 样式</p> -->
<!-- 通过数组绑定多个样式 -->
<p :style="[ styleObj1, styleObj2 ]">Vue 中 css 样式</p>
</div>
<script src="./lib/vue-2.4.0.js"></script>
<script>
var vm = new Vue({
el: '#app',
data: {
styleObj1: { color: 'red', 'font-weight': 200 },
styleObj2: { 'font-style': 'italic' }
}
})
</script>
</body>
Tips:若样式中间有横杠 -,则必须用单引号包裹 ,如 font-size
v-for 和 key 属性
v-for 循环
循环普通数组
格式:item in 数组
,若要获取索引,在 item
后面指定即可,索引从 0 开始。
<div id="app">
<!-- <li v-for="item in list">{{ item }}</li> -->
<li v-for="(item, i) in list">索引:{{ i }},值: {{ item }}</li>
</div>
<script src="./lib/vue-2.4.0.js"></script>
<script>
var vm = new Vue({
el: '#app',
data: {
list: [1, 2, 3]
}
})
</script>
循环对象数组
<div id="app">
<li v-for="(item, i) in list">ID:{{ item.id }}, Name: {{ item.name }}, 索引:{{ i }}</li>
</div>
<script src="./lib/vue-2.4.0.js"></script>
<script>
var vm = new Vue({
el: '#app',
data: {
list: [
{ id: 1, name: 'zs1' },
{ id: 2, name: 'zs2' },
{ id: 3, name: 'zs3' },
{ id: 4, name: 'zs4' }
]
}
})
</script>
循环对象
<div id="app">
<li v-for="(val, key, i) in user">值: {{ val }}, 键: {{ key }}, 索引: {{ i }}</li>
</div>
<script src="./lib/vue-2.4.0.js"></script>
<script>
var vm = new Vue({
el: '#app',
data: {
user: {
id: 1,
name: '托尼·屎大颗',
gender: '男'
}
},
})
</script>
循环数字
<div id="app">
<li v-for="count in 10">{{ count }}</li>
</div>
<script src="./lib/vue-2.4.0.js"></script>
<script>
var vm = new Vue({
el: '#app',
data: {},
})
</script>
Tips: 循环数字从 1 开始,而非 0
v-for 的 key 属性
2.2.0+ 的版本里,当在组件中使用 v-for 时,key 现在是必须的
v-for
循环的时候,key
属性只能使用number
获取string
key
在使用的时候,必须使用v-bind
属性绑定的形式,指定key
的值- 在组件中,使用
v-for
循环的时候,或者在一些特殊情况中,如果v-for
有问题,必须 在使用v-for
的同时,指定唯一的字符串/数字 类型:key
值
示例:
以下示例动态向数组对象 list
中添加对象,勾选其中一项,当向后添加 push
时,不会更改所勾选的选项。
而当向前添加 unshift
时,则会更改所勾选的选项,这时就需要指定 key
属性,属性值且必须是 number
或 string
。
<div id="app">
ID: <input type="text" v-model='id'>
NAME: <input type="text" v-model="name">
<input type="button" value="添加" @click="add">
<!-- 指定 key 属性 -->
<!-- <p v-for="item in list"> -->
<p v-for="item in list" :key="item.id">
<input type="checkbox">{{ item.id }} -- {{ item.name }}
</p>
</div>
<script src="./lib/vue-2.4.0.js"></script>
<script>
var vm = new Vue({
el: '#app',
data: {
id: '',
name: '',
list: [
{ id: 1, name: '李斯' },
{ id: 2, name: '嬴政' },
{ id: 3, name: '赵高' },
{ id: 4, name: '韩非' },
{ id: 5, name: '荀子' }
]
},
methods: {
add() {
// this.list.push({id: this.id, name: this.name});
this.list.unshift({id: this.id, name: this.name})
}
}
})
</script>
v-if 和 v-show
v-if 和 v-show
都是根据条件展示元素,但是两者还是有些差别。
v-if
:每次都会重新删除或创建元素,有较高的切换性能消耗v-show
:每次不会重新进行 DOM 的删除和创建操作,只是切换了元素的display:none
样式,有较高的初始渲染消耗- 如果元素涉及到频繁的切换,最后不要使用
v-if
,而是推荐使用v-show
- 如果元素可能永远也不会被显示出来被用户看到,则推荐使用
v-if
<div id="app">
<input type="button" value="按钮" @click="toggle">
<h3 v-show="flag">v-if 控制的元素</h3>
<h3 v-show="flag">v-show 控制的元素</h3>
</div>
<script src="./lib/vue-2.4.0.js"></script>
<script>
var vm = new Vue({
el: '#app',
data: {
flag: false
},
methods: {
toggle() {
this.flag=!this.flag
}
}
})
</script>
MVC 和 MVVM 的关系图解
总结
v-bind
:绑定属性、包括 css 样式,简写::
v-model
:表单空间元素,双向数据绑定,简写:@
v-for
:循环数组、对象、数组对象,2.2+ 版本需注意key
属性,属性值类似为number
或string
v-if
和v-show
:都是根据条件显示元素,但是在渲染时还是有区别的- 绑定 css 样式两种方式:
v-bind:class
和v-bind:style
vm
实例:el
指定要控制的区域,data
:挂载数据,对象类型,methods
:挂载方法/事件,对象类型- 事件修饰符:
.stop、 .prevent、.capture、.self、.once