vue简介

vue中文官网

动态构建用户界面的渐进式 JavaScript 框架

vue的特点:

  1. 遵循MVVM模式
  2. 采用组件化模式,提高代码复用率,让代码更好维护
  3. 声明式编码,无需直接操作DOM,提高开发效率,编码简洁、体积小,运行效率高
  4. 本身只关注UI,也可以引入其他三方库开发项目
  5. 使用虚拟DOM+优秀的Diff算法,尽量复用DOM节点

环境准备

1.导入vue
  1. 在页面以CDN包的形式导入

    <!-- cdn链接 -->
    <script src="https://cdn.jsdelivr.net/npm/vue@2.7.16/dist/vue.js"></script> <!--生产环境,推荐链接到一个明确的版本号和构建文件,以避免新版本造成的不可预期的破坏 -->
    <script src="https://cdn.jsdelivr.net/npm/vue@2.7.16"></script>
  2. 下载Js源代码文件通过script导入

    <script src="本地源代码路径"></script>
  3. npm

    在用 Vue 构建大型应用时推荐使用 npm 安装 。npm 能很好地和诸如webpack 或 Rollup 模块打包器配合使用

    # 最新稳定版
    npm install vue@next
  4. 脚手架工具(CLI)

    Vue 提供了一个官方的 CLI,为单页面应用 (SPA) 快速搭建繁杂的脚手架。它为现代前端工作流提供了功能齐备的构建设置。只需要几分钟的时间就可以运行起来,并带有热重载、保存时 lint 校验,以及生产环境可用的构建版本

    npm install -g @vue/cli
  5. Vite

    Vite 是尤雨溪新开发的一个 web 开发构建工具,由于其原生 ES 模块导入方式,可以实现闪电般的冷服务器启动,通过在终端中运行以下命令,可以使用 Vite 快速构建 Vue 项目

    npm init vite@latest <project-name> --template vue
    cd <project-name>
    npm install
    npm run dev
2.vue全局配置

Vue.config 是一个对象,包含 Vue 的全局配置,可以在启动应用之前修改

配置详解

    // 阻止 vue 在启动时生成生产提示
Vue.config.productionTip = false

vue实例

  • 想让Vue工作,就必须创建一个Vue实例,且要传入一个配置对象
  • 容器里的代码依然符合html规范,只不过混入了一些特殊的Vue语法
  • 容器里的代码被称为Vue模板
  • Vue实例和容器是一一对应的,一个vue实例只能和一个实例对应
  • 真实开发中只有一个Vue实例,并且会配合着组件一起使用
  • {{插值语法}}中可以写js表达式(1+1、Data.now()),且表达式可以自动读取到data中的所有属性
<body>
<!--创建ID为root的容器 -->
<div id="root"> <!-- 插值语法,关联创建的vue实例data对象中的name字段 -->
<h1>{{name}}</h1>
</div> </body>
<script>
// 阻止 vue 在启动时生成生产提示
Vue.config.productionTip = false // 创建Vue实例,参数是一个配置对象
new Vue({
// el是element的缩写,el用于指定当前Vue实例为哪个容器服务,值通常为css选择器字符串
// 也可以使用el:document.getElementById("root")
// 关联ID是root的容器
el:"#root",
// data是用于存储数据,数据供el指定的容器去使用
data:{
name:"vue"
}
}) </script>

模版语法

Vue模板语法有2大类:

  1. 插值语法:

    功能:用于解析标签体内容。

    写法:{{xxx}},xxxjs表达式,且可以直接读取到data中的所有属性。

  2. 指令语法:

    功能:用于解析标签(标签属性、标签体内容、绑定事件等等)

    ​ 写法:Vue中有很多的指令且形式都是:v-xxxx:表达式, xxx是具体的指令,指令中同样写js表达式

<body>
<!--创建ID为root的容器 -->
<div id="root"> <!-- 插值语法-->
<h1>{{name}}</h1>
<!--指令语法-->
<!-- v-bind表示绑定,将data的url绑定给href,使用v-bind之后href的""就不再是字符串,而是js表达式 -->
<!-- 等同于 <h2><a href="https://www.baidu.com">百度一下</a></h2> -->
<h2><a v-bind:href="url">百度一下</a></h2>
<!-- v-bind简写形式,直接使用: -->
<h2><a :href="url">百度一下简写</a></h2> </div> </body>
<script> new Vue({
el: "#root",
data: {
name: "vue",
url: "https://www.baidu.com"
}
}) </script>

数据绑定

Vue中有2种数据绑定的方式:

  1. 单向绑定(v-bind):数据只能从data流向页面。
  2. 双向绑定(v-model):数据不仅能从data流向页面,还可以从页面流向data。
    • 双向绑定一般都应用在表单类元素(输入类元素)
    • v-model:value 可以简写为 v-model,因为v-model默认收集的就是value值
<body>
<div id="root"> 单向数据绑定: <input type="text" v-bind:value="name">
单向数据绑定简写: <input type="text" :value="name">
<br>
双向数据绑定: <input type="text" v-model:value="info.category">
<br>
双向数据绑定简写: <input type="text" v-model="info.category"> <!-- 双向数据绑定-有一处地方数据发生变化,所有引用的地方都会发生变化。
当数据模型中的数据发生变化时,与之绑定的视图会自动更新以反映新的数据状态;
反之,当用户在视图层通过交互操作(如在输入框中输入内容、选择下拉菜单选项等)改变了数据,数据模型也会相应地更新--> </div>
</body> <script type="text/javascript">
Vue.config.productionTip = false new Vue({
el:'#root',
data:{
name:'vue',
info:{
category:"分类" }
}
})
</script>

vue实例创建的两种写法

  1. 第一种方式
	new Vue({
// 第一种写法:创建实例的时候直接挂载对应的容器
el:'#root',
// 第一种写法:对象式
data:{
name:'vue'
}
})
  1. 第二种方式
    // 创建Vue实例
const vm = new Vue({
// 第二种方式:函数式,必须返回一个对象
data:function (){
// 此处的this是Vue实例对象
return{name:"vue"}
}
})
// 通过$mount方法绑定容器,$mount是vue原型上的方法,作用是将vue挂载指定容器
vm.$mount("#root")
  • el使用哪种方式都可以,data的创建后续使用组件的时候,必须使用函数式
  • 由Vue管理的函数,一定不要写箭头函数,一旦写了箭头函数,this就不再是Vue实例,而是Window

MVVM模型

  1. M:模型(Model) :data中的数据
  2. V:视图(View) :模板代码
  3. VM:视图模型(ViewModel):Vue实例
    • data中所有的属性,最后都出现在了vm身上。
    • vm身上所有的属性 及 Vue原型上所有属性,在Vue模板中都可以直接使用

Js的Object.defineProperty

用于在一个对象上定义一个新属性,或者修改一个已经存在的属性。它允许精确地添加或修改对象的属性,包括属性的值、可枚举性、可配置性和可读写性等

// 创建一个对象
let user = {
name: "test",
age: 18
} // 使用:Object.defineProperty(obj, prop, descriptor)
// 参数
// obj:是要定义属性的目标对象。
// prop:是要在目标对象上定义或修改的属性的名称。
// descriptor:是一个对象,用于描述属性的各种特征。它可以包含以下键值对:
// value:属性的值。例如,{ value: 42 }会将属性的值设置为 42。
// writable:一个布尔值,表示属性是否可写。默认为false,则不能重新赋值。例如,{ writable: false, value: 'immutable' }定义了一个不可写的属性。
// enumerable:一个布尔值,表示属性是否可枚举。默认为false,在使用for...in循环或者Object.keys()方法等列举对象属性时,该属性不会被列出
// configurable:一个布尔值,表示属性是否可配置。默认为false,则不能删除该属性,并且除了value和writable之外的其他属性描述符(如enumerable和configurable)也不能被修改
//
// getter和setter方法,读和写,和上述部分属性是互斥的 // 向user对象中添加一个num属性,值是20
Object.defineProperty(user, "num", {
value: 20,
writable: true,
enumerable: true,
configurable: true, }) let test = 10
// 向user对象中添加一个test属性
Object.defineProperty(user, "test", { // value/writable与get/set互斥
// 当使用Object.defineProperty定义属性时,不能同时指定value(或writable)和get/set。
// 原因是它们代表了两种不同的属性定义模式。value和writable用于定义一个简单的数据属性,其值是直接存储的,读取和修改操作是基本的赋值和取值
// 而get和set定义的是访问器属性,通过自定义函数来控制属性的读取和写入逻辑,属性值可能存储在其他地方,不是简单地通过value来存储 configurable: true, // 当读取user的test的属性的时候get(getter)函数就会被调用,返回值是num的值
get: function () {
console.log("test属性被调用")
return test
},
// 当修改user的test的属性的时候set(setter)函数就会被调用,且会收到修改的值
set: function (value) {
console.log(`test属性被修改,值是${value}`)
test = value
} })

数据代理

数据代理:通过一个对象代理对另一个对象中属性的操作(读/写)

数据代理概念
let user1 = {num:100}
let user2 = {} // 向user2中添加一个num属性
Object.defineProperty(user2,"num",{
// 读取user2的num属性的时候,返回的是user1的num
get() {
return user1.num
}, // 修改user2的num属性的时候,修改的是user1的num
set(value){
user1.num = value
}
})
vue中的数据代理
  1. Vue中的数据代理:

    通过vm对象来代理data对象中属性的操作(读/写)
  2. Vue中数据代理的好处:

    更加方便的操作data中的数据
  3. 基本原理:

    通过Object.defineProperty()把data对象中所有属性添加到vm上。

    为每一个添加到vm上的属性,都指定一个getter/setter。

    在getter/setter内部去操作(读/写)data中对应的属性
  1. 原理示例
// 1. 创建vue实例的时候,data对象是存储在_data属性中
// 2. 使用Object.defineProperty向vue中添加_data对象中的属性,定义getter和setter方法
// 定义的getter和setter方法,返回和修改的是_data中对应的属性,所以我们可以通过vue实例对象访问代理数据 // 模拟vue的代理机制
// 模拟Vue实例(这里简化为一个普通对象来理解原理),实际的_data实现了数据劫持
const vm = {
// 用于存储数据的属性,模拟Vue的_data属性
_data: {}, // 构造函数,模拟Vue实例创建过程
constructor() {
// 将传入的数据对象赋值给_data属性,类似Vue内部的处理
this._data = {...dataObject }; // 遍历_data中的所有属性,为它们创建数据代理
for (let key in this._data) {
Object.defineProperty(this, key, {
get() {
return this._data[key];
},
set(v) {
this._data[key] = v;
}
});
}
}
}
  1. 使用代理数据
// 结合vue实现数据代理的原理,我们可以使用下面两种方式访问和修改数据
const vm = new Vue({
el: "#root",
data: {name: "vue"}
}) // 通过_data对象
console.log(vm._data.name)
//
console.log(vm.name)

事件处理

  1. 使用v-on:xxx 或 @xxx 绑定事件,其中xxx是事件名;
  2. 事件的回调需要配置Vue选项参数的methods对象中,最终会在vm上;
  3. methods中配置的函数,不要用箭头函数!否则this就不是vm了;
  4. methods中配置的函数,都是被Vue所管理的函数,this的指向是vm 或 组件实例对象;
基本使用
<div id="root">

    <!--    绑定点击事件-方式一-->
<button v-on:click="info">显示信息</button>
<!-- 绑定点击事件-方式二-->
<button @click="info">显示信息2</button>
<!-- 绑定点击事件-传参的回调函数 使用$event传递event对象,如果不需要使用event,可以不传,只传自定义参数-->
<button @click="info2($event,66666)">显示信息3</button> <!-- 回调函数可以不传event对象,然后在函数内部可以直接使用-->
<button @click="info3">显示信息4</button> </div>
</body> <script type="text/javascript">
const vm = new Vue({
el: "#root",
data: {name: "vue"},
// 配置回调方法,回调方法最终也是存储在vm上,没有做数据代理
methods: {
// 回调方法
info() {
alert("hello world")
}, info2(event,number){
console.log(this) // 此处的this是vm,如果使用箭头函数this是Window
alert(event.target + number.toString())
},
info3(e){
console.log(e.target) } }
}) </script>
事件修饰符
  • prevent:阻止默认事件
  • stop:阻止事件冒泡
  • once:事件只触发一次
  • capture:使用事件的捕获模式
  • self:只有event.target是当前操作的元素时才触发事件
  • passive:事件的默认行为立即执行,无需等待事件回调执行完毕
    <!--    a标签配置点击的事件回调-触发info方法-点击事件的行为设置了prevent, -->
<!-- prevent-阻止默认事件,即点击超链接不会触发跳转效果 -->
<a href="https://www.baidu.com" @click.prevent="info">百度一下</a>
<a href="https://www.baidu.com" v-on:click.prevent="info">百度一下2</a> <!-- 一个div绑定了点击事件,内部有一个按钮绑定了点击事件,会触发事件冒泡 -->
<div @click="info" style="width: 100px;height: 100px;background-color: yellow">
<!-- stop-阻止事件冒泡-->
<button @click.stop="info">点点</button>
</div> <!-- 按钮绑定了点击事件-->
<!-- once-事件只会触发一次 -->
<button @click.once="info">只有一次</button> <!-- div绑定了点击事件-->
<!--使用事件的捕获模式,捕获阶段触发事件-->
<div @click.capture="info" style="width: 100px;height: 100px;background-color: yellow">
<div @click style="width: 50px;height: 50px;background-color: gold"></div> </div> <!-- 只有event.target是当前操作的元素时,才触发事件-->
<div @click.self="info" style="width: 100px;height: 100px;background-color: yellow">
<button>按钮</button>
</div> <!-- 事件触发的时候立刻触发默认行为,不会等事件回调执行完 -->
<div style="height: 200px; overflow: auto" @scroll.passive="handleScroll">
键盘事件

键盘事件有:

  • keyup:按下键盘上的一个键并松开时触发

  • keydown:用户按下键盘上的键时触发

  • keypress:按下一个可打印字符(如字母、数字、标点符号等)的键并松开后触发

基本使用
<body>
<!-- 键盘事件-打印按下的按键-->
<input type="text" @keyup="info">
</body>
<script type="text/javascript">
const vm = new Vue({
el: "#root",
data: {name: "vue"},
// 配置回调方法
methods: {
// 回调方法
info(e) {
console.log(e.target.value)
}, }
}) </script>
键盘的按键别名
 <!--    vue常用的按键别名 -->
<!-- 回车 => enter-->
<!-- 删除 => delete (捕获“删除”和“退格”键)-->
<!-- 退出 => esc-->
<!-- 空格 => space-->
<!-- 换行 => tab (特殊,必须配合keydown去使用)-->
<!-- 上 => up-->
<!-- 下 => down-->
<!-- 左 => left-->
<!-- 右 => right-->
<!-- 键盘事件-按下按键后不会触发,需要按下回车键的时候才触发-->
<input type="text" @keyup.enter="info">
<!--也可以通过键码触发对应的按键-不推荐-已弃用 -->
<input type="text" @keyup.20="info">

通过按键名字触发事件

<div id="root">

    <!--    Vue未提供别名的按键,可以使用按键原始的key值去绑定-->
<!-- 在回调中通过event.target.key 和event.target.key分别获取按键名字和按键编码 -->
<!-- 可以通过按键名字(event.key)获取键名,如果是大驼峰的名字,需要转换小写每个单词-隔开-->
<!--按下大小写的按键的时候触发- CapsLock === caps-lock -->
<input type="text" @keyup.caps-lock="info"> </div>
</body> <script type="text/javascript">
const vm = new Vue({
el: "#root",
data: {name: "vue"},
// 配置回调方法
methods: {
// 回调方法
info(e) {
console.log(e.key) // 键名 CapsLock
console.log(e.keyCode) // 键码 20
}, }
})
自定义定制键名

Vue.config.keyCodes.自定义键名 = 键码,可以去定制按键别名

   // 设置大小写的别名为daxiaoxie
Vue.config.keyCodes.daxiaoxie = 20 const vm = new Vue({
el: "#root",
data: {name: "vue"},
// 配置回调方法
methods: {
// 回调方法
info(e) {
console.log(e.key) // 键名 CapsLock
console.log(e.keyCode) // 键码 20
}, }
})
键盘的系统修饰键

系统修饰键(用法特殊):ctrl、alt、shift、meta

(1).配合keyup使用:按下修饰键的同时,再按下其他键,随后释放其他键,事件才被触发。

(2).配合keydown使用:正常触发事件

计算属性

  • 定义:要用的属性不存在,要通过已有属性计算得来,即通过已有的属性计算生成一个新属性
  • 原理:底层借助了Objcet.defineproperty方法提供的getter和setter
  • 优势:与methods实现相比,内部有缓存机制(复用),效率更高,调试方便
  • 计算属性最终会出现在vm上,直接读取使用即可
  • 如果计算属性要被修改,那必须写set函数去响应修改,且set中要引起计算时依赖的数据发生改变
基本使用
<body>
<div id="root"> 姓氏:<input type="text" v-model="firstName">
<br>
名字:<input type="text" v-model="lastName">
<br>
全名: <span>{{allName}}</span> </div>
</body> <script type="text/javascript"> const vm = new Vue({
el: "#root",
data: {firstName: "vue",lastName:"html"},
methods:{},
// 配置计算属性
computed:{
// 定义一个allName计算属性
allName:{
// 当有人读取allName时,get就会被调用,返回值作为allName的返回值
// 被调用时机:1.初次读取allName的时候 2.依赖的数据发生变化的时候
// 初次计算后会将数据缓存,后续调用不用重复计算,除非有依赖数据发生变化
get(){
// this是vm
return this.firstName + "-" + this.lastName
},
// set在allName被修改的时候调用
set(v){
// abc-bcd格式的字符串,通过-切割
const arr = v.split("-")
// 将切割的两个值分别赋值给两个属性,然后计算属性联动变化
this.firstName = arr[0]
this.lastName = arr[1] } } } })
简写方式

如果计算属性只读取,不修改的话,可以简写

<body>
<div id="root"> 姓氏:<input type="text" v-model="firstName">
<br>
名字:<input type="text" v-model="lastName">
<br>
全名: <span>{{allName}}</span> </div>
</body> <script type="text/javascript"> const vm = new Vue({
el: "#root",
data: {firstName: "vue", lastName: "html"},
methods: {},
// 配置计算属性
computed: {
// 定义属性以函数的形式,该函数就是getter的作用
allName() {
// 直接返回计算后的属性
return this.firstName + "-" + this.lastName
} }
}) </script>

监视属性

  • 当被监视的属性变化时, 回调函数自动调用, 进行相关操作
  • 监视的属性必须存在,才能进行监视
  • 监视的两种写法:
    1. new Vue时传入watch配置
    2. 通过vm.$watch监视
基本使用
  1. 第一种写法

        const vm = new Vue({
    el: "#root",
    data: {firstName: "vue", lastName: "html"},
    methods: {},
    // 配置计算属性
    computed: {
    allName() {
    return this.firstName + "-" + this.lastName
    }
    }, // 配置监视属性
    watch:{
    // 要监视的属性名字
    firstName:{
    // 初始化的时候是否让handler调用一次,默认值是false
    immediate: true,
    // 当监视的属性发生变化的时候,handler调用
    handler(newValue,oldValue){
    console.log(`firstName被修改了`,newValue,oldValue)
    } }
    } })
  2. 第二种写法

      // 配置监视属性
    // 要监视的属性名字,配置对象
    vm.$watch("firstName",{
    immediate: true,
    handler(newValue,oldValue){
    console.log(`firstName被修改了`,newValue,oldValue)
    } })
深度监视
  • Vue中的watch默认不监测对象内部值的改变,只监视一层
  • 配置deep:true可以监测对象内部值改变,监视多层
  • Vue自身可以监测对象内部值的改变,但Vue提供的watch默认不可以
  • 使用watch时根据数据的具体结构,决定是否采用深度监视
  • 当被监视的对象是一个复杂对象(如包含嵌套属性的对象)时,默认情况下,watch只会监视对象的引用是否发生变化。而深度监视则会递归地监视对象内部的每一个属性,一旦内部属性发生变化,就会触发监听器的回调函数
const vm = new Vue({
el: "#root",
data: {
info: {
a: 1,
b: 2
}
},
methods: {},
// 配置计算属性
computed: {},
// 监视属性
watch:{
// 监视整个info,如果不深度监视,只会监视info对应的对象地址值引用有没有发生变化,而不会具体到里面的某个值
info:{
// 开启深度监视-监视多层结构中每个属性的变化
deep:true,
handler(){ console.log("info-",this.info)
}
}, // 监视多级结构中某个属性的变化-只监视info里面的a属性
// 对象的key是字符串,所以需要写成字符串形式
'info.a':{
handler() {
console.log("a",this.info.a)
}
} }
})
监视属性简写

如果不需要深度监视和初始化时调用,可以简写

  // 监视属性
watch:{
// 监视info,以函数的形式,函数相当于handler
info(newV,oldV){
console.log(newV,oldV)
}
}
  // 要监视的属性,回调函数,不允许写箭头函数
vm.$watch("info",function (newV,oldV) {
console.log(newV,oldV) })
计算属性和监视属性对比

computed和watch之间的区别:

  1. computed能完成的功能,watch都可以完成
  2. watch能完成的功能,computed不一定能完成,例如:watch可以进行异步操作
  3. 两个重要的小原则:
    • 所被Vue管理的函数,最好写成普通函数,这样this的指向才是vm 或 组件实例对象。
    • 所有不被Vue所管理的函数(定时器的回调函数、ajax的回调函数等、Promise的回调函数,最好写成箭头函数这样this的指向才是vm 或 组件实例对象

绑定样式

  • 在应用界面中, 某些元素的样式是变化的

  • class/style 绑定就是专门用来实现动态样式效果的技术

class绑定

使用:class进行绑定

<style>
.box {
width: 100px;
height: 100px;
} .box-color {
background-color: yellow; } .box-border {
border: 1px solid black; } </style> <body>
<div id="root">
<!-- 绑定class样式,ex是一个字符串,适用于样式不确定、需要动态指定-->
<!-- 最终class和:class的对应类会拼成一个class 最终是 class="box box-color "-->
<div class="box" :class="ex">box</div> <!-- 绑定class样式,exArr是一个数组,适用于要使用的样式个数不确定、名字也不确定-->
<div class="box" :class="exArr">box</div> <!-- 绑定class样式,exObj是一个对象,适用于要绑定的样式个数确定、名字也确定,但要动态决定用不用-->
<div :class="exObj">box</div> </div>
</body> <script type="text/javascript"> const vm = new Vue({
el: "#root",
data: {
ex: "box-color",
exArr: ["box-color", "box-border"],
exObj:{
box:true, // 根据true、false决定是否启动该样式
// 有特殊字符的key值,使用下面两种写法都可以
["box-color"]:true,
"box-border":true
} }
}) </script>
Style绑定
<body>
<div id="root">
<!-- 绑定style样式--对象写法,单个动态样式 -->
<div :style="styleObj">box</div>
<!-- 绑定style样式--数组写法,多个动态样式 -->
<div :style="styleArr">box</div> </div>
</body> <script type="text/javascript"> const vm = new Vue({
el: "#root",
data: {
styleObj:{
width:"100px",
height:"100px",
},
styleArr: [
{
width:"100px",
height:"100px",
},
{
// background-color 这种属性 改为小驼峰写法
// 也可以使用字符串key "background-color"
backgroundColor:"yellow"
}
] }
}) </script>

条件渲染

v-show
<div id="root">

    <!--    v-show可以控制显示、隐藏元素 -->
<!-- v-show并不会删除,只是页面不显示,相当于操作display: none;-->
<!-- 适用于切换频率较高的场景--> <!-- 布尔值,true显示,false隐藏-->
<h1 v-show="false">title1</h1>
<!--也可以写表达式值是布尔值-->
<h1 v-show="2>1">title2</h1>
<!-- 从vue data动态设置 -->
<h1 v-show="showIf">title3</h1> </div>
</body> <script type="text/javascript"> const vm = new Vue({
el: "#root",
data: {
showIf: true
}
}) </script>
v-if
<body>
<div id="root"> <!-- v-if会删除元素,而不是页面隐藏,适用于:切换频率较低的场景--> <!-- 布尔值,true显示,false隐藏-->
<h1 v-if="false">title1</h1>
<!--也可以写表达式值是布尔值-->
<h1 v-if="2>1">title2</h1>
<!-- 从vue data动态设置 -->
<h1 v-if="showIf">title3</h1> <!-- v-if可以和v-else-if、v-else一起使用,但要求结构不能被打断-->
<!-- 如果 1和"1" 相等 显示title4 -->
<h1 v-if="num===1">title4</h1>
<!-- 如果1大于2 显示title5-->
<h1 v-else-if="num>2">title5</h1>
<!-- 否则显示title6,,4和5条件都不成立-->
<h1 v-else>title6</h1> <!-- 等同于
if(num===1){ }else if(num>2){ }else { }
--> </div>
</body> <script type="text/javascript"> const vm = new Vue({
el: "#root",
data: {
showIf: true,
num:10
}
}) </script>
			<!-- v-if只能和template的配合使用,不能和v-show配合使用 -->
<template v-if="num === 20">
<h2>1</h2>
<h2>2</h2>
<h2>3</h2>
</template>
  • template用于定义一个模板片段,在这个模板片段中的内容在默认情况下不会被直接渲染到页面上,而是作为一种 “模板” 存储起来,以便在需要的时候通过 JavaScript 进行克隆或者其他操作来使用其中的内容。
  • 例如,在构建一个动态列表时,可以将列表项的模板定义在<template>标签中,然后根据数据动态地克隆和填充这个模板

列表渲染

基本渲染
<body>
<div id="root"> <!-- 遍历数组-->
<ul>
<!-- 等同于 for (let u of users)-->
<!-- 有多少条数据会填充多少条li-->
<!-- 也可以使用 u in users-->
<!-- :key用来指定这个li节点的唯一标识 -->
<li v-for="u of users" :key="u.id">
{{u.name}}---{{u.tag}}
</li> </ul>
<ul>
<!--index是下标-->
<li v-for="(u,index) of users" :key="u.id">
{{u.name}}---{{u.tag}}---{{index}}
</li>
</ul> <!-- 遍历对象 -->
<ul>
<li v-for="(value,key) of info" :key="key">
{{key}} -- {{value}}
</li>
</ul> <!-- 遍历字符串 -->
<ul>
<li v-for="(char,index) of strFor" :key="index">
{{char}} -- {{index}}
</li>
</ul>
<!-- 遍历指定次数 -->
<ul>
<!-- 遍历5次,number是从1开始的值,index是下标 -->
<li v-for="(number,index) of 5" :key="index">
{{number}}--{{index}}
</li>
</ul>
</div>
</body> <script type="text/javascript"> const vm = new Vue({
el: "#root",
data: {
users: [
{id: 1, name: "vue", "tag": "js"},
{id: 2, name: "python", "tag": "py"},
{id: 3, name: "golang", "tag": "go"},
],
info: {
name: "vue",
count: 10,
price: 1000 },
strFor: "helloworld"
}
}) </script>
v-for key的原理和作用

虚拟DOM中key的作用:

key是虚拟DOM对象的标识,当数据发生变化时,Vue会根据【新数据】生成【新的虚拟DOM,随后Vue进行【新虚拟DOM】与【旧虚拟DOM】的差异比较,比较规则如下:

  1. 旧虚拟DOM中找到了与新虚拟DOM相同的key:

    • 若虚拟DOM中内容没变, 直接使用之前的真实DOM!

    • 若虚拟DOM中内容变了, 则生成新的真实DOM,随后替换掉页面中之前的真实DOM。

  2. 旧虚拟DOM中未找到与新虚拟DOM相同的key

    • 创建新的真实DOM,随后渲染到到页面

用index作为key可能会引发的问题:

  1. 若对数据进行:逆序添加、逆序删除等破坏顺序操作:

    会产生没有必要的真实DOM更新 ==> 界面效果没问题, 但效率低。

  2. 如果结构中还包含输入类的DOM:

    会产生错误DOM更新 ==> 界面有问题

开发中如何选择key:

  1. 最好使用每条数据的唯一标识作为key, 比如id、手机号等唯一值
  2. 如果不存在对数据的逆序添加、逆序删除等破坏顺序操作,仅用于渲染列表用于展示,使用index作为key是没问题的
  3. 如果不指定:key,vue默认是使用下标作为key的
列表过滤
使用watch实现
<body>
<div id="root"> <!-- 双向绑定过滤关键字-->
<input type="text" v-model="keyWord">
<ul>
<!-- 遍历模糊搜索过滤的数组 -->
<li v-for="u of filUsers" :key="u.id">
{{u.name}}---{{u.tag}}
</li> </ul>
</div>
</body> <script type="text/javascript"> const vm = new Vue({
el: "#root",
data: {
// 过滤的关键字
keyWord: "",
users: [
{id: 1, name: "vue", "tag": "html", "price": 30},
{id: 2, name: "python", "tag": "server", "price": 40},
{id: 3, name: "golang", "tag": "server", "price": 50},
],
// 定义一个新数组,用于存储过滤后的数据
filUsers: []
},
// 配置监视属性
watch: {
keyWord:{
// 初始化时调用一下,过滤空串,初显全部数据
immediate: true,
handler(newValue) {
// 从users的tag过滤 包含newValue的所有数据,重新赋值给this.users
this.filUsers = this.users.filter((p) => {
// 返回tag包含newValue的数据
// indexOf 不包含 返回-1 空串 返回0
return p.tag.indexOf(newValue) !== -1
}) } } }
}) </script>
用computed实现
    const vm = new Vue({
el: "#root",
data: {
// 过滤的关键字
keyWord: "",
users: [
{id: 1, name: "vue", "tag": "html", "price": 30},
{id: 2, name: "python", "tag": "server", "price": 40},
{id: 3, name: "golang", "tag": "server", "price": 50},
], },
// 配置计算属性
computed:{
// 计算属性依赖keyword,keyword发生变化的时候,触发计算出新的数组
filUsers(){
return this.users.filter((p)=>{
return p.tag.indexOf(this.keyWord) !== -1
})
}
}
})
列表排序
<body>
<div id="root"> <!-- 双向绑定过滤关键字-->
<input type="text" v-model="keyWord">
<!-- 按钮点击的时候 修改sortType的值 -->
<button @click="sortType = 2">price 升序</button>
<button @click="sortType = 1">price 降序</button>
<button @click="sortType = 0">原顺序</button> <ul>
<!-- 遍历模糊搜索过滤的数组 -->
<li v-for="u of filUsers" :key="u.id">
{{u.name}}---{{u.tag}}--{{u.price}}
</li> </ul>
</div>
</body> <script type="text/javascript"> const vm = new Vue({
el: "#root",
data: {
// 过滤的关键字
keyWord: "",
// 定义一个关键字,0表示原顺序 1表示降序 2表示升序
sortType: 0,
users: [
{id: 1, name: "vue", "tag": "html", "price": 30},
{id: 2, name: "python", "tag": "server", "price": 40},
{id: 3, name: "golang", "tag": "server", "price": 50},
], },
// 配置计算属性
computed: {
// 计算属性依赖keyword,keyword发生变化的时候,触发计算出新的数组
filUsers() {
// 定义一个数组接收过滤后的数据
const arr = this.users.filter((p) => {
return p.tag.indexOf(this.keyWord) !== -1
})
// 先过滤 再排序
// 判断是否需要排序
if (this.sortType) {
arr.sort((a, b) => {
// 如果type===1 降序 否则升序
return this.sortType === 1 ? b.price - a.price : a.price - b.price
})
}
// 返回排序后的数组
return arr
}
}
}) </script>

Vue监测数据原理

Vue监测对象
  1. Vue监测对象的原理

    当创建一个 Vue 实例时,Vue 会遍历data选项中的所有属性。对于每个属性,它使用Object.defineProperty方法来进行数据劫持。这个方法允许 Vue 重新定义属性的getset访问器

    vm的数据代理,data数据给 _data前,先将数据加工,然后再赋值给_data,更好的实现响应式,对象中每个属性都有对应的getter和setter

    // 模拟实现一个vm的数据监测
    
        function  Observer(obj){
    // 获取对象中所有的属性,生成一个数组
    const keys = Object.keys(obj) // 遍历所有属性
    keys.forEach((k)=>{
    // 将对应的属性添加到当前实例身上
    Object.defineProperty(this,k,{
    get(){
    // 返回对应的值
    return obj[k]
    },
    set(v){
    // 数据被修改,去解析模版,生成虚拟DOM比对,更新页面
    obj[k] = v
    } }) }) } let data = {
    name:"vue",
    tag:"js"
    } // 创建一个监视的实例对象,用于监视data中属性的变化
    const obs = new Observer(data) // 准备一个的vm实例对象
    let vm = {}
    vm._data = data = obs
    // 可以通过vm._data去获取和修改属性
  2. 问题示例:点击按钮触发回调更新数据,第一种方法可以更新成功,第二个方法更新不成功(数据改了但是没有响应式)

    <button @click="updateInfo1" type="button">按钮</button>
<button @click="updateInfo2" type="button">按钮</button>
<ul>
<!-- 遍历模糊搜索过滤的数组 -->
<li v-for="u of users" :key="u.id">
{{u.name}}---{{u.tag}}--{{u.price}}
</li> </ul>
</div>
</body> <script type="text/javascript"> const vm = new Vue({
el: "#root",
data: {
users: [
{id: 1, name: "vue", "tag": "html", "price": 30},
{id: 2, name: "python", "tag": "server", "price": 40},
{id: 3, name: "golang", "tag": "server", "price": 50},
], },
// 回调
methods:{
updateInfo1(){
// 可以更新成功
this.users[0].name = "js"
this.users[0].price = 40
},
updateInfo2(){
// 数据更新成功,但是页面没有响应式更新,原因看监测数组原理
this.users[0] = {id: 1, name: "css", "tag": "html", "price": 40}
}
}
}) </script>
Vue.set()方法

如果我们想直接给vm或者_data上加一个新属性,通过vm.xxx = xxx 或者vm._data.xxx = xx是没有响应式的

Vue的数据的响应式是通过Object.defineProperty来实现的,每个属性都有对应的getter和setter,而直接添加属性是没有数据实现

Vue给我们提供了set和$set方法,给vm或者_data添加属性, 并且完成数据加工

  • Vue.set是全局的 API,它的调用方式是Vue.set(target, key, value)

    • 其中target是要添加属性的目标对象(响应式对象),key是要添加的属性名,value是属性的值
    • 这种调用方式不依赖于特定的 Vue 组件实例,适用于在组件外部或者一些工具函数等场景中使用
  • this.$set是 Vue 实例(组件)的一个实例方法,它只能在 Vue 组件内部使用

    • 通过this.$set来调用。this指向当前的 Vue 组件实例,调用方式为this.$set(target, key, value)
    • 参数含义与Vue.set相同。这种方式更符合在组件内部操作数据的习惯,因为它与组件实例紧密相关,可以方便地访问组件的this上下文,如组件的数据(data)、计算属性(computed)等
  • Vue.set() 和 vm.$set() 不能给vm 或 vm的根数据对象 添加属性

    const vm = new Vue({
el: "#root",
data: {
user:{
name:"vue",
info:{
price:100
}
}
},
methods:{
// 事件回调 给info天添加一个tag数学
addInfo(){
Vue.set(this.user.info,"tag1","html") this.$set(this.user.info,"tag2","html")
}
} })
Vue监测数组

vm上数组的数据,没有getter和setter

vm监测数组数据变化实现响应式,是通过调用Vue数组(非原生方法)方法实现的

  • Vue在数据原型上实现了数组的增删改查方法(push、pop等)
  • 内部先调用了原生数组的增删改查方法来实现数据变化
  • 然后解析模版实现响应式

通过数组索引修改数据,只是修改了数据,没有重新解析模版,所以页面不会跟随更新

  // 使用this.$set来更新数组元素,实现响应式更新
this.$set(this.numbers, 0, 10); // 使用splice方法来更新数组元素,实现响应式更新
this.numbers.splice(0, 1, 10);

vue收集表单数据和修饰符

<body>
<div id="root"> <form>
<!-- 有输入框相关的,v-Model收集的是value值,用户输入的东西就是value值--> <!--
.trim修饰符
去除收集数据的首尾空格
-->
账号:<input type="text" v-model.trim="account"> <br/><br/>
密码:<input type="password" v-model="password"> <br/><br/> <!-- .number修饰符,用户输入vue收集过来会默认转换成number类型
type="number" 是只能输入number,
如果其他type 输入字符串“123”,修饰符收集过来会转换成number123
如果输入123abc,修饰符收集过来是123
-->
年龄:<input type="number" v-model.number="age"> <br/><br/> <!-- radio类型没有输入框 v-model收集的是value值,需要给标签配置value值 -->
性别:
男<input type="radio" name="sex" value="male" v-model="sex">
女<input type="radio" name="sex" value="female" v-model="sex"> <br/><br/> <!--
checkbox类型
如果没有配置value属性,v-model收集的就是标签的checked属性,true 或者false
如果配置了value属性
1. v-model的初始值是非数组,那么收集的就是checked(勾选 or 未勾选,布尔值)
2. v-model的初始值是数组,那么收集的的就是value组成的数组
初始值就是vue双向绑定给的初始值 -->
爱好:
学习<input type="checkbox" v-model="hobby" value="study">
打游戏<input type="checkbox" v-model="hobby" value="game">
吃饭<input type="checkbox" v-model="hobby" value="eat">
<br/><br/>
所属校区
<select v-model="city">
<option value="">请选择校区</option>
<option value="beijing">北京</option>
<option value="shanghai">上海</option>
<option value="shenzhen">深圳</option>
<option value="wuhan">武汉</option>
</select>
<br/><br/>
其他信息: <!--
.lazy修饰符
默认收集数据是实时的,每输入一个字符都会直接收集
使用 .lazy修饰符,会在失去焦点的时候统一收集,而不是实时收集
-->
<textarea v-model.lazy="other"></textarea> <br/><br/> <input type="checkbox" v-model="agree">阅读并接受<a href="https://www.baidu.com">《用户协议》</a>
<button>提交</button>
</form>
</div>
</body> <script type="text/javascript"> const vm = new Vue({
el: "#root",
data: {
account: "",
password: "",
age: 20, // 默认20
sex: "male", // 默认选中 value为male
// 复选:v-model初始值设置为数组,收集所选数据
hobby: [], city: "beijing", // 默认选择北京
other: "",
agree: "" // 复选:不需要收集具体数,设置为字符串,收集checked状态 } }) </script>

过滤器

过滤器不会改变原本的数据, 是产生新的对应的数据

局部过滤器
<body>
<div id="root">
<!-- 要展示的属性 | 要使用的过滤器 -->
<!-- 过滤器原理: 先读取time,把time当做参数传给过滤器,过滤器的返回值替换{{}}插值语法中的内容-->
<h2>{{time | timeFormat }}</h2>
<!-- 过滤器可以传递参数,第一个参数默认就是value,然后第二个参数需要使用形参接受-->
<h2>{{time | timeFormat(true) }}</h2> <!-- 多个过滤器可以一起使用 多个过滤器使用 | 分割 , 插值 | 过滤器 |过滤器 ..-->
<!-- 原理:先将time交给timeFormat处理,然后把timeFormat处理的结果交给testFilter,最后使用testFilter的值进行替换-->
<h2>{{time | timeFormat | testFilter}}</h2> </div>
</body> <script type="text/javascript"> const vm = new Vue({
el: "#root",
data: {
time: Date.now() // 当前时间的时间戳
},
// 配置局部过滤器,只有当前vue实例可以使用,其他实例不可以使用
filters: {
// 过滤器就是函数
timeFormat(value, status) {
if (status) {
console.log(value)
}
// 将时间戳格式化 然后返回
return dayjs(value).format("YYYY年MM月DD日 HH:mm:ss") },
testFilter(value) {
return value[0] } } }) </script>
全局过滤器
  // 全局过滤器 必须在Vue实例创建之前配置
Vue.filter("myFilter", function (value) {
return value.slice(0, 4)
}) // 如果要多个全局过滤器,需要多声明
Vue.filter("myFilter2", function (value) {
return value.slice(0, 4)
}) const vm = new Vue({
el: "#root",
data: {
time: Date.now() // 当前时间的时间戳
},
// 配置局部过滤器,只有当前vue实例可以使用,其他实例不可以使用
filters: {
// 过滤器就是函数
timeFormat(value, status) {
if (status) {
console.log(value)
}
// 将时间戳格式化 然后返回
return dayjs(value).format("YYYY年MM月DD日 HH:mm:ss") },
testFilter(value) {
return value[0]
}
}
})
<!--在单向数据绑定的时候,也可以使用过滤器 -->
<input :value="time | timeFormat">

内置指令

v-bind : 单向绑定解析表达式, 可简写为 :xxx

v-model : 双向数据绑定

v-for : 遍历数组/对象/字符串

v-on : 绑定事件监听, 可简写为@

v-if : 条件渲染(动态控制节点是否存存在)

v-else : 条件渲染(动态控制节点是否存存在)

v-show : 条件渲染 (动态控制节点是否展示)

v-text

作用:向其所在的节点中渲染文本内容。

与插值语法的区别:v-text会替换掉节点中的内容,插值语法则不会替换

<body>
<div id="root"> <!-- 123vue-->
<h1>123{{name}}</h1> <!-- vue -->
<!-- v-text会拿到data里的值替换掉整个标签里的内容-->
<!-- v-text会将数据当成字符串渲染,不会解析标签,如果值是标签内容 也会当字符串显示-->
<h1 v-text="name">123</h1> </div>
</body> <script type="text/javascript">
const vm = new Vue({
el: "#root",
data: {
name: "vue"
}
})
</script>
v-html

向指定节点中渲染包含html结构的内容

v-html有安全性问题:

  1. 在网站上动态渲染任意HTML是非常危险的,容易导致XSS攻击
  2. 一定要在可信的内容上使用v-html,永不要用在用户提交的内容上
<div id="root">

    <!--<h1>666</h1>-->
<div>{{name}}</div>
<!-- <h1>666</h1>-->
<div v-text="name"></div> <!--h1效果的666 ,v-html可以解析标签 ,如果标签中有其他内容,也会整个替换,和v-text一样-->
<div v-html="name"></div> </div>
</body> <script type="text/javascript">
const vm = new Vue({
el: "#root",
data: {
name: "<h1>666</h1>"
}
})
</script>
v-clock

本质是一个特殊属性,Vue实例创建完毕并接管容器后,会删掉v-cloak属性。

使用css配合v-cloak可以解决网速慢时页面展示出{{xxx}}的问题

<style>

    /*  当vue没有创建成功的时候,插值语法还没有值,标签有v-cloak属性,选中这些标签 将该元素隐藏 */
/* 当vue创建成功的之后,标签的v-cloak都被删掉,这些元素就不会隐藏了 */
[v-cloak] {
display: none;
}</style>
<body>
<div id="root"> <!-- vue实例没有创建成功的时候,标签内v-cloak,当实例创建成功之后,会删除所有 所有标签内的v-cloak -->
<h1 v-cloak>{{name}}</h1>
<h1 v-cloak>{{name}}</h1> </div>
</body> <script type="text/javascript">
const vm = new Vue({
el: "#root",
data: {
name: "vue"
}
})
</script>
v-once

v-once所在节点在初次动态渲染后,就视为静态内容了。

以后数据的改变不会引起v-once所在结构的更新,可以用于优化性能

    <!--    使用v-once,只会读取一次num值,后续不会在更新-->
<h2 v-once>{{num}}</h2> <!-- 每点一次 按钮 num增加1 -->
<h2>当前的n值是:{{num}}</h2>
<button @click="num++">点我n+1</button>
v-pre
  • 跳过其所在节点的编译过程
  • 可利用它跳过:没有使用指令语法、没有使用插值语法的节点,会加快编译
  <!--  页面显示  {{name}}} 不会解析了 使用了插值语法、指令的地方,不使用 -->
<div v-pre>{{name}}</div> <!-- 对于不需要vue渲染的 可以使用该指令 -->
<div v-pre>内容</div>

自定义指令

指令对象式里面的方法、函数式的this都是Window

函数式
<div id="root">

    <div style="height: 100px" v-test="num" ></div>

</div>
</body> <script type="text/javascript">
const vm = new Vue({
el: "#root",
data: {
num: 10
},
// 配置自定义指令
directives:{
// 函数形式写法-自定义一个test指令,函数名字不需要v-,但是使用的时候需要v- // element:使用该指令所绑定的 DOM 元素 比如 <div style=""></div>,真实DOM而非虚拟DOM
// binding:一个对象,它包含了指令的相关信息
// def:包含了指令在生命周期不同阶段执行的函数,主要是bind和update
// update:当指令所绑定的数据发生变化时,update函数会被调用。它用于根据新的数据更新指令相关的操作。例如,如果指令是将数据绑定到元素的文本内容,update函数会更新文本内容以反映数据的变化
// expression:指令中使用的表达式,v-指令="xxx"中的xxx
// modifiers:一个对象,存储指令的修饰符。当指令在模板中有修饰符时,这个对象会记录相关信息
// name: 自定义指令的名称,这里是test
// rawName:自定义指令的原始名称,包含v-,这里是v-test
// value:指令的表达式绑定的值,通常是由expression计算得出或者直接从绑定的数据获取的,会在指令的逻辑中用于各种操作,比如更新元素的属性或者作为条件判断的依据 // 指定触发时机 1.指令与元素成功绑定时(此时元素不一定已经放入页面)
// 如果一些操作比如使用element获取焦点,如果元素还没放入页面,就会失败
// 函数式存在指令和元素绑定成功但是vue还没将模版(html)渲染的问题
// 2.指令所在的模板被重新解析时
test(element,binding){
console.log(binding)
// element的对应的dom元素,向该元素写入数据, 从binding.value获取值,然后做处理
element.innerText = binding.value *10 } } })
</script>
对象式
<body>
<div id="root"> <div style="height: 100px" v-test="num"></div> <!-- 指令名如果是多个单词,要使用v-xxx-xxx命名方式,不要用小驼峰命名-->
<input type="text" v-test-obj:value="num"> </div>
</body> <script type="text/javascript">
const vm = new Vue({
el: "#root",
data: {
num: 10
},
// 配置自定义指令
directives: {
test(element, binding) {
// element的对应的dom元素,向该元素写入数据, 从binding.value获取值,然后做处理
element.innerText = binding.value * 10
},
// 对象式-可以解决函数式的绑定元素&页面元素未放入的时机问题
// bind和update方法大部分情况是一样的,函数式相当于实现了bind和update方法,没有inserted方法
testObj: {
// 调用时机-指令与元素成功绑定时
bind(element, binding) {
element.value = binding.value * 10
},
// 调用时机-指令所在元素被插入页面时调用
inserted(element, binding) {
// 获取input的焦点,触发时机是所在元素被插入页面时,所以dom的一些操作都会成功
element.focus()
},
// 调用时机-指令所在的模版呗重新解析时调用
update(element, binding) {
element.value = binding.value * 10
} },
// 官方推荐直接使用 多个单词-连接的方式
"test-object":{
bind(element, binding) {
},
inserted(element, binding) {
},
update(element, binding) {
}
}
}
})
</script>
自定义指令-全局指令

在vue实例上配置的指令,都是局部指令,只能在当前vue实例使用

   // 在vue实例之前
// 指令名,配置对象
Vue.directive("test",{})
// 指令名,回调函数
Vue.directive("test1",function () {})

生命周期

Vue 的生命周期是指 Vue组件从创建到销毁的整个过程中所经历的一系列阶段。在每个阶段,组件会触发相应的生命周期钩子函数,开发者可以通过在这些钩子函数中编写代码来实现特定的功能,例如初始化数据、发送网络请求、操作 DOM 元素、清理资源等

  • 又名:生命周期回调函数、生命周期函数、生命周期钩子。
  • Vue在关键时刻帮我们调用的一些特殊名称的函数
  • 生命周期函数的名字不可更改,但函数的具体内容是根据需求编写的
  • 生命周期函数中的this指向是vm 或 组件实例对象
    const vm = new Vue({
el: "#root",
data: {
opacity: 1 // 设置透明度
},
// mounted是一个生命周期钩子函数
// 当Vue完成模版解析并把初始的真实DOM放入页面后(挂载完毕)调用mounted
mounted() {
setInterval(()=>{
this.opacity -= 0.01
if(this.opacity <= 0)
this.opacity = 1
},16)
}
}
)
挂载流程

    // new vue实例
const vm = new Vue({
el: "#root",
data: {},
/** 挂载流程 **/ // 1.初始化生命周期和事件之后,调用该方法,此数据代理还未开始,不能通过vm访问data、methods
beforeCreate() {
console.log("beforeCreate")
}, // 2.当数据检测、数据代理等初始化完成之后调用该方法,此时可以通过vm访问data、methods中的方法
created() {
console.log("created")
}, // 3.Vue开始解析模版,生成虚拟DOM(内存中),此时页面还不能显示解析好的内容
// 判断new vue实例的时候有没有el选项,如果没有,就等待vm.$mount调用再后续执行
// 判断new vue实例的时候是否有template选项,如果有的话,编译模版到render函数 // 4.上方步骤之后,调用该方法,页面呈现的是未经Vue编译的DOM结构,所有对DOM的操作,此时都不奏效
beforeMount() {
console.log("beforeMount") }, // 5.将内存中的虚拟DOM转为真实DOM插入页面 // 6.当Vue完成模版解析并把初始的真实DOM放入页面后(挂载完毕)调用mounted
// 此时对DOM的操作均有效,但是尽量不在此时操作DOM
// 一般可以在这个时候开启定时器、发送请求、定向消息、绑定自定义事件等初始化操作
mounted() {
console.log("mounted") }, /** 更新流程 **/ // 1.当有数据改变的时候(更新之前),调用该方法
// 此时数据是新的,但是页面还是旧的,页面还未和数据保持同步
beforeUpdate() {
console.log("beforeUpdate")
}, // 2.根据新数据,生成新的虚拟DOM,与旧的虚拟DOM进行比较,然后完成页面更新,Model->View的更新 // 3. 更新完成之后,调用该方法,此时数据是新的,页面也是新的
updated() {
console.log("updated")
}, /** 销毁流程 **/
// 当调用vm.$destroy()之后,触发销毁流程
//
// // 1. 在组件即将被销毁之前调用的钩子函数。这个阶段组件仍然是完整的,还没有开始实际的销毁过程
// 目前vm中的方法属性等都处于可以用状态,但是修改不会再生效,一般在此时关闭定时器、取消消息解绑自定义事件等收尾操作
beforeDestroy() {
console.log("beforeDestroy") }, // 2. 完全销毁一个实例,清理它与其他实例的连接,解绑它的全部指令及监听
// vue不再管理页面,但是之前生成的数据还在 // 3.在组件已经完全被销毁之后调用
destroyed() {
console.log("destroyed")
} }
)

vue2-基础核心的更多相关文章

  1. Vue2基础知识学习

    Vue2基础知识学习 01.初识 new Vue({ el: '#root', //用于指定当前Vue实例为哪个容器服务,值通常为css选择器符 data () { return { } } }); ...

  2. JQuery基础核心

    一.代码风格 在jQuery程序中,不管是页面元素的选择.内置的功能函数,都是美元符号“$”来起始的. 而这个“$”就是jQuery当中最重要且独有的对象:jQuery对象,所以我们在页面元素选择或执 ...

  3. 06-CABasicAnimation基础核心动画

    *:first-child { margin-top: 0 !important; } body > *:last-child { margin-bottom: 0 !important; } ...

  4. spring中基础核心接口总结

    spring中基础核心接口总结理解这几个接口,及其实现类就可以快速了解spring,具体的用法参考其他spring资料 1.BeanFactory最基础最核心的接口重要的实现类有:XmlBeanFac ...

  5. jQuery之基础核心(demo)

    jQuery之基础核心     作者的热门手记 jQuery之基础核心(demo)   本文主要简单的介绍下jQuery一些基础核心,大致了解jQuery使用模式.适用于有HTML.CSS.javas ...

  6. 第一百六十三节,jQuery,基础核心

    jQuery,基础核心 一.代码风格 在jQuery程序中,不管是页面元素的选择.内置的功能函数,都是美元符号“$”来起 始的.而这个“$”就是jQuery当中最重要且独有的对象:jQuery对象,所 ...

  7. [php入门] 2、基础核心语法大纲

    1 前言 最近在学PHP,上节主要总结了PHP开发环境搭建<[php入门] 1.从安装开发环境环境到(庄B)做个炫酷的登陆应用>.本节主要总结PHP的核心基础语法,基本以粗轮廓写,可以算作 ...

  8. iOS基础 - 核心动画

    一.核心动画 l 核心动画基本概念 l 基本动画 l 关键帧动画 l 动画组 l 转场动画 l Core Animation是一组非常强大的动画处理API,使用它能做出非常炫丽的动画效果,而且往往是事 ...

  9. 1.0 JAVA基础核心概念

    JAVA基础知识 转载至:http://www.runoob.com/java/java-variable-types.html 对菜鸟教程进行核心整理: 一.JAVA理论概念 1.基础概念 Java ...

  10. 作用域链–JS基础核心之一

    JS中的作用域,大家都知道的,分为全局作用域和局部作用域,没有块级作用域,听起来其实很简单的,可是作用域是否能够有深入的了解,对于JS代码逻辑的编写成功率,BUG的解决能力,以及是否能写出更优秀的代码 ...

随机推荐

  1. 2024-09-04:用go语言,给定一个长度为n的数组 happiness,表示每个孩子的幸福值,以及一个正整数k,我们需要从这n个孩子中选出k个孩子。 在筛选过程中,每轮选择一个孩子时,所有尚未选

    2024-09-04:用go语言,给定一个长度为n的数组 happiness,表示每个孩子的幸福值,以及一个正整数k,我们需要从这n个孩子中选出k个孩子. 在筛选过程中,每轮选择一个孩子时,所有尚未选 ...

  2. 消息队列初见:一起聊聊引入系统mq 之后的问题

    消息队列前文目录 消息队列初见:一起聊聊引入系统mq 之后的问题 https://www.cnblogs.com/yizhiamumu/p/16573472.html 分布式事务实战方案汇总 http ...

  3. 6.2 XXE和XML利用

    pikaqu靶场xml数据传输测试-有回显,玩法,协议,引入 1.构造payload 写文件 <?xml version="1.0" encoding="UTF-8 ...

  4. webpack笔记-loader的详细使用介绍(四)

    loader 基本上都是第三方类库,使用时需要安装,有一些 loader 还需要安装额外的类库,例如 less-loader 需要 less,babel-loader 需要 babel 等. load ...

  5. CSS & JS Effect – Styling Select

    参考 YouTube – Custom select menu - CSS only 原装 select 的缺点 这是一个原装 select design 它最大的问题是没有 spacing. bor ...

  6. CSS – Naming Conversion

    参考: CSS Naming Conventions that Will Save You Hours of Debugging Class Name kebab-case .hero-section ...

  7. mongodb 中rs.stauts()命令参数解析

    转载请注明出处: rs.status()命令用于获取MongoDB副本集的状态信息.它提供了关于副本集中各个节点的详细信息,包括节点的健康状况.角色.选举状态等. 以下是查看一个mongo集群状态返回 ...

  8. SaaS架构:流程架构分析

    大家好,我是汤师爷~ 今天聊聊SaaS架构中的流程架构分析. 业务流程的概念 业务流程是企业为实现目标而制定的一套系统化的工作方法.它由一系列有序的业务活动组成,按照既定规则将资源(输入)转化为有价值 ...

  9. Winrar 免广告、去评估版的解决办法 ( 实测有效 )

    事件起因: 在打开 Winrar 压缩软件的时候,总是会弹出广告弹窗,而且上面还是显示评估版本. 解决办法: 1. 正常安装 Winrar 软件 2. 安装破解软件--Restorator http: ...

  10. Java使用snmp协议采集服务器信息

    Java使用snmp协议采集服务器信息    一.snmp简介   SNMP是专门设计用于在 IP 网络管理网络节点(服务器.工作站.路由器.交换机及Hubs等)的一种标准协议,它是一种应用层协议. ...