Vue指令
MVVM模式设计模式
用数据驱动视图改变,不用在操作dom元素
-
MVVM,一种软件架构模式,决定了写代码的思想和层次
- M: model数据模型 (data里定义)
- V: view视图 (html页面)
- VM: ViewModel视图模型 (vue.js源码)
-
MVVM通过
数据双向绑定让数据自动地双向同步 不再需要操作DOM- V(修改视图) -> M(数据自动同步)
- M(修改数据) -> V(视图自动同步)
-
数据驱动思想:vue不推荐操作DOM,直接操作数据
1. 在vue中,不推荐直接手动操作DOM!!!
2. 在vue中,通过数据驱动视图,不要在想着怎么操作DOM,而是想着如何操作数据!!
3.使用vue指令,有简写的语法建议使用简写语法
1.插值表达式 {{ }}
可以在标签之中,直接插入数据内容 又名:声明式渲染 /文本插值
语法 :{{ 表达式 }}
作用:可以在视图中显示data中的数据
<template>
<div>
<h1>{{ msg }}</h1>
<h2>{{ obj.name }}</h2>
<h3>{{ obj.age > 18 ? '成年' : '未成年' }}</h3>
</div>
</template>
<script>
export default {
data() { // 格式固定, 定义vue数据之处
return { // key相当于变量名
msg: "hello, vue",
obj: {
name: "Vue世界",
age: 19
}
}
}
}
</script>
<style>
</style>
总结:dom中插值表达式赋值,vue的变量必须在data中赋值
2. v-bind
给标签属性设置vue变量的值
vue 指令,实质上就是特殊的html标签属性,以v-开头
每个指令,都有独立的作用
- 语法:v-bind:属性名=“vue变量”
- 简写::属性名=“vue变量”
<!-- vue指令-v-bind属性动态赋值 -->
<a v-bind:href="url">我是a标签</a>
<img :src="imgSrc">
总结:把vue的变量赋值到dom标签上,改变标签效果
3.v-on
给标签绑定事件,函数一定要写在methods中
- 语法:v-on:事件名=“要执行的代码 || 函数名 || 函数名(实参)”
- 简写:@事件名=“要执行的代码 || 函数名 || 函数名(实参)”
<!-- vue指令: v-on事件绑定-->
<p>你要买商品的数量: {{count}}</p>
<button v-on:click="count = count + 1">增加1</button>
<button v-on:click="addFn">增加1个</button>
<button v-on:click="addCountFn(5)">一次加5件</button>
<button @click="subFn">减少</button>
<script>
export default {
data(){
return{
count : 1,
};
},
methods: {
addFn(){ // this代表export default后面的组件对象(下属有data里return出来的属性)
this.count++
},
addCountFn(num){
this.count += num
},
subFn(){
this.count--
}
}
}
</script>
总结:把事件直接写在dom标签上,省去了传统js中操作dom的部分
3.1 v-on事件常用修饰符(鼠标)
在事件后面.修饰符名,给事件带来更方便,强大的功能
-
语法:@事件名.修饰符=“函数”
- .stop ------ 阻止事件冒泡
- .pre --------阻止默认行为
- .once ----------- 程序运行期间,只触发一次事件处理函数
<template>
<div @click="fatherFn">
<p @click.stop="onFn">点击阻止冒泡</p>
<a href="http://www.baidu.com" @click.prevent.stop>点击去百度</a>
<p @click.once="tFn">点击观察事件处理函数执行几次</p>
</div>
</template>
<script>
export default {
methods: {
fatherFn() {
console.log("父亲被点击");
},
onFn() {
console.log("儿子被点击");
},
tFn() {
console.log("11111");
},
},
};
</script>
<style>
</style>
3.2 v-on事件常用修饰符(键盘)
-
语法:@事件名.修饰符=“函数”
- @keyup.enter ------- 检测回车键
- @keyup.esc ---------- 检测退出键
<template>
<div>
<!-- 1.绑定键盘按下事件,.enter回车 -->
<input type="text" @keydown.enter="entFn" />
<!-- 2. .esc修饰符 退出键 -->
<input type="text" @keydown.esc="escFn" />
</div>
</template>
<script>
export default {
methods: {
entFn() {
console.log("触发了enter");
},
escFn() {
console.log("触发了esc");
},
},
};
</script>
<style>
</style>
总结:修饰符的使用能更加高效的完成需求,不需要进行繁琐的dom操作
4.v-model
把value属性和vue数据变量,双向绑定到一起
- 语法:v-model=“vue数据变量”
- 双向数据绑定
- MVVM设计模型
<template>
<div>
<!--
v-model:是实现vuejs变量和表单标签value属性, 双向绑定的指令
-->
<div>
<span>用户名:</span>
<input type="text" v-model="username" />
</div>
<div>
<span>密码:</span>
<input type="password" v-model="pass" />
</div>
<div>
<span>来自于: </span>
<!-- 下拉菜单要绑定在select上 -->
<select v-model="from">
<option value="北京市">北京</option>
<option value="南京市">南京</option>
<option value="天津市">天津</option>
</select>
</div>
<div>
<!-- (重要)
遇到复选框, v-model的变量值
非数组 - 关联的是复选框的checked属性
数组 - 关联的是复选框的value属性
-->
<span>爱好: </span>
<input type="checkbox" v-model="hobby" value="抽烟">抽烟
<input type="checkbox" v-model="hobby" value="喝酒">喝酒
<input type="checkbox" v-model="hobby" value="写代码">写代码
</div>
<div>
<span>性别: </span>
<input type="radio" value="男" name="sex" v-model="gender">男
<input type="radio" value="女" name="sex" v-model="gender">女
</div>
<div>
<span>自我介绍</span>
<textarea v-model="intro"></textarea>
</div>
</div>
</template>
<script>
export default {
data() {
return {
username: "",
pass: "",
from: "",
hobby: [],
sex: "",
intro: "",
};
// 总结:
// 特别注意: v-model, 在input[checkbox]的多选框状态
// 变量为非数组, 则绑定的是checked的属性(true/false) - 常用于: 单个绑定使用
// 变量为数组, 则绑定的是他们的value属性里的值 - 常用于: 收集勾选了哪些值
}
};
</script>
总结:目前v-model只能用在表单元素上,学到组件后会使用v-model高级用法
4.1 v-model修饰符
修饰符让v-model有了更简单,强大的功能
-
语法 v-model.修饰符=“vue变量”
- .number -----------以parseFloat转为数字类型
- .trim --------------- 去除首位空白字符
- .lazy ----------------- 在change触发时而非input触发时
<template>
<div>
<div>
<span>年龄:</span>
<input type="text" v-model.number="age">
</div>
<div>
<span>座右铭:</span>
<input type="text" v-model.trim="title">
</div>
<div>
<span>自我介绍:</span>
<textarea v-model.lazy="intro"></textarea>
</div>
</div>
</template>
<script>
export default {
data() {
return {
age: "",
title: "",
intro: ""
}
}
}
</script>
总结: v-model修饰符, 可以对值进行预处理, 非常高效好用
5.v-html和v-text
更新DOM对象的innerText和innerHTML,会覆盖插值表达式
-
语法
- v-text=“vue变量”
- v-html=“vue变量”
<template>
<div>
<p v-text="str"></p>
<p v-html="str"></p>
</div>
</template>
<script>
export default {
data() {
return {
str: "<p>我是一个p标签</p>"
}
}
}
</script>
v-text将值当作普通字符串显示,v-html将值当作html解析
6.v-show和v-if
控制标签的显示/隐藏
-
语法
- v-show=“vue变量”
- v-if=“vue变量 ”
-
原理
- v-show 使用标签的display:none属性进行隐藏(适合频繁切换)
- v-if 会对DOM树进行移除
-
v-if高级使用
- v-else-if
- v-else
<template>
<div>
<h1 v-show="isOk">v-show的盒子</h1>
<h1 v-if="isOk">v-if的盒子</h1>
<div>
<p v-if="age <16 ">我还是个孩子</p>
<p v-else-if="age <18 ">我长大了</p>
<p v-else>可以去娱乐场所了</p>
</div>
</div>
</template>
<script>
export default {
data() {
return {
isOk: true,
age: 15
}
}
}
</script>
总结: 使用v-show和v-if以及v-else指令, 方便通过变量控制一套标签出现/隐藏
7.v-for
列表渲染,所在标签结构, 按照数据数量, 循环生成,给谁循环就把v-for加到谁身上
-
语法
- v-for(值,索引) in 目标结构
- v-for 值 in 目标结构
-
目标结构
- 可以遍历数组 / 对象 / 数字 / 字符串 (可遍历结构)
<template>
<div id="app">
<div id="app">
<!-- v-for 把一组数据, 渲染成一组DOM -->
<!-- 口诀: 让谁循环生成, v-for就写谁身上 -->
<p>学生姓名</p>
<ul>
<li v-for="(item, index) in arr" :key="item">
{{ index }} - {{ item }}
</li>
</ul>
<p>学生详细信息</p>
<ul>
<li v-for="obj in stuArr" :key="obj.id">
<span>{{ obj.name }}</span>
<span>{{ obj.sex }}</span>
<span>{{ obj.hobby }}</span>
</li>
</ul>
<!-- v-for遍历对象(了解) -->
<p>老师信息</p>
<div v-for="(value, key) in tObj" :key="value">
{{ key }} -- {{ value }}
</div>
<!-- v-for遍历整数(了解) - 从1开始 -->
<p>序号</p>
<div v-for="i in count" :key="i">{{ i }}</div>
</div>
</div>
</template>
<script>
export default {
data() {
return {
arr: ["小明", "小欢欢", "大黄"],
stuArr: [
{
id: 1001,
name: "孙悟空",
sex: "男",
hobby: "吃桃子",
},
{
id: 1002,
name: "猪八戒",
sex: "男",
hobby: "背媳妇",
},
],
tObj: {
name: "小黑",
age: 18,
class: "1期",
},
count: 10,
};
},
};
</script>
总结: vue最常用指令, 铺设页面利器, 快速把数据赋予到相同的dom结构上循环生成
7.1 v-for更新检测
当v-for遍历的目标结构改变, Vue触发v-for的更新
-
口诀
-
数组变更方法, 就会导致v-for更新, 页面更新
- 数组方法作用到原数组上的,会导致v-for更新,页面更新
-
数组非变更方法, 返回新数组, 就不会导致v-for更新, 可采用覆盖数组或this.$set()
- 数组方法返回一个新数组的,不会导致v-for更新,页面不更新
-
<template>
<div>
<ul>
<li v-for="(val, index) in arr" :key="index">
{{ val }}
</li>
</ul>
<button @click="revBtn">数组翻转</button>
<button @click="sliceBtn">截取前3个</button>
<button @click="updateBtn">更新第一个元素值</button>
</div>
</template>
<script>
export default {
data(){
return {
arr: [5, 3, 9, 2, 1]
}
},
methods: {
revBtn(){
// 1. 数组翻转可以让v-for更新
this.arr.reverse()
},
sliceBtn(){
// 2. 数组slice方法不会造成v-for更新
// slice不会改变原始数组
// this.arr.slice(0, 3)
// 解决v-for更新 - 覆盖原始数组
let newArr = this.arr.slice(0, 3)
this.arr = newArr
},
updateBtn(){
// 3. 更新某个值的时候, v-for是监测不到的
// this.arr[0] = 1000;
// 解决-this.$set()
// 参数1: 更新目标结构
// 参数2: 更新位置
// 参数3: 更新值
this.$set(this.arr, 0, 1000)
}
}
}
</script>
<style>
</style>
-
以下数组方法会发生页面改变,v-for会检测到并更新页面
- push()`
pop()shift()unshift()splice()sort()reverse()
-
以下方法页面不会改变
- slice()`
filter()concat()
注意: vue不能监测到数组里赋值的动作而更新, 如果需要请使用Vue.set() 或者this.$set(), 或者覆盖整个数组
总结:只有改变原数组目标结构的方法,才会让v-for更新
7.2 v-for就地更新
v-for的默认行为会尝试原地修改元素而不是移动他们
这种 虚拟DOM对比方式, 可以提高性能 - 但是还不够高