vue的核心是用数据驱动视图,因此在学习VUE时我们应该转换思想,不要想着如何去操作DOM,而是去想着如何操作数据。
安装Vue
CDN下载(需连接网络)
直接在html中通过script标签将其引入即可使用。
<!-- 开发环境版本,包含了有帮助的命令行警告 -->
<script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.0/vue.js"></script>
<!-- 生产环境版本,优化了尺寸和速度 -->
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
Vue中的MVVM开发模式
Model 代表数据模型,数据和业务逻辑都在Model层中定义;
View 代表UI视图,负责数据的展示;
ViewModel 负责监听 Model 中数据的改变并且控制视图的更新,处理用户交互操作
Model 中的数据改变时会触发 View 层的刷新,View 中由于用户交互操作而改变的数据也会在 Model 中同步
vue虽然没有完全遵循 MVVM 模型,但Vue 的设计无疑受到了它的启发。因此在文档中经常会使用 vm (ViewModel 的简称) 这个变量名表示 Vue 实例。
常用内置指令
v-text | 更新元素的 text,输出的是纯文本,一般简写为{{}} (也叫做插值语法) |
v-html | v-html 指令类似于 v-text 指令,但v-html会将其当html标签解析后输出 |
v-if | 本质是通过控制dom元素的添加与移除来控制标签是否显示 |
v-else | 如果为 false, 当前标签才会输出到页面 |
v-show | 本质是通过控制 display 样式来控制dom元素的显示与隐藏 |
v-for | 遍历数组/对象 |
v-on | 绑定事件监听, 可以简写为@ |
v-bind | 绑定解析表达式, 可以省略 v-bind,简写为 : |
v-model | 双向数据绑定 |
v-cloak | 防止闪现, 与 css 配合: [v-cloak] { display:none} |
v-once | 执行一次性地插值,当数据改变时,插值处的内容不会更新 |
模板语法
el用于指定当前Vue实例为哪个容器服务,值通常为css选择器字符串;
data用于存储数据,数据供el所指定的容器去使用。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="https://cdn.jsdelivr.net/npm/vue@2.7.10"></script>
</head>
<body>
<div id="app">
<!-- 模板语法 -->
<!-- 1.文本插值 mustache语法 {{}} -->
{{msg}}
<!-- 2.从后端获取代码片段 使用v-html指令可以解析代码片段 innerHTML-->
<div v-html="p"></div>
<!-- 3.绑定变量 v-bind 或者 :简写 -->
<div v-bind:title="title">我是一个div</div>
<!-- 4.绑定事件 -->
<button v-on:click="msg='我被修改了'">点我</button>
<button @click="msg='我被修改了'">点我</button>
<!-- 5.{{使用js表达式}} -->
{{count * 100}}
<!-- 10000 -->
{{Number(msg)}}
<!-- NaN -->
{{Boolean(msg)}}
<!-- true -->
</div>
<script>
new Vue({
el:'#app',
data:{
count:100,
msg:"hello vue",
title:"我是一个标题",
p:'<a href="https://www.baidu.com">百度一下</a>'
}
})
</script>
</body>
</html>
Vue模板语法包括两大类:
-
插值语法:
- 功能:用于解析标签体内容
- 写法:
{{xxx}}
,xxx是js表达式,且可以直接读取到data中的所有区域
-
指令语法:
- 功能:用于解析标签(包括:标签属性、标签体内容、绑定事件…)
- 举例:
<a v-bind:href="xxx">
或简写为<a :href="xxx">
,xxx同样要写js表达式,且可以直接读取到data中的所有属性 - 备注:Vue中有很多的指令,详见上述常用内置指令。
1.1数据绑定
数据绑定分为单向数据绑定与双向事件绑定。
- 单向绑定(
v-bind
):数据只能从data流向页面 - 双向绑定(
v-model
):数据不仅能从数据层流向视图层,还可以从视图层流向数据层,即用户与页面交互输入的内容也会被同步更新在数据层。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>数据绑定</title>
<script src="https://cdn.jsdelivr.net/npm/vue@2.7.10"></script>
</head>
<body>
<div id="app">
单向数据绑定:<input type="text" v-bind:value="name"><br>
双向数据绑定:<input type="text" v-model:value="name">
</div>
<script>
new Vue({
el:'#app',
data:{
name:'zzy'
}
})
</script>
</body>
</html>
注意:
双向绑定一般都应用在表单类元素上(如:<input>
、<select>
、<textarea>
等)
1.2 条件渲染
条件渲染有两种方式:
- v-if:满足条件时渲染到html中,通过操纵dom元素的添加或移除来进行切换显示
- v-show:元素始终被渲染到HTML,当不满足条件的元素被设置style=“display:none”的样,是通过修改元素的的CSS属性(display)来决定实现显示还是隐藏
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="https://cdn.jsdelivr.net/npm/vue@2.7.10"></script>
</head>
<body>
<div id="app">
<!-- 条件渲染 -->
<div v-if="type==='email'">
<form >
<input type="text" placeholder="请输入邮箱">
</form>
</div>
<div v-else-if="type==='telephone'">
<form >
<input type="text" placeholder="请输入电话">
</form>
</div>
<div v-else>错误</div>
<div v-show="isShow">我是一个div</div>
</div>
<script>
new Vue({
el:"#app",
data:{
type:"telephone",
isShow:false
}
})
</script>
</body>
</html>
v-if与v-show的适用场景:
v-if需要操作dom元素,有更高的切换消耗,v-show只是修改元素的的CSS属性有更高的初始渲染消耗,如果需要非常频繁的切换,建议使用v-show较好,如果在运行时条件很少改变,则使用v-if较好。
1.3 列表渲染
注意:
- 进行列表展示时,默认key是index;
- 如果数据只做展示使用,使用index作为key是没有任何问题的;
- 如果使用index作为key,而后续操作会破坏顺序,那么一定会带来效率问题,严重时会渲染出错误的DOM
-
因此在进行列表渲染时会给节点添加一个唯一值 key
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="https://cdn.jsdelivr.net/npm/vue@2.7.10"></script>
</head>
<body>
<div id="app">
<ul>
<li v-for="(item,index) in animal" :key="item">{{item}}--{{index}}</li>
</ul>
<!--列表渲染对象 -->
<ul>
<li v-for="(key,value,index) in obj" :key="index">{{key}}--{{value}}--{{index}}</li>
</ul>
</div>
<script>
new Vue({
el:"#app",
data:{
animal:['苹果','西瓜','橙子'],
obj:{
name:'zzy',
age:18
}
}
})
</script>
</body>
</html>
1.4 样式绑定
- 可以在数据中通过对象的方式存储样式;
- 如果需要同时绑定两个样式,可以使用数组将两个样式表包裹;
- 动态绑定类名,通过设置true/false来控制样式是否生效
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="https://cdn.jsdelivr.net/npm/vue@2.7.10"></script>
</head>
<style>
.red{
color:red;
}
.color{
font-size: 18px;
background-color: pink;
}
</style>
<body>
<div id="app">
<div :style="{color:currentColor}">我是一个div</div>
<!-- 绑定一个样式 -->
<div :style="styleObj1">我是第二个div</div>
<!-- 同时绑定两个样式 -->
<div :style="[styleObj1,styleObj2]"> 我是第三个div</div>
<!-- 动态绑定类名 -->
<div :class="{red:true}">我是第四个div</div>
<div :class="{red:false,color:true}">我是第五个div</div>
<div :class="[{red:true},{color:false}]">我是第六个div</div>
</div>
<script>
new Vue({
el:"#app",
data:{
currentColor:'red',
styleObj1:{
fontSize:'18px',
backgroundColor:'blue'
},
styleObj2:{
backgroundColor:'red'
}
}
})
</script>
</body>
</html>
1.5 事件修饰符
事件修饰符主要对事件的发生范围进行限定
详情见对应的代码与之注释。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="https://cdn.jsdelivr.net/npm/vue@2.7.10"></script>
<style>
.outer{
width: 400px;
height: 400px;
background-color: greenyellow;
display: flex;
justify-content: center;
align-items: center;
overflow: scroll;
}
.inner{
width: 200px;
height: 200px;
background-color: yellow;
}
</style>
</head>
<body>
<div id="app">
<!-- 与keyup一起使用的事件修饰符
.enter、.tab、.delete、.esc、.space、.up、.down、.left、.right
.ctrl、.alt、.shift、.meta 表示按下键盘上对应的键才会触发事件-->
<!-- 鼠标修饰符mouseup事件
.left、.right、.middle -->
<input type="text" @keyup.enter="console.log('键盘按下')">
<!-- 事件修饰符 .capture 事件捕获阶段执行 -->
<!-- 点击inner时outer会先执行 -->
<!-- <div class="outer" @click.capture="outer"> -->
<!-- .self.once只当在事件触发元素是当前元素自身时触发处理函数且执行一次后解绑 -->
<div class="outer" @click.self="outer">
<!-- .passive 滚动行为将会立即触发 ,一般与scroll连用 -->
<div class="outer" @scroll.passive="outer">
<!-- 事件修饰符 .stop阻止事件冒泡 -->
<!-- <div class="inner" @click.stop="inner"></div> -->
<div class="inner" @click="inner"></div>
</div>
<!-- 事件修饰符 .prevent 阻止事件默认行为 -->
<!-- <a @click.prevent="toJump" href="https://www.bilibili.com">哔哩哔哩</a> -->
</div>
<script>
new Vue({
el:"#app",
data:{
},
methods:{
outer(){
console.log('outer被点击了');
},
inner(){
console.log('inner被点击了');
// 原生阻止事件冒泡
// event.stopPropagation();
},
toJump(){
// 原生阻止事件默认行为
// 点击a链接无法跳转
// event.preventDefault();
}
}
})
</script>
</body>
</html>
生命周期:
Vue 实例从创建到销毁的过程,就是生命周期。也就是从开始创建、初始化数据、编译模板、挂载Dom→渲染、更新→渲染、卸载等一系列过程,我们称这是 Vue 的生命周期。
生命周期可以总共分为8个阶段:创建前/后, 载入前/后,更新前/后,销毁前/后。
1.beforeCreate
实例初始化之前 此时不可以访问data和methods 初始化一些事件默认的生命周期
2.created
实例初始化完成 可以访问data数据和methods中方法 发送异步请求
3.beforeMount
实例挂载到页面之前 编译模板 创建一个虚拟得$el代替真实dom
是否有el属性,没有需要手动调用vm.$mount(模板标签)挂载
有el属性 有template模板 有template模板 将template作为模板进行编译
没有 指定el外部得html作为模板进行编译
4.mouted
实例挂载到页面上 此时可以获取dom元素 也可以发送异步请求
前四个生命周期只会执行一次
5.beforeUpdate
实例更新会触发得生命周期 数据时最新得 视图还没有更新 实例找到数据对应得视图进行更新
6.updated
实例更新已经完成 视图已经渲染完成
手动调用触发销毁 vm.$destroy()
7.beforeDestroy
实例销毁之前 此时还是可以访问实例对象data和methods
8.destroed
实例销毁完成 除了移除子组件、监听器、不会重新编译模板