一、浏览器本地存储(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的本地存储
将我们写的案例里的数据存一份到本地数据当中去
我想的是在添加todos的地方再写个添加数据,删除再写删除、、、比较麻烦,用watch监视,然后把最新的todos直接给本地数据就行
watch:{
todos(newvalue){
localStorage.setItem('todos',JSON.stringify(newvalue))
//JSON.stringify将Js对象或值转换为JSON格式化的字符串
}
}
这么写的话数据是保存了但是一刷新还是什么数据都没有,因为我们默认的最开始数组就是空
todos:JSON.parse(localStorage.getItem('todos')) || []
//要是什么都没有todos就不是空数组而是null了,那就会报错,空数组还得往下传,所以或一下
//JSON.parse将格式完好的json字符串转换为json对象
做完之后又发现打勾之后再刷新勾就没有了,因为只是表层监视了一下,所以得深层监视
watch:{
// todos(newvalue){
// localStorage.setItem('todos',JSON.stringify(newvalue))
// //这样写的话监视只是表层监视,如果你打勾了刷新就没勾了
// }
todos:{
deep:true,
handler(newvalue){
localStorage.setItem('todos',JSON.stringify(newvalue))
}
}
}
二、组件自定义事件
自定义事件是给组件用的
儿子给父亲传递数据
1.父亲先给儿子传递函数
app父亲:
<mySchool :getSchoolName="getSchoolName"/>
methods: {
getSchoolName(name){
console.log(name)
},
儿子:
<button @click="get(name)">点我获取学校名字</button>
props:['getSchoolName'],
methods:{
get(name){
this.getSchoolName(name)
}
}
2.绑定一个自定义事件
(1)v-on
app:
<myStudent v-on:atguigu="getStudentName"/>
<!-- 给student这个组件的实例对象vc身上绑定,有人触发事件调函数 -->
getStudentName(name){
console.log(name)
},
儿子:给谁绑的就找谁触发
<button @click="sendStudentName">点我发送student名字</button>
methods:{
sendStudentName(){
//emit是触发student组件实例vc的atguigu事件
this.$emit('atguigu',this.name)
}
}
相同点:都得配置回调函数
不同点,props得往子组件传东西然后子组件亲自收到并调用,但是自定义事件不给儿子传东西,而是给他绑定自定义事件,然后当回调使用,事件名aiteguigu写对才行
(2)ref
app:
<myStudent ref="myStudent"/>
mounted(){
this.$refs.myStudent.$on('atguigu',this.getStudentName)
//当atguigu事件触发的时候我要进行回调get、、
//第一个参数是事件名,第二个参数是事件触发后的回调函数。
}
这种麻烦但是灵活性更强,可以用setTimeout
3.解绑
给谁绑定的就找谁去解绑
(1)解绑一个自定义事件
<button @click="unbind">点我解绑</button>
unbind(){
this.$off('atguigu')
}
(2)解绑多个自定义事件
this.$off(['atguigu','demo'])
以数组形式写多个事件的事件名
(3)解绑所有自定义事件
this.$off()
4.销毁
<button @click="death">点我销毁组件</button>
death(){
this.$destroy()
//销毁当前student的实例,销毁后所有自定义事件都不奏效
}
5.一些注意点
1-我们想在app中插入学生姓名
(注意插值语法只能是computed、props、data),props肯定不行,是从儿子传过来的,computed得是由原数据计算而来的,所以这个也不行,放data
(1)v-on的情况下直接让插值语法里面的name=传过来的name
data(){
return{
studentName:''
}
},
methods: {
getStudentName(name){
console.log(name)
this.studentName=name
},
(2)ref情况下
忽略箭头函数,如果我们把getStudentName写在methods里可以实现
但是把getStudentName用普通函数的方式写在mounted里的话就不可以实现,因为vue规定ref里的this是触发事件的对象也就是student,我们写在methods里,methods规定this就是vue
写成箭头函数的话也能实现,this也是vue
2-给组件设置原生dom事件
默认给组件设置的事件是自定义事件,加.native
@click.native="m2"
总结:
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指向会出问题!
三、TodoList自定义事件
中间是爷爷和孙子先不改,改header、footer
注意只能去修改父给子传函数的地方,不能改传数据数组的todos
app里涉及到的地方全加@
<myFooter :todos="todos"
@checkAllTodo="checkAllTodo"
@clearAllTodo="clearAllTodo"/>
methods:{
checkAll(e){
this.$emit('checkAllTodo',e.target.checked)
//还是得动app里的数据,得this.checkAllTodo,methods又没有
},
clearAll(){
this.$emit('clearAllTodo')
}
}