Vue(day3)
第三天
异步 DOM 更新
- Vue 中采用了
异步DOM更新
的机制 - 如何更新页面?
-
数据发生改变后, vue 没有立即将数据的改变更新到视图中,
-
而是等到数据不再变化的时候 一次性的 将 数据的改变更新到视图中
//1. 验证了 for (let i = 0; i < 1000; i++) { this.count++ }
- 为什么是异步 DOM 更新?
- 性能的考虑
- 因为对于前端来说, 修改数据进行 DOM 操作是常有的事情,如果频繁操作 DOM,会严重影响页面的加载性能
- DOM 操作这是前端的性能的瓶颈
- 比如 : for (let i = 1; i < 10000; i++>) 如果同步 就要重新渲染 1000 次
- 验证 异步 DOM 更新 :
//2. 直接获取data 中的值 ,会立马获取成功
console.log(this.count)
this.count++
console.log(this.count)
// 但是 通过dom来获取count的值,因为DOM更新这个count值是异步的,是需要一点时间的
console.log(document.querySelector('h1').innerText) // 0
this.count = 100
console.log(document.querySelector('h1').innerText) // 0
-
需求 : 在数据更新后,立即获取到更新后的内容???>
DOM 更新后,会执行 this.$nextTick() 的回调函数,所以能拿到值
// setTimeout(() => {
// console.log(document.querySelector('h1').innerText)
// }, 1000)
this.$nextTick(() => {
console.log(document.querySelector('h1').innerText) // 100
})
三 : 监听 watch
-
说明 : Vue 中可以通过 watch 配置项,来监听 vue 实例中数据的变化
-
基本使用
watch: { // 监听name属性的数据变化 // 作用 : 只要name的值发生变化,这个方法就会被调用 // 第一个参数 : 新值 // 第二个参数 : 旧值,之前的前 name(newVal,oldVal){ console.log('新 :',newVal); console.log('旧 :',oldVal); } }
-
基本使用案例 :
需求 : 监听用户名文本框字符个数(3-6),并显示格式验证
<input type="text" v-model="name" />
<span v-show="isShow">用户名的字符 在 6-12之间</span> if
(/^[0-9a-zA-Z]{3,6}$/.test(newVal)) { 验证 }
- 监听对象 (数组也属于对象)
// data :
data: {
obj: {
name: 'zs'
}
},
// 组件
<input type="text" v-model="obj.name" />
// 监听
- 开始监听对象的属性
// 从对象的角度来监听的
因为对象和数组都是引用类型,引用类型变量存的是地址,地址没有变,所以不会触发watch
obj:{
// 深度监听 属性的变化
deep:true,
// 立即处理 进入页面就触发
immediate: true,
// 数据发生变化就会调用这个函数
handler( newVal ) {
console.log( newVal.name );
}
},
// 从属性的角度来监听
'obj.name' ( newVal ) {
console.log('监听对象的属性',newVal);
}
- 计算属性和watch的区别
computed 和 watch的区别
computed : 计算属性
- 1.根据已知值 ,得到一个新值
- 2. 新值随着已知值(相关的数据)变化而变化
1. 计算属性 ==> (得到的是)新值
2. 计算属性(num) ==> 是别人影响了我
watch : 监听器
1. 监听 ==> (监听)已知值
2. 监听数据 (num2) => 是我影响到了别人
四 : TodoMVC 数据持久化
需求 : 将todoMVC中的数据,保存到
本地存储
中 (本地持久化)
-
何时存储数据?
因为功能中的 CRUD 都会修改 list 数据,所以,只要 list 数据发生改变,就要保存到本地存储中;
方法一 : 在 CRUD 中 分别调用保存数据的方法,(不推荐 太繁琐)
方法二 : 想办法监听 list 数据的改变,只要 list 数据变了, 就调用保存数据的方法
可以使用 vue 的 watch 监听 list 的数据改变
- 存储值
监听数组和监听对象一样 需要深度监听
保存值,记得把对象转化为字符串(存的快 省空间)
// 监听
watch: {
// 监听list
todoList: {
deep: true,
handler(newVal) {
// console.log('发生变化了', newVal)
// 保存起来
localStorage.setItem('todoList', JSON.stringify(newVal))
}
}
},
- 取值 , 在 data 中可以初始值
记得给一个默认值 空数组 []
const todoList = JSON.parse(localStorage.getItem('todoList')) || [],
过滤器
- 概念 :
- vue 中的过滤器(filter) : 数据格式化 ,
- 也就是说,让数据按照我们规定的一种格式输出
- 比如 : 对于日期来说,将日期格式化转化为
年-月-日 小时:分:秒
格式的过程
// 直接显示
<h1>{{ date }}</h1>
显示 : 2019-01-11T10:11:19.566Z
不是我们想要的
我们想要的 : 2019-01-11 18-11-53
- 全局过滤器 和 局部过滤器
- 说明 : 通过全局方式创建的过滤器,在任何一个 Vue 实例中都可以使用 (一般情况下,为了项目方便管理,都是一个 vue 实例)
- 注意点: 使用全局过滤器的时候,应该先创建全局过滤器,再创建 Vue 实例
- 局部创建的过滤器 只能在当前 vue 实例中使用
- 怎么注册 全局过滤器
// 第一个参数 : 过滤器的名字
// 第二个参数 : 是一个回调函数,只要使用过滤器的时候,这个回调函数就会执行
/// 通过回调函数的返回值得到格式化后的数据
Vue.filter('date', res => {
return '嘻嘻'
})
- 使用过滤器 示例 :
// 组件
<h1>时间戳-格式 {{ date2 | date }}</h1>
// js
Vue.filter('date', res => {
return `${res.getFullYear()}-${res.getMonth()}-${res.getDate()} ${res.getHours()}:${res.getMinutes()}:${res.getSeconds()}`
})
- moment 插件
-
使用
1. 安装 : `npm i moment` 2. 引入 : 3. 使用
-
日期 => 指定格式
moment(res).format('YYYY-MM-DD HH-mm-ss')
-
时间戳 => 指定格式
moment(res).format('YYYY-MM-DD HH-mm-ss')
-
// 全局 Vue.filter('date', res => { return moment(res).format('YYYY-MM-DD HH-mm-ss') })
- 参数问题
- 示例
<h1>时间戳-格式 {{ date2 | date('YYYY-MM-DD HH-mm-ss',888) }}</h1>
// 默认值
Vue.filter('date', (res, format = 'YYYY-MM-DD', arg) => {
console.log(arg)
return moment(res).format(format)
})
- 局部过滤器
在 vm 的配置项里写一个
filters
对应的是一个对象
filters: {
date(res, format = 'YYYY-MM-DD', arg) {
return moment(res).format(format)
}
}
五、生命周期函数
- 所有的 vue 组件,都是 vue 实例, 一个组件对应一个实例,并且接收相同的选项对象(一些根实例特有的选项除外)
- 实例生命周期也叫做 : 组件生命周期
生命周期介绍
- 简单说 : 一个组件(实例) 从开始到最后消灭所经历的各种状态,就是一个组件(实例)的生命周期
- 生命周期钩子函数的定义 : 从组件被创建,到组件挂在到页面上运行,再到页面关闭组件被销毁,这三个阶段总是伴随着组件各种的事件,这些事件,统称为组件的生命周期函数 (简称 : 钩子函数)
- 开发人员可以通过 vue 提供的钩子函数,让我们写的代码参与到 vue 的生命周期里面来,让我们的代码在合适的阶段起到相应的作用
注意 :
- 注意 : vue 在执行过程中 会自动调用
生命周期钩子函数
, 我们只需要提供这些钩子函数即可 - 注意 : 钩子函数的名称都是 vue 中规定好的
5.0 学习 vue 组件生命周期 学什么?
- Vue 内部执行的流程(难)
- 钩子函数如何使用 (两个重要的钩子函数 created mounted)
5.1 钩子函数 - beforeCreate
-
说明 : 在实例初始化之前,数据观测 和 event/watcher 事件配置之前被调用
-
组件实例刚被创建,组件属性计算之前, 例如 data 属性 methods 属性
-
注意 : 此时,无法获取 data 中的数据 和 methoids 中的方法
-
场景 : 几乎不用
5.2 钩子函数 - created (掌握)
-
说明 : 组件实例创建完成,属性已绑定, 可以调用 methods 中的方法、可以获取 data 值
-
使用场景 : 1-发送 ajax 2-本地存储获取数据
-
beforeCreate() { // 无法获取数据和事件 console.warn('beforeCreate', this.msg, this.fn) }, created() { console.warn('created', this.msg, this.fn) },
Has 'el' option ?
- YES => 就是正常的 el 边界
- NO => 可以注释,但是必须要手动添加
vm.$mount(el)
去指定边界
vm.$mount('#app')
Has template
option?
- No => 将 el 的 outerHtml 作为模板进行编译 ( outerHTML = 自身 + innerHTML )
- YES =>
// 如果提供了 template, 那么 vue 就会将 template 的内容进行编译,编译后,替换页面中 vue 管理的边界
template : `
<h1>嘻嘻</h1>
`,
5.3 钩子函数 - beforeMounted()
- 说明 : 在挂载开始之前被调用 (挂载:可以理解DOM 渲染)
5.3 钩子函数 - mounted() (掌握)
-
说明 : 挂载之后, DOM 完成渲染
-
使用场景 : 1-发送 ajax 2-操作 DOM
-
记得把template去掉 // 渲染DOM之前 beforeMount() { // 渲染之前的 <h1 id="h1" @click="fn">{{ msg }}</h1> console.log(document.querySelector('h1')) }, // 渲染DOM之后 <h1 id="h1">测试</h1> mounted() { console.log(document.querySelector('h1')) }
5.4 钩子函数 - beforeUpdated()
- 说明:数据更新时调用,发生在虚拟 DOM 重新渲染和打补丁之前。你可以在这个钩子中进一步地更改状态,这不会触发附加的重渲染过程。
- 注意:此处获取的数据是更新后的数据,但是获取页面中的 DOM 元素是更新之前的
小提示 : 打印 this.$el ,打开小三角是之后的,是因为打印是有监听的功能,展示的是后面更改之后的
5.5 钩子函数 - updated()
-
说明:组件 DOM 已经更新,所以你现在可以执行依赖于 DOM 的操作。
-
beforeUpdate() { // 更新之前的值 : 信息 console.warn('beforeUpdate',document.querySelector('h1').innerText) }, updated() { // 更新之后的值 : 信息1111 console.warn('updated', document.querySelector('h1').innerText) }
5.6 钩子函数 - beforeDestroy()
- 说明:实例销毁之前调用。在这一步,实例仍然完全可用。
- 使用场景:实例销毁之前,执行清理任务,比如:清除定时器等
created() {
this.timerId = setInterval(() => {
console.log(1111);
}, 500);
},
// 如果当组件销毁了,还不清除定时器会出现性能问题
// 在浏览器中可以尝试销毁 vm.$destroy()
// 最后销毁
beforeDestroy() {
clearInterval(this.timerId)
},
5.7 钩子函数 - destroyed()
说明:Vue 实例销毁后调用。调用后,Vue 实例指示的所有东西都会解绑定,所有的事件监听器会被移除,所有的子实例也会被销毁。
六 : 使用钩子函数来完善 数据存储
created {
this.list = JSON.parse(localStorage.getItem('list'))
}