一.data属性
data属性是传入一个函数,并且该函数需要返回一个对象:
在Vue2.x的时候,也可以传入一个对象 (虽然官方推荐是一个函数)。
在Vue3.x的时候,必须传入一个函数,否则就会直接在浏览器中报错。
data中返回的对象会被Vue的响应式系统劫持,之后对该对象的修改或者访问都会在劫持中被处理。
二.methods属性
是一个对象,通常我们会在这个对象中定义很多的方法:
这些方法可以被绑定到模板中;
在该方法中,我们可以使用this关键字来直接访问到data中返回的对象的属性;

事实上Vue的源码当中就是对methods中的所有函数进行了遍历,并且通过bind绑定了this:
1、将传入的methods进行了遍历,通过种种方式,会拿到key,再通过key从methods里面拿到methodHandler这个真实的函数。
2、再通过menthodsHandler,用bind函数绑定publicThis(当前实例的代理对象)

三.v--bind
1、绑定属性用法:动态绑定一个或多个attribute,或者向另一个组件传递props值。
<div id="app">
<!-- v-bind绑定属性 -->
<!-- 1.绑定img的src属性 -->
<img v-bind:src="imgUrl" alt="">
<!-- 2.绑定a的超连接 href属性-->
<a :href="href">百度一下</a>
<h2>{{message}}</h2>
</div>
<script src="./lib/vue.js"></script>
<script>
// 1.创建app
const app = Vue.createApp({//vue全局对象。调用Vue.createApp(),返回一个函数。
data: function () {
return {
message: "hello vue",
imgUrl: "https://gimg3.baidu.com/search/src=http%3A%2F%2Fpics6.baidu.com%2Ffeed%2Ff31fbe096b63f624a0b8d792a22897f31b4ca336.jpeg%40f_auto%3Ftoken%3D340c4cf24c2b0013b1753942bde64287&refer=http%3A%2F%2Fwww.baidu.com&app=2021&size=f360,240&n=0&g=0n&q=75&fmt=auto?sec=1672506000&t=fbc712de714ce3673a2226e733a3fbb1",
href: "http://baidu.com"
}
},
})
// 2.挂载app
app.mount("#app");//app调用mount函数,挂载到#app里面。底层通过querySelector找到div元素
2、v-bind绑定class属性
对象语法:
<div id="app">
<!-- 1.基本绑定clalss -->
<h2 :class="classes">{{message}}</h2>
<!-- 2. 动态绑定class可以写对象语法-->
<button :class=" isActive ? 'active':'' " @click="btnClick">我是按钮</button>
<!-- 2.1对象语法的基本使用 -->
<button :class=" {active:isActive} " @click="btnClick">我是按钮二</button>
<!-- 2.2对象语法的多个键值对 -->
<button :class="{active:isActive,why:true,kobe:false}" @click="btnClick">按钮</button>
<!-- 2.3动态绑定的class的可以和普通的class的并列使用 -->
<button class="abc cba" :class="{active:isActive,why:true,kobe:false}" @click="btnClick">按钮</button>
<!-- 2.4直接调用getDynaicClass函数,拿到对应对象的结果 -->
<button class="abc cba" :class="getDynaicClass()" @click="btnClick">按钮</button>
</div>
<script src="./lib/vue.js"></script>
<script>
// 1.创建app
const app = Vue.createApp({//vue全局对象。调用Vue.createApp(),返回一个函数。
data: function () {
return {
message: "hello vue",
classes: "abc cba nba",
isActive: false,
}
},
methods: {
btnClick() {
this.isActive = !this.isActive;
console.log(this.isActive);
},
getDynaicClass() {
// 根据boolean类型为true还是false决定class是否要绑定过来。
return { active: this.isActive, why: true, kobe: false }
}
},
})
// 2.挂载app
app.mount("#app");//app调用mount函数,挂载到#app里面。底层通过querySelector找到div元素
数组语法:
<!-- 3.动态绑定的classs是可以写数组语法 -->
<h2 :class="['abc','sbc']">Hello Array</h2>
<h2 :class="['abc',classNmae]">Hello Array</h2>
<h2 :class="['abc',classNmae,isActive?'active':'']">Hello Array</h2>
<!--优化 -->
<h2 :class="['abc',classNmae,{active:isActive}]">Hello Array</h2>
3、v-bind绑定style属性:CSS property名可以用驼峰式 (camelCase)或短横线分隔(kebab-case,记得用引号括起来来命名)。
<div id="app">
<!-- 1.普通html写法 -->
<h2 style="color: red;font-size: 30px;">哈哈哈1</h2>
<!-- 2.style中的某些值,来自data中 -->
<!-- 2.1动态绑定style,在后面更上对象类型,单引号的使用 -->
<h2 :style="{color:fontcolor,'font-size':'30px'}">哈哈哈1</h2>
<!-- 2.2动态的绑定属性,这个属性是一个对象 -->
<h2 :style="objStyle">呵呵哈哈哈</h2>
<!-- 3.style的数组语法 -->
<h2 :style="[objStyle,{backgroudColor:'purple'}]">kkkk</h2>
</div>
静态绑定内联样式
v-bind:style 的对象语法十分直观,CSS属性名可以用 驼峰式 (camelCase) 或 短横线分隔 (kebab-case,记得用引号括起来) 来命名:
<div v-bind:style="{ color: activeColor, fontSize: fontSize + 'px' }"></div>
data: {
activeColor: 'red',
fontSize: 30
}
三元判断的对象
<div :style="{color:(index == 0 ? conFontColor : '#000')}"></div>
- 数组
三元多属性
2025年2月19日更新
:style="[
{height:(warnData.length > 0?'calc(100% - 54px - 42px)':'calc(100% - 54px)')},
{color:'#fff'}
]"
写成计算属性
:style="boxStyle"
<template>
<div class="PlatformDisplay">
<dv-border-box-11 title="平台展示" :style="boxStyle">
<div class="icon" @click="$router.push('/')" title="返回首页">
<i class="el-icon-s-home" style="color: white"></i>
</div>
<div class="main">
<div class="header">
<div class="left">
<div v-for="(item, index) in displayOptions1" :key="index">
<el-button type="primary" size="small" @click="changeIndex(item.index)" :plain="showIndex !== item.index">
{{ item.label }}
</el-button>
</div>
</div>
</div>
</div>
</dv-border-box-11>
</div>
</template>
<script>
export default {
data() {
return {
showIndex: 1,
displayOptions1: [
// 假设这里是你的按钮选项数组
{ index: 1, label: '选项1' },
{ index: 2, label: '选项2' },
// 更多选项...
],
};
},
computed: {
//在computed中写计算属性
boxStyle() {
return {
height: this.showIndex === 1 ? 'calc(100vh + 190px)' : 'calc(100vh + 90px)',
position: 'relative',
};
},
},
methods: {
changeIndex(index) {
this.showIndex = index;
},
},
};
</script>
其他使用案例
- 将样式绑定到元素上
在模板中,使用 :style 绑定 dynamicHeightStyle 到 div 元素上,这样 div 的高度就会根据 headerHeight 和 footerHeight 的值动态计算。
- 封装成独立的函数
如果你希望将计算高度的逻辑封装成一个独立的函数,可以在 methods 中定义一个函数,然后在 computed 或模板中调用它。
<template>
<div :style="getDynamicHeightStyle(headerHeight, footerHeight)">
<!-- 你的内容 -->
</div>
</template>
<script>
export default {
data() {
return {
headerHeight: 100,
footerHeight: 50,
};
},
methods: {
getDynamicHeightStyle(headerHeight, footerHeight) {
return {
height: `calc(100vh - ${headerHeight + footerHeight}px)`,
};
},
},
};
</script>
<style scoped>
/* 你的样式 */
</style>
4、v-bind绑定对象
<div id="app">
<h2 :name="name" :age="18" :height="1.88">Hello World</h2>
<!-- v-bind对象 ,会自动的遍历对象的所有属性,把他们作为属性,添加到当前元素上面-->
<h2 v-bind="props">hello 222</h2>
</div>
5、v-memo的使用
<div id="app">
<!-- v-memo,当name发生改变时,数据才发生更新。用于性能优化 -->
<div v-memo="[name]">
<h2>姓名:{{name}}</h2>
<h2>年龄:{{age}}</h2>
<h2>身高:{{height}}</h2>
</div>
<button @click="updatechange">改变</button>
</div>
四.声明式编程和命令式编程的区别
1、命令式编程关注的是 “how to do”自己完成整个how的过程。我们每完成一个操作,都需要通过JavaScript编写一条代码,来给浏览器一个指令,这样的编写代码的过程,我们称之为命令式编程。在早期的原生JavaScript和jQuery开发的过程中,我们都是通过这种命令式的方式在编写代码的。
2、声明式编程关注的是 “what to do”,由框架(机器)完成 “how”的过程。们会在createApp传入的对象中声明需要的内容,模板template、数据data、方法methods,这样的编写代码的过程,我们称之为是声明式编程。目前Vue、React、Angular、小程序的编程模式,我们称之为声明式编程。
五.v-on绑定事件
1、v-on的使用:
缩写:@
预期:Function | Inline Statement | Object
参数:event
修饰符:v-on支持修饰符,修饰符相当于对事件进行了一些特殊的处理:
<div class="box" @click="divClick">
<!-- .stop添加修饰符,阻止事件冒泡 内部调用 event.stopPropagation(),-->
<button @click.stop="btn1Click">按钮</button>
</div>
.stop - 调用 event.stopPropagation(),阻止事件冒泡。
.prevent - 调用 event.preventDefault(),阻止默认行为。
.capture - 添加事件侦听器时使用 capture 模式。
.self - 只当事件是从侦听器绑定的元素本身触发时才触发回调。
.{keyAlias} - 仅当事件是从特定键触发时才触发回调。
.once - 只触发一次回调。
.left - 只当点击鼠标左键时触发。
.right - 只当点击鼠标右键时触发。
.middle - 只当点击鼠标中键时触发。
.passive - { passive: true } 模式添加侦听器
用法:绑定事件监听
<div id="app">
<!-- 1.基本的写法 -->
<div class="box" v-on:click="divClick"></div>
<!-- 2.语法糖写法 -->
<div class="box" @click="divClick"></div>
<!-- 3.绑定的方法的位置,也可以写成一个表达式 -->
<h2>{{counter}}</h2>
<button @click="increment">+1</button>
<button @click="counter++">+1</button>
<!-- 4.绑定其他方法 -->
<div class="box" @click="divClick" @mousemove="divmouseMove"></div>
<!-- 5.元素绑定多个事件(绑定的事件名称和方法) -->
<div class="box" v-on="{click:divClick,mousemove:divmouseMove}"></div>
</div>
2、默认传递event对象
<div id="app">
<!-- 1.默认传递event事件 -->
<button @click="btn1Click">按钮</button>
<!-- 2.明确的参数 -->
<!-- 'why',18作为参数传递到methods中的btn2Click() -->
<button @click="btn2Click('why',18)">按钮</button>
<!-- 3.自己的参数和event对象 -->
<!-- 在模板中想要明确的获取event对象:$event -->
<button @click="btn3Click('why',age,$event)">按钮</button>
</div>
<script src="../lib/vue.js"></script>
<script>
// 1.创建app
const app = Vue.createApp({//vue全局对象。调用Vue.createApp(),返回一个函数。
data: function () {
return {
message: "hello vue",
age: 19,
}
},
methods: {
// 1.默认参数event对象
// 总结:如果在绑定事件的时候,没有传递任何参数,那么event对象会默认传递进来
btn1Click(event) {
console.log("btn1Click", event);
},
btn2Click(name, age) {
console.log("btn2Click", name, age);
},
btn3Click(name, age,event) {
console.log("btn3Click", name, age,event);
}
},
})
六.条件渲染
1、v-if的基本使用
<!-- v-if="条件"-->
<!-- 判断info有没有key,返回一个数组 -->
<div class="info" v-if="Object.keys(info).length > 0">
<h2>个人信息</h2>
<ul>
<li>姓名:{{info.name}}</li>
<li>年龄:{{info.age}}</li>
</ul>
</div>
v-if的渲染原理:
v-if是惰性的;
当条件为false时,其判断的内容完全不会被渲染或者会被销毁掉;
当条件为true时,才会真正渲染条件块中的内容;
2、v-show和v-if的用法看起来是一致的,也是根据一个条件决定是否显示元素或者组件:
首先,在用法上的区别:
v-show是不支持template;
v-show不可以和v-else一起使用;
其次,本质的区别:
v-show元素无论是否需要显示到浏览器上,它的DOM实际都是有存在的,只是通过CSS的display属性来进行切换;
v-if当条件为false时,其对应的原生压根不会被渲染到DOM中,根本不存在元素;
开发中如何进行选择呢?
如果我们的原生需要在显示和隐藏之间频繁的切换,那么使用v-show;
如果不会频繁的发生切换,那么使用v-if;
3、template元素可以当做不可见的包裹元素,并且在v-if上使用,但是最终template不会被渲染出来:
有点类似于小程序中的block
七.列表渲染
1、v-for的基本格式是"item in 数组":
数组通常是来自data或者prop,也可以是其他方式;
item是我们给每项元素起的一个别名,这个别名可以自定来定义;
我们知道,在遍历一个数组的时候会经常需要拿到数组的索引:
如果我们需要索引,可以使用格式: "(item, index) in 数组";
注意上面的顺序:数组元素项item是在前面的,索引项index是在后面的;
2、v-for也支持遍历对象,并且支持有一二三个参数:
一个参数: "value in object",为value;
二个参数: "(value, key) in object",value和key;
三个参数: "(value, key, index) in object",value、key和索引index;
<div id="app">
<!-- 遍历对象 -->
<ul>
<li v-for="(value,key ,index) in info">{{value}}-{{key}}-{{index}}</li>
</ul>
</div>
data() {
return {
message: "hello vue",
info: { name: "why", age: 19, height: 1.99 }
}
},

v-for同时也支持数字的遍历:
每一个item都是一个数字;
v-for也可以遍历其他可迭代对象(Iterable)
八.数组更新检测
Vue 将被侦听的数组的变更方法进行了包裹,所以它们也将会触发视图更新。
这些被包裹过的方法包括:
push()
pop()
shift()
unshift()
splice()
sort()
reverse()
替换数组的方法
上面的方法会直接修改原来的数组;
但是某些方法不会替换原来的数组,而是会生成新的数组,比如 filter()、concat() 和 slice();
九.v-for中的key是什么作用?
这个key属性有什么作用呢?我们先来看一下官方的解释:
key属性主要用在Vue的虚拟DOM算法,在新旧nodes对比时辨识VNodes;
如果不使用key,Vue会使用一种最大限度减少动态元素并且尽可能的尝试就地修改/复用相同类型元素的算法;
而使用key时,它会基于key的变化重新排列元素顺序,并且会移除/销毁key不存在的元素;
1、认识VNode
我们先来解释一下VNode的概念:
因为目前我们还没有比较完整的学习组件的概念,所以目前我们先理解HTML元素创建出来的VNode;
VNode的全称是Virtual Node,也就是虚拟节点;
事实上,无论是组件还是元素,它们最终在Vue中表示出来的都是一个个VNode;
VNode的本质是一个JavaScript的对象;
(1).将div元素解析成VNode,如下图所示:(本质上还是一个javascript对象)

(2).将模板里的每一个元素,转化成VNode,再将VNode,进行解析,创建对应元素,并添加属性。最终将VNode转化成真实的DOM元素。

2、虚拟DOM
如果我们不只是一个简单的div ,而是有一大堆的元素,那么它们应该会形成一个VNode Tree:

里面的每一个元素,都会创建对应的vnode,再让children属性形成嵌套关系,最终vnode对vnode进行解析,会形成一棵树结构。
vnode-->树结构-->虚拟(virtual)DOM-->真实DOM树

添加虚拟DOM的主要原因:
(1)、方便进行diff算法。
(2)、有虚拟DOM,方便对我们的当前所写的代码进行跨平台。

3、key的作用
(1)、第一次形成的虚拟DOM,一旦数据发送改变,就会根据最新的数据创建第二个虚拟DOM,创建完第二个虚拟DOM之后,新旧虚拟DOM对比,有没有发送变化,如果没有发生变化,等到准备操作真实DOM的时候,没有必要去改变原来的数据。
如果没有设置key的话,(不知道可以重复利用元素)会重复利用元素,改变元素(比如li标签中的换成F),接下来的所有元素也需要改变,最后少一个元素,需要新建一个元素,算法效率低。
绑定key的目的,让vue可以更加快速的识别新旧节点是否是同一个东西。

(2)、如下图所示我们可以确定的是,这次更新对于ul和button是不需要进行更新,需要更新的是我们li的列表:
<div id="app">
<button @click="insert">插入F</button>
<ul>
<!-- 动态绑定key,key要求唯一:id -->
<li v-for="item in letters" :key="item">{{item}}</li>
</ul>
</div>
<script src="../lib/vue.js"></script>
<script>
// 1.创建app
const app = Vue.createApp({//vue全局对象。调用Vue.createApp(),返回一个函数。
data() {
return {
letters: ["a", "b", "c", "d", "e"]
}
},
methods: {
insert() {
this.letters.splice(2, 0, "f");//在2(b)的位置后面插入
}
},
})
// 2.挂载app
app.mount("#app");//app调用mount函数,挂载到#app里面。底层通过querySelector找到div元素
</script>
在Vue中,对于相同父元素的子元素节点并不会重新渲染整个列表;
因为对于列表中 a、b、c、d它们都是没有变化的;
在操作真实DOM的时候,我们只需要在中间插入一个f的li即可;
(4)、那么Vue中对于列表的更新究竟是如何操作的呢?
Vue事实上会对于有key和没有key会调用两个不同的方法;
(1)、有key,那么就使用 patchKeyedChildren方法,会尽可能的复用所有的节点,性能更高;


第一步的操作是从头开始进行遍历、比较:
a和b是一致的会继续进行比较;
c和f因为key不一致,所以就会break跳出循环;

第二步的操作是从尾部开始进行遍历、比较

第三步是如果旧节点遍历完毕,但是依然有新的节点,那么就新增节点:
a节点,b节点进行复用,c,d节点也进行复用,直接在相应的地方新增节点,并且在真实DOM里面新增节点。
第四步是如果新的节点遍历完毕,但是依然有旧的节点,那么就移除旧节点:

第五步是最特色的情况,中间还有很多未知的或者乱序的节点:
如果是乱序的话,也会就可能的复用节点。

(2)、没有key,那么久使用 patchUnkeyedChildren方法;

我们会发现上面的diff算法效率并不高:
c和d来说它们事实上并不需要有任何的改动;
但是因为我们的c被f所使用了,所有后续所有的内容都要一次进行改动,并且最后进行新增;
a复用,b复用,c改成新的值,d也改成新的值,最后新增一个节点。

十.computed计算属性
(1)、什么是计算属性呢?
官方并没有给出直接的概念解释;
而是说:对于任何包含响应式数据的复杂逻辑,你都应该使用计算属性;
计算属性将被混入到组件实例中
所有 getter 和 setter 的 this 上下文自动地绑定为组件实例;
(2)、计算属性的用法:
选项: computed
类型: { [key: string]: Function | { get: Function, set: Function } }
<div id="app">
<!-- 通过插值语法进行拼接 -->
<!-- 1.拼接名字 ,computed计算属性fullName不用加小括号-->
<h2>{{fullNmae}}</h2>
<h2>{{fullNmae}}</h2>
<!-- 2.显示分数等级 -->
<h2>{{scoreLevel}}</h2>
<!-- 3.反转单词显示文本 -->
<h2>{{reverseMessage}}</h2>
</div>
<script src="../lib/vue.js"></script>
<script>
// 1.创建app
const app = Vue.createApp({//vue全局对象。调用Vue.createApp(),返回一个函数。
data() {
return {
firstName: "kobe",
listName: "brant",
score: 80,
message: "my name is www",
}
},
methods: {
},
computed: {
fullNmae: function () {
return this.firstName + " " + this.listName;
},
scoreLevel() {
return this.score >= 60 ? "及格" : "不及格"
},
reverseMessage(){
return this.message.split(" ").reverse().join(" ");
}
}
})
(3)、computed计算属性VS methods的。
官方说明:涉及到响应式复杂逻辑统一使用计算属性computed。 计算属性有缓存的,这是因为计算属性会基于它们的依赖关系进行缓存;
在数据不发生变化时,计算属性是不需要重新计算的;
但是如果依赖的数据发生变化,在使用时,计算属性依然会重新进行计算;
<div id="app">
<!-- 1.methods -->
<h2>{{getFullName()}}</h2>
<h2>{{getFullName()}}</h2>
<h2>{{getFullName()}}</h2>
<!-- 2.computed -->
<h2>{{fullName}}</h2>
<h2>{{fullName}}</h2>
<h2>{{fullName}}</h2>
</div>
<script src="../lib/vue.js"></script>
<script>
// 1.创建app
const app = Vue.createApp({//vue全局对象。调用Vue.createApp(),返回一个函数。
data() {
return {
message: "hello vue",
firstName: "kobe",
listName: "brant",
score: 80,
message: "my name is www",
}
},
methods: {
getFullName() {
console.log(" getFullName()-----");
return this.firstName + " " + this.listName
}
},
computed: {
fullName() {
console.log("computed-----");
return this.firstName + " " + this.listName
}
}
})
(4)、计算属性的get和set
<div id="app">
<h2>{{fullName}}</h2>
<button @click="btnClick">设置fullName</button>
</div>
<script src="../lib/vue.js"></script>
<script>
// 1.创建app
const app = Vue.createApp({//vue全局对象。调用Vue.createApp(),返回一个函数。
data() {
return {
message: "hello vue",
firstName: "kobe",
listName: "brant",
score: 80,
message: "my name is www",
}
},
computed: {
// 语法糖
fullname() {
return this.firstName + " " + this.listName
},
// 完整写法
fullName: {
get: function () {
return this.firstName + " " + this.listName
},
set: function (value) {
const names = value.split(" ");
this.firstName = names[0];
this.listName = names[1];
}
},
},
methods: {
btnClick() {
// 可以打印,更改fullname的值
console.log(this.fullName);
this.fullName = "www bbb"
}
},
})
十一.watch侦听器
watch在javascript中逻辑中监听到当前的数据发生了变化
1、侦听器的用法如下:
选项: watch
类型: { [key: string]: string | Function | Object | Array}
<script>
// 1.创建app
const app = Vue.createApp({//vue全局对象。调用Vue.createApp(),返回一个函数。
data() {
return {
message: "hello vue",
info: { name: "why", age: 19 },
}
},
methods: {
changeMessage() {
this.message = "你好啊!"
this.info = { name: "kobe" }
}
},
watch: {
// 1.默认有两个参数newVlaue,oldVlaue
message(newValaue, oldVlaue) {
console.log(newValaue, oldVlaue);
console.log("message数据发生了变化~", this.message);//通过this.message获取当前的最新的message
},
info(newValaue, oldVlaue) {//newValaue本质上是一个proxy对象
// 2.如果是对象类型,那么拿到的是代理对象
console.log("info发生变化~", newValaue, oldVlaue);
console.log(newValaue.name, oldVlaue.name);//获取代理对象的值
// 3.获取原始对象
console.log({ ...newValaue });//方法一:对原来的对象做一个展开,将所有属性展开,将所有属性取出来,放到一个新的对象里面。
console.log(Vue.toRaw(newValaue));//方法二:通过toRaw拿到最原始的数据
}
}
})
// 2.挂载app
app.mount("#app");

2、侦听器的配置选项
1、默认情况下,watch只是在侦听info的引用变化 ,对于内部属性的变化是不会做出响应的:
将deep设置为true进行深度监听。
<div id="app">
<h2>{{info.name}}</h2>
<button @click="changeInfo">按钮</button>
</div>
<script src="../lib/vue.js"></script>
<script>
// 1.创建app
const app = Vue.createApp({//vue全局对象。调用Vue.createApp(),返回一个函数。
data() {
return {
message: "hello vue",
info: { name: "why", age: 19 },
}
},
methods: {
changeInfo() {
// 1.创建新对象复制给info
// this.info = { name: "kobe" }
// 2.直接修改原对象某一个属性
this.info.name = "kobe";
}
},
watch: {
// 1、默认watch不会进行深度监听
// info(newValaue, oldVlaue) {
// console.log(newValaue, oldVlaue);
// console.log("info数据发生了变化~");//通过this.message获取当前的最新的message
// },
//2、 进行深度监听
info: {//只是在改变info的属性
handler(newVlaue, oldVlaue) {
console.log("info改变", newVlaue, oldVlaue);
},
// 监听器选项
deep: true,//info进行深度监听
// 第一次渲染直接执行一次监听器
immediate: true,
}
}
})
// 2.挂载app
app.mount("#app");
2、Vue的$watch监听
// 1.创建app
const app = Vue.createApp({//vue全局对象。调用Vue.createApp(),返回一个函数。
data() {
return {
message: "hello vue",
}
},
methods: {
changeMessage() {
this.message = "你好啊~"
}
},
// 生命周期的回调函数:当前的组件被创建时自动执行
// 一般在该函数中,会进行网络请求
created() {
console.log("created");
this.$watch("message", (newValue, oldVlaue) => {
console.log("message变化~",newValue, oldVlaue);
}, { deeep: true })
}
})