文章目录
一、浏览器本地存储(WebStorage)
存储内容大小一般支持5MB左右(不同浏览器可能还不一样)
浏览器端通过 Window.sessionStorage
和 Window.localStorage
属性来实现本地存储机制。
1.相关API
(1) xxxxxStorage.setItem('key', 'value')
;该方法接受一个键和值作为参数,会把键值对添加到存储中,如果键名存在,则更新其对应的值。
(2) xxxxxStorage.getItem('person')
;该方法接受一个键名作为参数,返回键名对应的值。
(3) xxxxxStorage.removeItem('key')
;该方法接受一个键名作为参数,并把该键名从存储中删除。
(4)xxxxxStorage.clear()
该方法会清空存储中的所有数据。
2.一些注意点
(1)SessionStorage
存储的内容会随着浏览器窗口关闭而消失。
(2) LocalStorage
存储的内容,需要手动清除才会消失(调用clear或者清除缓存)。
(3) xxxxxStorage.getItem(xxx)
如果xxx对应的value
获取不到,那么getItem
的返回值是null
。
(4)JSON.parse(null)
的结果依然是null
。
3.TodoList中的本地存储
这里面的几个细节:
1、用watch
监视todos
数据的变化,如果数据改变那么浏览器本地存储就存个缓存,名字还叫todos
,值是更新后的数组(要转化为JSON字符串浏览器才能显示)
2、只监视是没用的,如果只监视不读取,那么数据会缓存到浏览器,但是页面刷新网页不会同步,所以一定要在data中读取浏览器中的数据,当然页面一上来可能没有缓存(也没添加任何数据),那么这时候JSON.parse(localStorage.getItem('todos'))
就是null(这样会报错的),所以再来个逻辑或,如果是null
那么就todos
初始化为空数组呗,然后再自己往里儿加数据,后面再刷新就会直接读浏览器了(总结:初始化时如果有就读,没有就初始值为空数组)
3、还有,watch中要配置深度监视deep
,否则页面刷新已经勾选的就重置了,这是因为watch监视todos只会监视todos里面的元素,也就是每个对象的地址,但是对象属性的变化监测不到,但是加了deep
就监视到了
data() {
return {
// JSON.parse将格式完好的json字符串转换为json对象
//如果有就读,没有就初始值为空数组
todos: JSON.parse(localStorage.getItem('todos')) || []
};
},
JSON.stringify将Js对象或值转换为JSON格式化的字符串
JSON.parse将格式完好的json字符串转换为json对象
watch: {
todos: {
deep: true, //深度监视不加,那么todos里面的东西改了是监测不到的
handler(newVal) {
// JSON.parse将格式完好的json字符串转换为json对象
// JSON.stringify将Js对象或值转换为JSON格式化的字符串
localStorage.setItem('todos', JSON.stringify(newVal));
}
}
}
二、组件自定义事件
1、一种组件间通信的方式,适用于:子组件 ===> 父组件
2、使用场景:A是父组件,B是子组件,B想给A传数据,那么就要在A中给B的标签绑定自定义事件(事件的回调在A中,用来接收数据)。
3、绑定自定义事件:
(1) 第一种方式,在父组件中:
<Demo @atguigu="test"/>或 <Demo v-on:atguigu="test"/>
(2)第二种方式,在父组件中:
<Demo ref="demo"/>
......
mounted(){ this.$refs.xxx.$on('atguigu',this.test) }
(3)若想让自定义事件只能触发一次,可以使用.once修饰符,或$once
方法。
4、触发自定义事件:this.$emit('atguigu',数据)
给谁绑的就找谁触发
5、解绑自定义事件this.$off('atguigu')
6、组件上也可以绑定原生DOM事件,需要使用native
修饰符。
7、注意:通过this.$refs.xxx.$on('atguigu',回调)
绑定自定义事件时,回调要么配置在methods中,要么用箭头函数,否则this指向会出问题!
1.引出组件自定义事件
在之前我们想要实现子组件给父组件传数据,都是通过父组件给子组件传递函数类型的props实现,在App中:
<!-- 通过父组件给子组件传递函数类型的props实现:子给父传数据 -->
<School :getSchoolName="getSchoolName" />
getSchoolName(name) {
console.log('App收到了学校名:', name);
},
然后在School中使用props接收,然后把name传过来。
<button @click="sendSchoolName(name)">点击把name交给App</button>
props: ['getSchoolName'],
methods: {
sendSchoolName(name) {
this.getSchoolName(name);
}
},
2.怎么给组件绑定?
(1)使用v-on
上面的子给父传数据,如今我们也可以换一种方式实现,那就是通过父组件给子组件绑定一个自定义事件实现。kiwi
事件被触发,就会调用getStudentName
<!-- 通过父组件给子组件绑定一个自定义事件实现:子给父传数据(第一种写法,使用v-on或@) -->
<Student v-on:kiwi="getStudentName"></Student>
getStudentName(name, age) {
console.log('App收到了学生名:', name, age);
}
然后在Student组件中触发这个事件,使用$emit
,第一个参数是事件名,后面的是实参,使用函数可以触发Student中的zzy事件
<button @click="sendStudentName">点我把学生名给App</button>
sendStudentName() {
//触发Student组件实例身上的kiwi事件,并传数据过去
this.$emit('kiwi', this.name, this.age);
}
(2)使用ref
使用ref也可以让父组件给子组件绑定一个自定义事件
<Student ref="student" />
使用ref获取组件实例,然后使用$on
绑定kiwi事件,第一个参数是事件名,第二个参数是事件触发后的回调函数。
触发方式和上面一样,用$emit
如果想只触发一次,用$once
methods: {
getSchoolName(name) {
console.log('App收到了学校名:', name);
},
getStudentName(name, age) {
console.log('App收到了学生名:', name, age);
}
},
//挂载完成时,手动把zzy事件绑定到student的vc上
mounted() {
// this.$refs.student.name???
setTimeout(() => {
//挂载完成后,隔3秒再给Student绑定事件
this.$refs.student.$on('kiwi', this.getStudentName);
}, 3000);
//挂载完成时,手动把kiwi事件绑定到student的vc上(且只能触发一次)
// this.$refs.student.$once('kiwi', this.getStudentName);
}
这种写法更灵活,可以异步
3.怎么解绑?
使用$off
解绑
<Student v-on:zzy="getStudentName" @ht="getStudentName"></Student>
//解绑一个自定义事件
this.$off('zzy');
//解绑多个自定义事件
this.$off(['zzy', 'ht']);
//解绑所有自定义事件
this.$off();
这里面有个很奇怪的地方,如果父组件写了多个Student标签(建立了多个vc),那么解绑的话只能解绑当前vc的自定义事件,其他vc的碰不到
4.几个注意点
1、销毁组件实例或者vm,其下面的自定义事件和原生DOM事件都会失效(老师的版本原生DOM事件不会失效,但是现在好像也会失效了,奇怪)
2、通过this.$refs.xxx.$on('atguigu',回调)
绑定自定义事件时,回调要么配置在methods中然后通过this.getStudentName
传过来。
this.$refs.student.$on('kiwi', this.getStudentName);
要么用箭头函数:
mounted() {
this.$refs.student.$on('kiwi', (name, ...arr) => {
console.log(this); //this指向App组件实例
this.studentName = name; //成功,因为this指向的是App组件实例对象
});
}
否则this指向会出问题!
mounted() {
this.$refs.student.$on('zzy', function (name, ...arr) {
console.log(this); //this指向Student组件实例
this.studentName = name; //失败,因为this指向的是Student组件实例对象
});
}
会出问题!
mounted() {
this.$refs.student.$on('zzy', function (name, ...arr) {
console.log(this); //this指向Student组件实例
this.studentName = name; //失败,因为this指向的是Student组件实例对象
});
}
3、组件上写的v-on
都会被当成自定义事件,即便是写@click
也会当成自定义事件,想要用原生DOM事件的话,需要加native
,比如@click.native = "demo"