第 1 章:Vue 核心
1.1 Vue 简介
1.1.1 介绍与描述
Vue 是一套用于构建用户界面的渐进式JavaScript框架。
1.1.2 Vue 的特点
-
采用组件化模式,提高代码复用率、且让代码更好维护。
-
声明式编码,让编码人员无需直接操作DOM,提高开发效率。
-
使用虚拟DOM监听数据的变化,采用双向数据绑定,尽量复用DOM节点
- 遵循 MVVM 模式
- 编码简洁,体积小,运行效率高,适合移动/PC端开发
- 它本身只关注 UI ,也可以引入其它第三方库开发项目
1.2 Vue 安装
1.2.1 <script>
引入
直接下载并用 <script>
标签引入,Vue 会被注册为一个全局变量。
<!-- 引入vue.js文件 -->
<script src="./vue.js"></script>
1.2.2 CDN 引入
使用 CDN 方式引入:
<!-- CDN引入 -->
<script src="https://cdn.jsdelivr.net/npm/vue@2.7.10/dist/vue.js"></script>
1.2.3 NPM 安装
项目初始化:npm init -y // 初始化 package.json 文件
执行命令:npm i vue@2.6.14 --save / npm i vue@2.6.14 -S
1.3 初识 Vue
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>初识Vue</title>
</head>
<body>
<!--
初识Vue:
1. 想让 Vue 工作,就必须创建一个 Vue 实例,且要传入一个配置对象
2. root 容器里的代码依然符合 html 规范,只不过混入了一些特殊的 Vue 语法
3. root 容器里的代码被称为【Vue 模板】
4. Vue 实例和容器是一一对应的
5. 真实开发中只有一个Vue实例,并且会配合着组件一起使用
6. `{{xxx}}` 中的 `xxx` 要写js表达式,且 `xxx` 可以自动读取到data中的所有属性
7. 一旦 data 中的数据发生改变,那么页面中用到该数据的地方也会自动更新
-->
<!-- 准备好一个容器 -->
<div id="root">
<h1>你好,{{name}}</h1>
</div>
<!-- 引入Vue -->
<script src="../js/vue.js"></script>
<script>
// 创建Vue实例
new Vue({
el: '#root', // el用于指定当前Vue实例为哪个容器服务,值通常为css选择器字符串
data:{ // data中用于存储数据,数据供el所指定的容器去使用
name:'张三'
}
})
</script>
</body>
</html>
注意事项:
- 不要把 vue 挂载在 html 和 body 标签上,挂载在正常的元素上
- vue 实例只能作用于一个元素节点上,所以建议使用 id 选择器
1.4 模板语法
1.4.1 模板的理解
html 中包含了一些 JS 语法代码,语法分为两种,分别为:
- 插值语法(双括号表达式)
- 指令(以
v-
开头)
1.4.2 插值语法
vue 提供的 {{ }} 语法,专门用来解决 v-text 会覆盖默认文本内容的问题。这种 {{ }} 语法的专业名称是插值表达式(英文名为:Mustache)。
- 功能:用于解析标签体内容
- 语法:
{{xxx}}
,xxx 会作为 js 表达式解析
<!-- 使用 {{ }} 插值表达式,将对应的值渲染到元素的内容节点中 -->
<!-- 同时保留元素自身的默认值 -->
<p>姓名:{{username}}</p>
<p>性别:{{gender}}</p>
<script>
const vm = new Vue({
el:'#app',
data:{
username:'张三',
gender:'女'
}
})
</script>
1.4.3 指令语法
- 功能:解析标签属性、解析标签体内容,绑定事假
- 举例:
v-bind:href = "xxx"
,xxx 会作为 js 表达式被解析
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>模板语法</title>
<!-- 引入Vue -->
<script src="../js/vue.js"></script>
</head>
<body>
<!--
Vue模板语法有2大类:
1.插值语法:
功能:用于解析标签体内容。
写法:{{xxx}},xxx是js表达式,且可以直接读取到data中的所有属性。
2.指令语法:
功能:用于解析标签(包括:标签属性、标签体内容、绑定事件...)。
举例:v-bind:href="xxx" 或 简写为 :href="xxx",xxx同样要写js表达式,
且可以直接读取到data中的所有属性。
-->
<div id="root">
<h1>插值语法</h1>
<h3>你好,{{name}}</h3>
<hr/>
<h1>指令语法</h1>
<a v-bind:href="url">百度一下,你就知道</a>
<a :href="game.url">4399小游戏,等你来玩</a>
</div>
<script>
new Vue({
el:'#root',
data:{
name:'张三',
url:'http://www.baidu.com',
game:{
url:'http://www.4399.com'
}
}
})
</script>
</body>
</html>
1.4.4 指令的概念
指令(Directives)是 vue 为开发者提供的模板语法,用于辅助开发者渲染页面的基本结构。
vue 中的指令按照不同的用途可以分为如下 6 大类:
1. 内容渲染指令
2. 属性绑定指令
3. 事件绑定指令
4. 双向绑定指令
5. 条件渲染指令
6. 列表渲染指令
注意:指令是 vue 开发中最基础、最常用、最简单的知识点。
1.5 数据绑定
1.5.1 单向数据绑定
- 语法:
v-bind:href="xxx"
或简写为:href
- 特点:数据只能从 data 流向页面
数据驱动视图:页面数据发生变化时,页面会自动重新渲染!
1.5.2 双向数据绑定
在填写表单时,双向数据绑定可以辅助开发者在不操作 DOM 的前提下,自动把用户填写的内容同步到数据源中。
- 语法:
v-model:value="xxx"
或简写为v-model="xxx"
- 特点:数据不仅能从 data 流向页面,还能从页面流向 data
示例图如下:
注意:数据驱动视图和双向数据绑定的底层原理是 MVVM(Mode 数据源、View 视图、ViewModel 就是 vue 的实例)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<!-- 引入Vue -->
<script src="../js/vue.js"></script>
</head>
<body>
<!--
Vue中有2种数据绑定的方式:
1.单向绑定(v-bind):数据只能从data流向页面。
2.双向绑定(v-model):数据不仅能从data流向页面,还可以从页面流向data。
备注:
1.双向绑定一般都应用在表单类元素上(如:input、select等)
2.v-model:value 可以简写为 v-model,因为v-model默认收集的就是value值。
-->
<!-- 准备好一个容器 -->
<div id="root">
<!-- 普通写法 -->
单向数据绑定:<input type="text" v-bind:value="name">
双向数据绑定:<input type="text" v-model:value="name">
<!-- 简写 -->
单向数据绑定:<input type="text" :value="name">
双向数据绑定:<input type="text" v-model="name">
<!-- 如下代码时错误的,因为v-model只能应用在表单类元素(输入类元素)上 -->
<h2 v-model:x="name">你好</h2>
</div>
<script>
new Vue({
el: '#root',
data: {
name: '张三'
}
})
</script>
</body>
</html>
1.5.3 指令修饰符
为了方便对用户输入的内容进行处理,vue 为 v-model 指令提供了 3 个修饰符,分别是:
修饰符 | 作用 | 实例 |
---|---|---|
.number | 自动将用户的输入值转为数值类型 | <input v-model.number="age"> |
.trim | 自动过滤用户输入的首尾空白字符 | <input v-model.trim="msg"> |
.lazy | 在"change"时而非"input"时更新 | <input v-model.lazy="msg"> |
实例用法如下:
<input type="text" v-model.number="n1">+
<input type="text" v-model.number="n2">=
<span>{{n1 + n2}}</span>
1.5.4 el与data的两种写法
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>el与data的两种写法</title>
<!-- 引入Vue -->
<script src="../js/vue.js"></script>
</head>
<body>
<!--
el与data的2种写法:
1.el有2种写法
(1) new Vue的时候配置el属性。
(2) 想创建Vue实例,随后再通过vm.$mount('#root')指定el的值。
2.data有2种写法
(1) 对象式
(2) 函数式
如何选择:目前哪种写法都可以,以后学习到组件时,data必须使用函数式,否则会报错。
3.一个重要的原则:
由Vue管理的函数,一定不要写箭头函数,一旦写了箭头函数,this就不再是Vue实例了。
-->
<div id="root">
<h1>你好,{{name}}</h1>
</div>
<script>
// el的两种写法
// const v = new Vue({
// // el:'#root', // 第一种写法
// data:{
// name:'张三'
// }
// })
// console.log(v)
// v.$mount('#root') // 第二种写法
// data的两种写法
new Vue({
el:'#root',
// data的第一种写法:对象式
// data:{
// name:'张三'
// }
// data的第二种写法:函数式
data(){
console.log('@@@',this) // 此处this是Vue实例对象
return{
name:'张三'
}
}
})
</script>
</body>
</html>
1.5.5 MVVM 模型
MVVM 是 vue 实现数据驱动视图和双向数据绑定的核心原理。MVVM 指的是 Model、View 和 ViewModel, 它把每个 HTML 页面都拆分成了这三个部分,如图所示:
- M:模型(Model) :对应 data 中的数据
- V:视图(View) :模板
- VM:视图模型(ViewModel) : Vue 实例对象
在 MVVM 概念中: Model 表示当前页面渲染时所依赖的数据源。 View 表示当前页面所渲染的 DOM 结构。 ViewModel 表示 vue 的实例,它是 MVVM 的核心。
1.5.6 MVVM 的工作原理
ViewModel 作为 MVVM 的核心,是它把当前页面的数据源(Model)和页面的结构(View)连接在了一起。
-
当数据源发生变化时,会被 ViewModel 监听到,VM 会根据最新的数据源自动更新页面的结构
-
当表单元素的值发生变化时,也会被 VM 监听到,VM 会把变化过后最新的值自动同步到 Model 数据源中
1.6 事件处理
1.6.1 绑定监听
vue 提供了 v-on
事件绑定指令,用来辅助程序员为 DOM 元素绑定事件监听。语法格式如下:
- 语法:
v-on:事件类型="事件方法名"
- 简写:
@事件类型="事件方法名"
注意:原生DOM对象有 onclick、oninput、onkeyup 等原生事件,替换为 vue 的事件绑定形式后, 分别为:v-on:click、v-on:input、v-on:keyup
通过 v-on
绑定的事件处理函数,需要在 methods 节点中进行声明:
<div id="app">
<!--
语法:
v-on:事件类型="事件方法名"
简写:
@事件类型="事件方法名"
-->
<button v-on:click="fn">点击</button>
<button v-on:click="fn()">点击</button>
<button v-on:click="fn(666)">点击</button>
<button @click="fn(666)">点击</button>
</div>
<script>
// 实例化vue
new Vue({
el:'#app',
data:{ // 数据
},
methods:{ // 方法
fn(num){
console.log(num);
console.log('我被点击了');
}
}
});
</script>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>事件的基本使用</title>
<!-- 引入Vue -->
<script src="../js/vue.js"></script>
</head>
<body>
<!--
事件的基本使用:
1.使用v-on:xxx 或 @xxx 绑定事件,其中xxx是事件名
2.事件的回调需要配置在methods对象中,最终会在vm上
3.methods中配置的函数,不需要用箭头函数!否则this就不是vm了
4.methods中配置的函数,都是被Vue所管理的函数,this的指向是vm或组件实例对象
5.@click="demo" 和 @click="demo($event)" 效果一致,但后者可以传参
-->
<!-- 准备好一个容器 -->
<div id="root">
<h2>你好,{{name}}</h2>
<button v-on:click="showInfo1">点我提示信息(不传参)</button>
<button @click="showInfo2($event,66)">点我提示信息(传参)</button>
</div>
<script>
const vm = new Vue({
el:'#root',
data:{
name:'张三'
},
methods:{
showInfo1(event){
console.log(event);
alert('这是第一条提示信息');
},
showInfo2(number){
console.log(number);
console.log(this); // 此处this是vm
alert('这是第二条提示信息');
}
}
})
</script>
</body>
</html>
1.6.2 $event
$event
是 vue 提供的特殊变量,用来表示原生的事件参数对象 event。$event 可以解决事件参数对象 event 被覆盖的问题。
两种方式:
- 隐式获取:不需要传递任何参数,在形参中直接获取
event
事件源对象 - 显式获取:实参中通过
$event
传递,在形参中直接接收
注意事项:如果传递多个参数同时获取事件源对象,需要通过显式来获取
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<!-- 1. 引入vue.js -->
<script src="./vue.js"></script>
</head>
<body>
<!-- 2. 创建DOM元素 -->
<div id="app">
<!-- 隐式获取event对象 -->
<button @click="getEvent">隐式获取event事件对象</button>
<!-- 显示获取event事件对象 -->
<button @click="getEvent($event)">显示获取event事件对象</button>
<!-- 参数中传递多个参数同时获取事件源对象 -->
<button @click="getParam(10,$event,20)">传递多个参数</button>
</div>
<script>
new Vue({
el: '#app',
data: {},
methods: {
getEvent(e) {
console.log(e);
},
getParam(num1, num2, e) {
console.log(num1)
console.log(num2)
console.log(e)
}
}
})
</script>
</body>
</html>
1.6.3 事件修饰符
在事件处理函数中调用 event.preventDefault()
或 event.stopPropagation()
是非常常见的需求。因此,vue 提供了事件修饰符的概念,来辅助程序员更方便的对事件的触发进行控制。常用的 5 个事件修饰符如下:
事件修饰符 | 说明 |
---|---|
.prevent | 阻止事件默认行为(例如:阻止 a 连接的跳转、阻止表单的提交等) |
.stop | 阻止事件冒泡 |
.capture | 以捕获模式触发当前的事件处理函数 |
.once | 绑定的事件只触发1次 |
.self | 只有在 event.target 是当前元素自身时触发事件处理函数 |
.passive | 事件的默认行为立即执行,无需等待事件回调执行完毕 |
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>事件修饰符</title>
<!-- 引入Vue -->
<script src="../js/vue.js"></script>
<style>
*{
margin-top:20px;
}
.demo1{
height:50px;
background-color: skyblue;
}
.box1{
padding:5px;
background-color: skyblue;
}
.box2{
padding:5px;
background-color: orange;
}
.list{
width: 200px;
height:200px;
background-color: peru;
overflow: scroll;
}
li{
height: 100px;
}
</style>
</head>
<body>
<!--
Vue中的事件修饰符:
1.prevent:阻止默认事件(常用)
2.stop:阻止事件冒泡(常用)
3.once:事件只触发一次(常用)
4.capture:使用事件的捕获模式
5.self:只有event.target是当前操作的元素时才触发事件
6.passive:事件的默认行为立即执行,无需等待事件回调执行完毕
-->
<!-- 准备好一个容器 -->
<div id="root">
<h2>欢迎来到{{name}}</h2>
<!-- 阻止默认事件(常用) -->
<a href="http://www.baidu.com" @click.prevent="showInfo">百度一下,你就知道</a>
<!-- 阻止事件冒泡(常用) -->
<div class="demo1" @click="showInfo">
<button @click.stop="showInfo">点我提示信息</button>
</div>
<!-- 事件只触发一次(常用) -->
<button @click.once="showInfo">点我提示信息(触发一次)</button>
<!-- 使用事件的捕获模式 -->
<div class="box1" @click.capture="showMsg(1)">
box1
<div class="box2" @click="showMsg(2)">box2</div>
</div>
<!-- 只有event.target是当前操作的元素时才触发事件 -->
<div class="demo1" @click.self="showInfo">
<button @click="showInfo">点我提示信息</button>
</div>
<!-- 事件的默认行为立即执行,无需等待事件回调执行完毕 -->
<ul class="list" @scroll.passive="demo">
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
</ul>
</div>
<script>
new Vue({
el:'#root',
data:{
name:'清华大学'
},
methods:{
showInfo(e){
alert('你好,张三');
},
showMsg(n){
console.log(n);
},
demo(){
console.log('@');
}
}
})
</script>
</body>
</html>
1.6.4 按键修饰符
在监听键盘事件时,我们经常需要判断详细的按键。此时,可以为键盘相关的事件添加按键修饰符。
.enter
:回车键 – 13.left
:左键 – 37.up
:上键 – 38.right
:右键 – 39.down
:下键 – 40
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<!-- 1. 引入vue.js -->
<script src="./vue.js"></script>
</head>
<body>
<!-- 2. 创建DOM元素 -->
<div id="app">
<!--
1.Vue中常用的按键别名:
回车 => enter
删除 => delete(捕获“删除”和“退格”键)
退出 => esc
空格 => space
换行 => tab(特殊:必须配合keydown使用)
上 => up
下 => down
左 => left
右 => right
2.Vue未提供别名的按键,可以使用按键原始的key值去绑定,但注意要转为kebab-case(短横线命名)
3.系统修饰键(用法特殊):ctrl、alt、shift、meta
(1) 配合keyup使用:按下修饰键的同时,再按下其他键,随后释放其他键,事件才被触发。
(2) 配合keydown使用:正常触发事件。
4.也可以使用keyCode去指定具体的按键(不推荐)
5.Vue.config.keyCodes.自定义键名 = 键码,可以去定制按键别名
-->
<input type="text" placeholder="回⻋" @keydown.enter="enter">
<input type="text" placeholder="回⻋" @keydown.13="enter">
<hr>
<input type="text" placeholder="左键" @keydown.left="left">
<input type="text" placeholder="左键" @keydown.37="left">
<hr>
<input type="text" placeholder="上键" @keydown.up="up">
<input type="text" placeholder="上键" @keydown.38="up">
<hr>
<input type="text" placeholder="右键" @keydown.right="right">
<input type="text" placeholder="右键" @keydown.39="right">
<hr>
<input type="text" placeholder="下键" @keydown.down="down">
<input type="text" placeholder="下键" @keydown.40="down">
</div>
<script>
new Vue({
el: '#app',
data: {},
methods: {
enter() {
console.log('回⻋');
},
left() {
console.log('left');
},
up() {
console.log('up');
},
right() {
console.log('right');
},
down() {
console.log('down');
}
}
})
</script>
</body>
</html>
1.7 计算属性与监视
1.7.1 计算属性-computed
计算属性指的是通过一系列运算之后,最终得到一个属性值。这个动态计算出来的属性值可以被模板结构或 methods 方法使用。
- 虽然计算属性在声明的时候被定义为方法,但是计算属性的本质是一个属性
- 计算属性会缓存计算的结果,只有计算属性依赖的数据变化时,才会重新进行运算
实例代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>姓名案例_计算属性实现</title>
<!-- 引入Vue -->
<script src="../js/vue.js"></script>
</head>
<body>
<!--
计算属性:
1.定义:要用的属性不存在,要通过已有的属性计算得来。
2.原理:底层借助了Object.defineproperty方法提供的getter和setter。
3.get函数什么时候执行?
(1)初次读取时会执行一次。
(2)当依赖的数据发生改变时会再次被调用。
4.优势:与methods实现相比,内部有缓存机制(复用),效率更高,调试方便。
5.备注:
1.计算属性最终会出现在vm上,直接读取使用即可。
2.如果计算属性要被修改,那必须写set函数去响应修改,且set中要引起计算时依赖的数据发生改变。
-->
<!-- 准备好一个容器 -->
<div id="root">
姓:<input type="text" v-model="firstName"><br/>
名:<input type="text" v-model="lastName"><br/>
全名:<span>{{fullName}}</span>
</div>
<script>
new Vue({
el:'#root',
data:{
firstName:'张',
lastName:'三'
},
computed:{
// 完整写法
// fullName:{
// // 当有人读取fullName时,get就会被调用,且返回值就作为fullName的值。
// // get什么时候被调用?1.初次读取fullName时。2.所依赖的数据发生变化时。
// get(){
// console.log('get被调用了',this);
// return this.firstName + this.lastName
// },
// // set什么时候被调用?当fullName被修改时。
// set(value){
// console.log('set',value);
// const arr = value.split('-')
// this.firstName = arr[0]
// this.lastName = arr[1]
// }
// }
// 只读不改简写
fullName(){
console.log('get被调用了');
return this.firstName + this.lastName
}
}
})
</script>
</body>
</html>
1.7.2 监视属性-watch
watch 侦听器允许开发者监视数据的变化,从而针对数据的变化做特定的操作。
普通监听:
监听一般的数据类型:监听 data 数据的改变,从而做出相应的操作
- 1、当被监视的属性变化时,回调函数自动调用,进行相关操作
- 2、该方法中系统自动注入两个参数newValue,oldValue
- 3、在普通监听中可以获取最新值和旧值
- 4、监视的属性必须存在,才能进行监视
- 5、监视的两种写法:
- (1) new Vue时传入 watch 配置
- (2) 通过 vm.$watch 监视
案例一:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>天气案例_监视属性</title>
<!-- 引入Vue -->
<script src="../js/vue.js"></script>
</head>
<body>
<!--
监视属性watch:
1.当被监视的属性变化时,回调函数自动调用,进行相关操作
2.监视的属性必须存在,才能进行监视
3.监视的两种写法:
(1)new Vue时传入watch配置
(2)通过vm.$watch监视
-->
<div id="root">
<h2>今天天气很{{info}}</h2>
<!-- 绑定事件的时候:@xxx="yyy" yyy可以写一些简单的语句 -->
<!-- <button @click="isHot = !isHot">切换天气</button> -->
<button @click="changeWeather">切换天气</button>
</div>
<script>
const vm = new Vue({
el:'#root',
data:{
isHot:true,
x:1
},
computed:{
info(){
return this.isHot ? '炎热' : '凉爽';
}
},
methods:{
changeWeather(){
this.isHot = !this.isHot
}
},
watch:{
isHot:{
immediate:true, // 初始化时让handler调用一下
// 当isHot发生改变时,handler会被调用
handler(newValue,oldValue){
console.log('isHot被修改了',newValue,oldValue);
}
}
}
})
vm.$watch('info',{
immediate:true, // 初始化时让handler调用一下
// 当isHot发生改变时,handler会被调用
handler(newValue,oldValue){
console.log('info被修改了',newValue,oldValue);
}
})
</script>
</body>
</html>
案例二:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<!-- 1. 引入vue.js -->
<script src="./vue.js"></script>
</head>
<body>
<!-- 2. 创建DOM元素 -->
<div id="app">
<input type="text" v-model="name">
<div>{{name}}</div>
<hr>
<input type="text" v-model="age">
<div>{{age}}</div>
<hr>
<input type="text" v-model="arr[1]">
<div>{{arr[1]}}</div>
<hr>
<input type="text" v-model="obj.name">
<div>{{obj.name}}</div>
</div>
<script>
// 3.实例化vue
new Vue({
el: '#app',
data: {
name: '张三',
age: 18,
arr: ['长沙', '臭豆腐', '橘子洲', '糖油粑粑'],
obj: {
name: '张三'
}
},
// watch 监听data数据
watch: {
/**
1.系统会自动注入两个参数:newVal和oldVal
2.在普通监听中是可以获取到新值和旧值
3.数组只有新值,没有旧值
**/
name(newVal, oldVal) {
console.log(newVal, oldVal);
},
age(newVal, oldVal) {
console.log(newVal, oldVal);
},
// 只有新值,没有旧值
arr(newVal) {
console.log(newVal);
},
obj(newVal, oldVal) {
console.log(newVal);
}
}
})
</script>
</body>
</html>
深度监听:
如果 watch 侦听的是一个对象,如果对象中的属性值发生了变化,则无法被监听到。此时需要使用 deep
选项,代码示例如下:
const vm = new Vue({
el: '#app',
data: {
info:{ username: 'admin' }
},
watch: {
info: {
// handler 是固定写法,表示当username的值变化时,自动调用handler处理函数
hanlder(newVal) {
console.log(newVal.username)
},
deep: true
}
}
})
- Vue 中的 watch 默认不监测对象内部值的改变(一层)
- 配置 deep:true 可以监测对象内部值改变(多层)
备注:
(1) Vue 自身可以监测对象内部值的改变,但 Vue 提供的 watch 默认不可以。
(2) 使用 watc h时根据数据的具体结构,决定是否采用深度监视。
案例一:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>天气案例_深度监视</title>
<!-- 引入Vue -->
<script src="../js/vue.js"></script>
</head>
<body>
<!--
深度监视:
(1)Vue中的watch默认不监测对象内部值的改变(一层)
(2)配置deep:true可以监测对象内部值改变(多层)
备注:
(1)Vue自身可以监测对象内部值的改变,但Vue提供的watch默认不可以
(2)使用watch时根据数据的具体结构,决定是否采用深度监视。
-->
<div id="root">
<h2>今天天气很{{info}}</h2>
<button @click="changeWeather">切换天气</button>
<hr>
<h2>a的值是:{{numbers.a}}</h2>
<button @click="numbers.a++">点击a++</button>
</div>
<script>
const vm = new Vue({
el:'#root',
data:{
isHot:true,
numbers:{
a:1,
b:1
}
},
computed:{
info(){
return this.isHot ? '炎热' : '凉爽';
}
},
methods:{
changeWeather(){
this.isHot = !this.isHot
}
},
watch:{
isHot:{
immediate:true, // 初始化时让handler调用一下
// 当isHot发生改变时,handler会被调用
handler(newValue,oldValue){
console.log('isHot被修改了',newValue,oldValue);
}
},
// 简写
/*
isHot(newValue,oldValue){
console.log('isHot被修改了',newValue,oldValue);
}
*/
numbers:{
deep:true,
handler(){
console.log('numbers改变了')
}
}
}
})
// 简写
vm.$watch('isHot',(newValue,oldValue)=>{
console.log('isHot被修改了',newValue,oldValue);
})
</script>
</body>
</html>
案例二:
- 监听对象只能使用深度监听
- 深度监听的方法必须是handler
- 必须是
deep: true
作为深度监听 - 在深度监听中无法监听旧值,因为初始设计中没有保存旧值
- 深度监听只能获取最新值
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<!-- 1. 引入vue.js -->
<script src="./vue.js"></script>
</head>
<body>
<!-- 2. 创建DOM元素 -->
<div id="app">
<input type="text" v-model="person.name">
<div>{{person.name}}</div>
</div>
<script>
// 3.实例化vue
new Vue({
el: '#app',
data: {
person: {
name: '张三'
}
},
/**
* 监听对象必须是深度监听
* 深度监听的方法必须是handler
* 必须是deep:true
* 在深度监听中无法监听旧值,因为初始化设计没有旧值
* 在深度监听中只能获取新值
**/
watch: {
person: {
handler(newVal) {
console.log(newVal)
console.log(this.person.name)
},
deep: true, //深度 默认false
}
}
})
</script>
</body>
</html>
监听对象单个属性:
如果只想监听对象中单个属性的变化,则可以按照如下的方式定义 watch 侦听器:
const vm = new Vue({
el: '#app',
data: {
info:{ username: 'admin' }
},
watch: {
'info.username': {
hanlder(newVal) {
console.log(newVal)
}
}
}
})
1.7.3 computed 与 watch 的区别
- computed 能完成的功能,watch 都可以完成。
- watch 能完成的功能,computed 不一定能完成,例如:watch 可以进行异步操作。
两个重要的小原则:
1. 所被Vue管理的函数,最好写成普通函数,这样 this 的指向才是vm或组件实例对象。
2. 所有不被Vue所管理的函数(定时器的回调函数、ajax的回调函数等),最好写成箭头函数,这样this的指向才是vm或组件实例对象。
1.7.4 computed 与 methods 的区别
相同点:
- 都可以执行操作
- 结果都是一致的
不同点:
- methods:调用几次,就执行几次,当数据发生改变时,再次被执行
- computed:computed 有缓存功能,不管调用几次,最终使用的都是第一次的执行结果。当数据发生改变时,再次执行一次。
应用场景:
- methods 中执行的一般是事件操作
- computed 用来执行一些复杂的逻辑操作,并且有返回值
1.8 class 与 style 绑定
在应用界面中,某个(些)元素的样式是变化的,class/style 绑定就是专门用来实现动态样式效果的技术。
class样式:
语法:class="xxx"
xxx可以是字符串、对象、数组。
字符串写法适用于:类名不确定,要动态获取。
对象写法适用于:要绑定多个样式,个数不确定,名字也不确定。
数组写法适用于:要绑定多个样式,个数确定,名字也确定,但不确定用不用。
style样式:
语法:
:style="{fontSize: xxx}"
其中xxx是动态值。:style="[a,b]"
其中a、b是样式对象。
案例代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>绑定样式</title>
<script src="../js/vue.js"></script>
</head>
<body>
<!--
绑定样式:
1.class样式
写法:class="xxx" xxx可以是字符串、对象、数组。
字符串写法适用于:类名不确定,要动态获取。
对象写法适用于:要绑定多个样式,个数不确定,名字也不确定。
数组写法适用于:要绑定多个样式,个数确定,名字也确定,但不确定用不用。
2.style样式
:style="{fontSize: xxx}" 其中xxx是动态值。
:style="[a,b]" 其中a、b是样式对象。
-->
<div id="root">
<!-- 绑定class样式--字符串写法,适用于:样式类名不确定,需要动态指定 -->
<div class="basic" :class="mood" @click="changeMood">{{name}}</div><br/>
<!-- 绑定class样式--数组写法,适用于:要绑定的样式个数不确定、名字也不确定 -->
<div class="basic" :class="classArr">{{name}}</div><br/>
<!-- 绑定class样式--对象写法,适用于:要绑定的样式个数确定、名字也确定,但要动态决定用不用 -->
<div class="basic" :class="classObj">{{name}}</div><br/>
<!-- style--对象写法 -->
<div class="basic" :style="styleObj">{{name}}</div><br/>
<!-- 绑定style样式--数组写法 -->
<div class="basic" :style="styleArr">{{name}}</div><br/>
</div>
<script>
const vm = new Vue({
el:'#root',
data:{
name:'张三',
mood:'normal',
classArr:['box1','box2','box3'],
classObj:{
box1:false,
box2:false
},
styleObj:{
fontSize:'40px',
color:'red'
},
styleObj2:{
backgroundColor:'orange'
},
styleArr:[
{
fontSize:'40px',
color:'blue'
},
{
backgroundColor:'gray'
}
]
}
})
</script>
</body>
</html>
1.9 条件渲染
1.9.1 条件渲染指令
条件渲染指令用来辅助开发者按需控制 DOM 的显示与隐藏。条件渲染指令有如下两个,分别是:v-if
、v-show
1.9.1.1 v-if
v-else
:v-if 可以单独使用,或配合 v-else 指令一起使用v-else-if
:v-else-if 指令,顾名思义,充当 v-if 的 “else-if 块”,可以连续使用
适用于:切换频率较低的场景。
特点:不展示的 DOM 直接被移除。
<div id="app">
<!--
v-if="表达式"
v-else-if="表达式"
v-else="表达式"
以上三个指令在使用过程中,不能出现其他的内容,一旦出现,则指令不再生效
-->
<div v-if="score < 60"> 不及格 </div>
<!--<div>score的值为:{{score}}</div>-->
<div v-else-if="score >= 60 && score < 80"> 及格 </div>
<div v-else="score >= 80"> 优秀 </div>
</div>
<script>
// 3. 实例化vue
new Vue({
el:'#app',
data:{
score:60,
}
})
</script>
注意:
v-else-if
与v-else
指令必须配合v-if
指令一起使用,否则它将不会被识别,且要求结构不能被“打断”。
1.9.1.2 v-show
- 语法:
v-show="表达式"
- 适用于:切换频率较高的场景。
- 特点:不展示的DOM元素未被移除,仅仅是使用样式隐藏掉。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<script src="./vue.js"></script>
</head>
<body>
<div id="app">
<div v-show="score >= 60 && score < 80">(测试v-show)及格</div>
</div>
<script>
new Vue({
el:'#app',
data:{
score: 90,
}
});
</script>
</body>
</html>
1.9.2 v-if 与 v-show 的区别
实现原理不同:
-
v-if 指令会动态地创建或移除 DOM 元素,从而控制元素在页面上的显示与隐藏;
-
v-show 指令会动态为元素添加或移除 style=“display: none;” 样式,从而控制元素的显示与隐藏;
使用 v-if 时,元素可能无法获取到,而使用 v-show 一定可以获取到。
性能消耗不同:
v-if 有更高的切换开销,而 v-show 有更高的初始渲染开销。因此:
-
如果需要非常频繁地切换,则使用 v-show 较好
-
如果在运行时条件很少改变,则使用 v-if 较好
1.10 列表渲染
1.10.1 v-for
vue 提供了 v-for
列表渲染指令,用来辅助开发者基于一个数组来循环渲染一个列表结构。v-for 指令需要使用 item in items 形式的特殊语法,其中:
- items 是待循环的数组
- item 是被循环的每一项
data:{
list:[
{id: 1, name: 'zs'},
{id: 2, name: 'ls'},
]
}
//---------------------------------------------------
<ul>
<li v-for="item in list">姓名是:{{item.name}}</li>
</ul>
1.10.2 index 索引
v-for 指令还支持一个可选的第二个参数,即当前项的索引。语法格式为 (item, index) in items
,示例代码如下:
data:{
list:[
{id: 1, name: 'zs'},
{id: 2, name: 'ls'},
]
}
//---------------------------------------------------
<ul>
<li v-for="(item,index) in list">姓名是:{{item.name}},索引是:{{index}}</li>
</ul>
注意:v-for 指令中的 item 项和 index 索引都是形参,可以根据需要进行重命名。例如:(user, i) in userlist
1.10.3 key
当列表的数据变化时,默认情况下,vue 会尽可能的复用已存在的 DOM 元素,从而提升渲染的性能。但这种默认的性能优化策略,会导致有状态的列表无法被正确更新。
为了给 vue 一个提示,以便它能跟踪每个节点的身份,从而在保证有状态的列表被正确更新的前提下,提升渲染的性能。此时,需要为每项提供一个唯一的 key 属性:
用户列表区域
<ul>
加 key 属性的好处:
1. 正确维护列表的状态
2. 复用现有的 DOM 元素,提升渲染的性能
<li v-for="user in userlist" :key="user.id">
<input type="checkbox">
姓名:{{user.name}}
</li>
</ul>
key 的注意事项:
-
key 的值只能是字符串或数字类型
-
key 的值必须具有唯一性(即:key 的值不能重复)
-
建议把数据项 id 属性的值作为 key 的值(因为 id 属性的值具有唯一性)
-
使用 index 的值当作 key 的值没有任何意义(因为 index 的值不具有唯一性)
```姓名是:{{item.name}},索引是:{{index}}
注意:v-for 指令中的 item 项和 index 索引都是形参,可以根据需要进行重命名。例如 (user, i) in userlist
1.10.4 面试题:react、vue中的key有什么作用?(key的内部原理)
一、虚拟DOM中key的作用:
key是虚拟DOM对象的标识,当状态中的数据发生变化时,Vue会根据【新数据】生成【新的虚拟DOM】,
随后Vue进行【新虚拟DOM】与【旧虚拟DOM】的差异比较,比较规则如下:
二、对比规则:
1.旧虚拟DOM中找到了与新虚拟DOM相同的key:
(1) 若虚拟DOM中内容没变,直接使用之前的真实DOM。
(2) 若虚拟DOM中的内容变了,则生成新的真实DOM,随后替换掉页面中之前的真实DOM。
2.旧虚拟DOM中未找到与新虚拟DOM相同的key:
创建新的真实DOM,随后渲染到页面。
三、用index作为key可能会引发的问题:
1.若对数据进行:逆序添加、逆序删除等破坏顺序操作:
会产生没有必要的真实DOM更新 => 界面效果没问题,但效率低。
2.如果结构中还包含输入类的DOM:
会产生错误DOM更新 => 界面有问题。
四、开发中如何选择key?
1.最好使用每条数据的唯一标识作为key,比如id、手机号、身份证号、学号等唯一值。
2.如果不存在对数据的逆序添加、逆序删除等破坏顺序的操作,仅用于渲染列表用于展示,
使用index作为key是没有问题的。
1.11 内容渲染指令
内容渲染指令用来辅助开发者渲染 DOM 元素的文本内容。常用的内容渲染指令有如下 3 个:
v-text
{{ }}
v-html
1.11.1 v-text
用法示例:
<!-- 把 username 对应的值,渲染到第一个 p 标签中-->
<p v-text="username"></p>
<!-- 把 gender 对应的值,渲染到第二个 p 标签中 -->
<!-- 注意:第二个p标签中,默认的文本“性别”会被gender的值覆盖掉 -->
<p v-text="gender">性别</p>
<script>
const vm = new Vue({
el:'#app',
data:{
username:'张三',
gender:'女'
}
})
</script>
注意:v-text
指令会覆盖元素内默认的值。
1.11.2 v-html
v-text 指令和插值表达式只能渲染纯文本内容。如果要把包含 HTML 标签的字符串渲染为页面的 HTML 元素, 则需要用到 v-html
这个指令:
<!-- 假设 data中定义了名为 discription 的数据,数据的值为包含HTML 标签的字符串: -->
<!-- '<h5 style="color: red;">我在黑马程序员学习vue.js课程。</h5>' -->
<p> v-html="discription"></p>
<script>
const vm = new Vue({
el:'#app',
data:{
username:'zs',
gender:'男',
discription: '<h5 style="color: red;">我在黑马程序员学习vue.js课程。</h5>'
}
})
</script>
1.11.3 v-once
v-once:只渲染一次,当前元素及以下的所有子元素都只渲染一次
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<!-- 1. 引入vue.js -->
<script src='./vue.js'></script>
</head>
<body>
<!-- 2. 创建DOM元素 -->
<div id="app" v-once>
<button @click="changeName('朱天旭')">点击修改name的值</button>
<div>name的值为:{{name}}</div>
</div>
<script>
// 3.实例化vue
new Vue({
el:'#app',
data:{
name:'朱砂痣'
},
methods:{
changeName(name){
console.log(name)
this.name = name;
}
}
})
</script>
</body>
</html>
1.12 $set
在 vue 中,并不是任何时候数据都是双向绑定的。
由于 JavaScript 的限制,Vue不能检测对象属性的添加或删除
从文档得知,当数据没有被双向绑定的时候,我们就需要使用set了。
1.12.1 set 用法
解决数据没有被双向绑定我们可以使用 vm.$set 实例方法,
该方法是全局方法 Vue.set 的一个别名。
方法一:this.$set(目标对象, 索引值, 需要赋的值)
方法二:Vue.set(目标对象,下标/属性,值/属性值)
length 的问题还需要用 splice 方法。
vm.items.splice(newLength)
1.12.2 $set 操作数组
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<!-- 1. 引入vue.js -->
<script src="./vue.js"></script>
</head>
<body>
<!-- 2. 创建DOM元素 -->
<div id="app">
<div>{{arr}}</div>
<button @click="add">添加'🚀'</button>
</div>
<script>
let vm = new Vue({
el: '#app',
data: {
arr: ['🍎', '🍇', '🍑', '🍌']
},
methods: {
add() {
// 系统函数
// this.arr.push('🚀');
// this.arr[4] = '🚀'; // 不可取
// 方式一 this.$set(目标,下标,添加的值)
this.$set(this.arr,4,'🚀');
// 方式二:Vue.set(目标,下标,添加的值)
// Vue.set(this.arr, 4, '🚀');
console.log(this.arr);
}
}
})
</script>
</body>
</html>
1.12.3 $set 操作对象
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<!-- 1. 引入vue.js -->
<script src="./vue.js"></script>
</head>
<body>
<!-- 2. 创建DOM元素 -->
<div id="app">
<div>{{person}}</div>
<button @click="addSex">添加性别</button>
</div>
<script>
new Vue({
el: '#app',
data: {
person: {
name: '张三',
age: 20,
hobby: ['吃饭', '睡觉', '打豆豆'],
}
},
methods: {
addSex() {
// this.person.sex = '男'; //不可取
// 方式一:this.$set(目标,属性,添加的值)
// this.$set(this.person,'sex','男');
// 方式二:Vue.set(目标,属性,添加的值)
Vue.set(this.person, 'sex', '男');
console.log(this.person);
}
}
})
</script>
</body>
</html>
1.12.4 $set 操作数组对象
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<!-- 1. 引入vue.js -->
<script src="./vue.js"></script>
</head>
<body>
<!-- 2. 创建DOM元素 -->
<div id="app">
<button @click="getData">显示数据</button>
<ul>
<li v-for="(item,index) in list" :key="item.id">
{{item.name}} === {{item.sex}} <button @click="addSex(index)">添加性别</button>
</li>
</ul>
</div>
<script>
let arr = [
{ id: 1, name: '张三' },
{ id: 2, name: '李斯' }
]
new Vue({
el: '#app',
data: {
list: []
},
methods: {
getData() {
this.list = arr;
},
addSex(index) {
// this.list[index].sex = '男';
// 方式一:this.$set(目标,属性/下标,添加的值)
// let obj = this.list[index]; // {id:1,name:'张三'}
// obj.sex = '男'; // {id:1,name:'张三',sex:'男'}
// this.$set(this.list,index,obj); // [{id:1,name:'张三',sex:'男'}]
// 方式二:Vue.set(目标,属性/下标,添加的值)
// let obj = this.list[index];
// obj.sex = '男';
// Vue.set(this.list, index, obj);
// 方式三:
let obj = this.list[index];
obj.sex = '男';
this.list.splice(index, 1, obj);
console.log(this.list);
}
}
})
</script>
</body>
</html>
1.13 过滤器
1.13.1 概念
过滤器(Filters)是 vue 为开发者提供的功能,常用于文本的格式化。过滤器可以用在两个地方:插值表达式
和 v-bind
属性绑定。
过滤器应该被添加在 JavaScript 表达式的尾部,由 “管道符” 进行调用,示例代码如下:
<!-- 在双花括号中通过“管道符”调用 capitalize 过滤器,对 message 的值进行格式化 -->
<p>{{message | capitalize}}</p>
<!-- 在 v-bind 中通过“管道符”调用 formatId 过滤器,对 rawId 的值进行格式化 -->
<div v-bind:id="rawId | formatId"></div>
1.13.2 定义过滤器
在创建 vue 实例期间,可以在 filters 节点中定义过滤器,示例代码如下:
- 每一个过滤器的方法为自定义
- 系统自动注入一个参数:要过滤的对象
- 每一个过滤器方法中必须有return,其返回的结果被方法名所接收
const vm = new Vue({
el:'#app',
data:{
message:'hello vue.js',
info:'title info'
},
filters:{ // 在 filters 节点下定义“过滤器”
capitalize(str){ // 把首字母转为大写的过滤器
return str.charAt(0).toUpperCase() + str.slice(1)
}
}
})
1.13.3 全局过滤器
在 filters
节点下定义的过滤器,称为“私有过滤器”,因为它只能在当前 vm 实例所控制的 el 区域内使用。
如果希望在多个 vue 实例之间共享过滤器,则可以按照如下的格式定义全局过滤器:
// 全局过滤器 - 独立于每个 vm 实例之外
// Vue.filter() 方法接收两个参数:
// 第 1 个参数,是全局过滤器的“名字”
// 第 2 个参数,是全局过滤器的“处理函数”
Vue.filter('capitalize',(str)=>{
return str.charAt(0).toUpperCase() + str.slice(1) + '~~'
})
1.13.4 连续调用多个过滤器
过滤器可以串联地进行调用,例如:
<!-- 把 message 的值,交给 filterA进行处理 -->
<!-- 把 filterA 处理的结果,再交给 filterB 进行处理 -->
<!-- 最终把 filterB 处理的结果,作为最终的值渲染到页面上 -->
{{ message | filterA | filterB }}
示例代码如下:
<!-- 串联调用多个过滤器 -->
<p>{{text | capitalize | maxLength}}</p>
<script>
// 全局过滤器 – 首字母大写
Vue.filter('capitalize', (str) =>{
return str.charAt(O).toUpperCase() + str.slice(1) + '~~'
})
// 全局过滤器 – 控制文本的最大长度
Vue.filter('maxLength', (str) => {
if (str.length <= 10) return str
return str.slice(0,11) + '...'
})
</script>
1.13.5 过滤器传参
过滤器的本质是 JavaScript 函数,因此可以接收参数,格式如下:
<!-- arg1 和 arg2 是传递给 filterA 的参数 -->
<p>{{ message | filterA(arg1,arg2) }}</p>
<script>
// 过滤器处理函数的形参列表中:
// 第 1 个参数:永远都是"管道符"前面待处理的值
// 从第 2 个参数开始,才是调用过滤器时传递过来的 arg1 和 arg2 参数
Vue.filter('filterA',(msg,arg1, arg2) => {
// 过滤器的代码逻辑...
})
</script>
示例代码如下:
<!-- 调用 maxLength 过滤器时传参 -->
<p>{{text | capitalize | maxLength(5)}}</ p>
<script>
// 全局过滤器 - 首字母大写
Vue.filter('capitalize', (str) =>{
return str.charAt(O).toUpperCase() + str.slice(1) + '~~'})
//全局过滤器 – 控制文本的最大长度
Vue.filter('maxLength', (str, len = 10) => {
if(str.length <= len) return str
return str.slice(0,len) + '...'
})
</script>
1.13.6 封装时间过滤器
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<!-- 1. 引入vue.js -->
<script src="./vue.js"></script>
</head>
<body>
<!-- 2. 创建DOM元素 -->
<div id="app">
<ul>
<li v-for="item in news" :key="item.id">
<div>新闻标题: {{item.title}}</div>
<div>发布时间:{{item.time | timeFilter('x-x-x x:x:x')}}</div>
<div>发布时间:{{item.time | timeFilter('x-x-x')}}</div>
</li>
</ul>
</div>
<script>
// 时间过滤器
// 时间格式:xx/xx/xx x:x:x || xxx-xx-xx
Vue.filter('timeFilter', (e, type) => {
let date = new Date(e);
let y = date.getFullYear();
let m = (date.getMonth() + 1 + '').padStart(2, '0');
let d = (date.getDate() + '').padStart(2, '0');
let h = (date.getHours() + '').padStart(2, '0');
let i = (date.getMinutes() + '').padStart(2, '0');
let s = (date.getSeconds() + '').padStart(2, '0');
if (type === 'x-x-x x:x:x') {
return `${y}-${m}-${d} ${h}:${i}:${s}`;
} else if (type === 'x-x-x') {
return `${y}-${m}-${d}`;
}
})
// 3.实例化vue
new Vue({
el: '#app',
data: {
news: [
{ id: 1, title: '哈萨克斯坦首都街头飘扬中国红', time: 1663224746000 },
{ id: 2, title: '超六成专科生月薪低于5000元', time: 1665224746000 },
{ id: 3, title: '公安部:车检周期10月1日起放宽', time: 1667224746000 },
]
}
})
</script>
</body>
</html>
1.14 生命周期
1.14.1 定义
生命周期(Life Cycle)是指一个组件从创建 -> 运行 -> 销毁
的整个阶段,强调的是一个时间段。
生命周期函数:是由 vue 框架提供的内置函数,会伴随着组件的生命周期,自动按次序执行。
注意:生命周期强调的是时间段,生命周期函数强调的是时间点
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WJl0JwL9-1666016537531)(图片/image-20220921195005642.png)]
1.14.2 钩子函数
-
beforeCreate
/* 创建之前 什么都是undefined 不能操作元素 */ beforeCreate(){ console.group('==beforeCreate=='); console.log('el的值',this.$el); console.log('data的值',this.$data); console.log('name的值',this.name); console.groupEnd(); }
-
created
/* 创建完成 1.不能操作元素 2.el还是undefined 3.此时数据已经存在 4.作用:实现异步请求 */ created(){ console.group('==created=='); console.log('el的值',this.$el); console.log('data的值',this.$data); console.log('name的值',this.name); console.groupEnd(); }
-
beforeMount
/* 挂载之前:beforeMount 1.找到el挂载点 2.此时数据已经存在 3.实现异步请求 4.可以操作元素 5.视图中数据未解析 */ beforeMount(){ console.group('==beforeMount=='); console.log('el的值',this.$el); console.log('data的值',this.$data); console.log('name的值',this.name); console.groupEnd(); }
-
mounted(重点)
/* 挂载完成:mouted 1.数据已经获取 2.元素挂载点找到 3.可以操作元素节点 作用:异步请求 轮播图 定时器 延时器 订阅等等 */ mounted(){ console.group('==mounted=='); console.log('el的值',this.$el); console.log('data的值',this.$data); console.log('name的值',this.name); console.log(document.querySelector('h2')); console.groupEnd(); },
-
beforeUpdate
/* 更新之前 数据已经是最新数据,指的是视图再次更新之前 */ beforeUpdate(){ console.group('==beforeUpdate=='); console.log('name的值',this.name); console.groupEnd(); },
-
updated
/* 更新完成 数据已经是最新数据,指的是视图更新完成 */ updated(){ console.group('==updated=='); console.log('name的值',this.name); console.groupEnd(); }
-
beforeDestroy
/* 销毁之前 作用:销毁数据 */ beforeDestroy(){ console.group('==beforeDestroy=='); console.groupEnd(); }
-
destroyed
/* 销毁完成 */ destroyed(){ console.group('==destroyed=='); console.groupEnd(); }
1.15 template 和 render 优先级问题
当 el、template、render 三个选项同时存在时,优先级:render > template > el
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<!-- 1. 引入vue.js -->
<script src="./vue.js"></script>
</head>
<body>
<!-- 2. 创建DOM元素 -->
<div id="app">
<h2> {{name}}</h2>
</div>
<script>
/**
* 当el,template,render三个选项同时存在时,存在优先级 render > template > el
*/
new Vue({
el: '#app',
template: '<h2>朱砂痣</h2>',
/**
* 钩子函数:
* 系统自动注入一个参数:createElement
* 返回值 返回创建的元素信息
*/
render(createElement) {
/*
参数一:创建的元素节点
参数二:内容
*/
return createElement('h2', '创建的标签')
},
data: {
name: '张三丰'
},
methods: {
}
})
</script>
</body>
</html>