🥔:山不向我走来,我便向它走去
更多Vue知识请点击——Vue.js
一、浏览器本地存储(WebStorage)
存储内容大小一般支持5MB左右(不同浏览器可能还不一样)
浏览器端通过 Window.sessionStorage
和 Window.localStorage
属性来实现本地存储机制。
1.相关API
(1) xxxxxStorage.setItem('key', 'value');
该方法接受一个键和值作为参数,会把键值对添加到存储中,如果键名存在,则更新其对应的值。
(2) xxxxxStorage.getItem('person');
该方法接受一个键名作为参数,返回键名对应的值。
(3) xxxxxStorage.removeItem('key');
该方法接受一个键名作为参数,并把该键名从存储中删除。
(4)xxxxxStorage.clear()
该方法会清空存储中的所有数据。
- localStorage
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>localStorage</title>
</head>
<body>
<h2>localStorage</h2>
<button onclick="saveDate()">点我保存一个数据</button>
<button onclick="readDate()">点我读取一个数据</button>
<button onclick="deleteDate()">点我删除一个数据</button>
<button onclick="deleteAllDate()">点我清空一个数据</button>
</body>
<script>
let p = {
name: '张三',
age: 18,
}
function saveDate() {
localStorage.setItem('msg', 'hello!')
localStorage.setItem('msg2', 666)
localStorage.setItem('person', JSON.stringify(p))
}
function readDate() {
console.log(localStorage.getItem('msg'))
console.log(localStorage.getItem('msg2'))
const result = localStorage.getItem('person')
console.log(result)
console.log(localStorage.getItem('msg3')) //由于没有msg3所以返回null
}
function deleteDate() {
localStorage.removeItem('msg2')
}
function deleteAllDate() {
localStorage.clear()
}
</script>
</html>
- SessionStorage
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>sessionStorage</title>
</head>
<body>
<h2>sessionStorage</h2>
<button onclick="saveDate()">点我保存一个数据</button>
<button onclick="readDate()">点我读取一个数据</button>
<button onclick="deleteDate()">点我删除一个数据</button>
<button onclick="deleteAllDate()">点我清空一个数据</button>
</body>
<script>
let p = {
name: '张三',
age: 18,
}
function saveDate() {
sessionStorage.setItem('msg', 'hello!')
sessionStorage.setItem('msg2', 666)
sessionStorage.setItem('person', JSON.stringify(p))
}
function readDate() {
console.log(sessionStorage.getItem('msg'))
console.log(sessionStorage.getItem('msg2'))
const result = sessionStorage.getItem('person')
console.log(result)
console.log(sessionStorage.getItem('msg3')) //由于没有msg3所以返回null
}
function deleteDate() {
sessionStorage.removeItem('msg2')
}
function deleteAllDate() {
sessionStorage.clear()
}
</script>
</html>
2.一些注意点
(1)SessionStorage
存储的内容会随着浏览器窗口关闭而消失。
(2) LocalStorage
存储的内容,需要手动清除才会消失(调用clear或者清除缓存)。
(3) xxxxxStorage.getItem(xxx)
如果xxx对应的value获取不到,那么getItem的返回值是null。
(4)JSON.parse(null)
的结果依然是null。
3.TodoList中的本地存储
我们上一次做的案例(TodoList案例)还不够完善,当我们重新刷新页面时,我们的数据就会丢失,这里我们可以利用本地存储,让数据存储下来。
这里面的几个细节:
1、用watch监视todos数据的变化,如果数据改变那么浏览器本地存储就存个缓存,名字还叫todos,值是更新后的数组
- 要转化为JSON字符串(
JSON.stringify()
)浏览器才能显示
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')) || []
};
},
watch: {
//这个写法只能监视到todo对象的增加删除这些浅层的,如果想监视到里面属性的变化,比如done的true还是false,就要开启深度监视
// todos(value) {
// localStorage.setItem('todos', JSON.stringify(value))
// },
todos: {
//开启深度监视
deep: true,
handler(value) {
localStorage.setItem('todos', JSON.stringify(value))
},
},
},
-
JSON.stringify
将Js对象或值转换为JSON格式化的字符串 -
JSON.parse
将格式完好的json字符串转换为json对象
二、组件自定义事件
组件自定义事件是指在Vue中,我们可以自己定义并使用的事件。与内置事件不同,组件自定义事件是由开发者自己定义的,包含事件名和事件回调等内容。它是一种用于组件间通信的方式,特别适用于子组件向父组件传递数据。通过定义好的自定义事件,我们可以在子组件中触发事件,并将需要传递的数据作为参数传递给父组件。这样,父组件就可以在事件回调中获取到子组件传递过来的数据,并进行相应的处理。
1、引出组件自定义事件
在之前我们想要实现子组件给父组件传数据,都是通过父组件给子组件传递函数类型的props实现,此处要求School.vue把name传给App.vue。我们以前的做法如下:
- App.vue:
<template>
<div class="app">
<h1>{{ msg }}</h1>
<!-- 通过父组件给子组件传递函数类型的props实现:子给符传递数据 -->
<School :getSchoolName="getSchoolName" />
</div>
</template>
<script>
import School from './components/School.vue'
export default {
name: 'App',
components: { School },
data() {
return {
msg: '你好呀',
}
},
methods: {
getSchoolName(name) {
console.log('App收到了学校名:', name)
},
},
}
</script>
<style>
.app {
background-color: gray;
}
</style>
- School.vue:在School中使用props接收,然后把name传过来。
<template>
<div class="school">
<h2>学校名称:{{ name }}</h2>
<h2>学校地址:{{ address }}</h2>
<button @click="sendSchoolName">把学校名给App</button>
</div>
</template>
<script>
export default {
name: 'School',
// 然后在School中使用props接收,然后把name传过来。
props: ['getSchoolName'],
data() {
return {
name: '哈哈大学',
address: '比奇堡',
}
},
methods: {
sendSchoolName() {
this.getSchoolName(this.name)
},
},
}
</script>
<style scoped>
.school {
background-color: skyblue;
}
</style>
2、给组件绑定自定义事件
(1)使用v-on
上面的子给父传数据,如今我们也可以换一种方式实现,那就是通过父组件给子组件绑定一个自定义事件实现。www
事件被触发,就会调用getStudentName
。
然后在Student组件中触发这个事件,使用$emit
,第一个参数是事件名,后面的是实参,使用函数可以触发Student中的zzy事件
- App.vue:
<template>
<div class="app">
<h1>{{ msg }}</h1>
<!-- 通过父组件给子组件绑定一个自定义事件实现:子给符传递数据(第一种写法,使用v-on或@) -->
<Student v-on:www="getStudentName" />
</div>
</template>
<script>
import Student from './components/Student.vue'
export default {
name: 'App',
components: { Student },
data() {
return {
msg: '你好呀',
}
},
methods: {
getStudentName(name) {
console.log('App收到了学生名:', name)
},
},
}
</script>
<style>
.app {
background-color: gray;
}
</style>
- Student.vue:
<template>
<div class="student">
<h2>学生姓名:{{ name }}</h2>
<h2>学生性别:{{ sex }}</h2>
<h2>学生年龄:{{ age }}</h2>
<button @click="sendStudentName">把学生名给App</button>
</div>
</template>
<script>
export default {
name: 'Student',
data() {
return {
name: 'potato',
sex: '女',
age: 18,
}
},
methods: {
sendStudentName() {
//触发Student组件实例身上的www事件
this.$emit('www', this.name)
},
},
}
</script>
<style scoped>
.student {
background-color: pink;
}
</style>
(2)使用ref
使用ref也可以让父组件给子组件绑定一个自定义事件。
使用ref获取组件实例,然后使用$on
绑定zzy事件,第一个参数是事件名,第二个参数是事件触发后的回调函数。
触发方式和上面一样,用$emit
如果想只触发一次,用$once
- App.vue:
<template>
<div class="app">
<h1>{{ msg }}</h1>
<!-- 通过父组件给子组件绑定一个自定义事件实现:子给符传递数据(第一种写法,使用v-on或@) -->
<!-- <Student v-on:www="getStudentName" /> -->
<!-- 通过父组件给子组件绑定一个自定义事件实现:子给符传递数据(第二种方法,使用ref属性) -->
<Student ref="student" />
</div>
</template>
<script>
import Student from './components/Student.vue'
export default {
name: 'App',
components: { Student },
data() {
return {
msg: '你好呀',
}
},
methods: {
getStudentName(name) {
console.log('App收到了学生名:', name)
},
},
mounted() {
// this.$refs.student.name???
setTimeout(() => {
//挂载完成后,隔3秒再给Student绑定事件
this.$refs.student.$on('www', this.getStudentName)
}, 3000)
},
}
</script>
<style>
.app {
background-color: gray;
}
</style>
- Student.vue:
<template>
<div class="school">
<h2>学习名称:{{ name }}</h2>
<h2>学校地址:{{ address }}</h2>
<button @click="sendSchoolName">把学校名给App</button>
</div>
</template>
<script>
export default {
name: 'School',
// 在School中使用props接收,然后把name传过来。
props: ['getSchoolName'],
data() {
return {
name: '哈哈大学',
address: '比奇堡',
}
},
methods: {
sendSchoolName() {
this.getSchoolName(this.name)
},
},
}
</script>
<style scoped>
.school {
background-color: skyblue;
}
</style>
这种写法更灵活,可以异步。仔细观察使用v-on和ref的区别。
注意:
- 通过
this.$refs.xxx.$on('xxx',回调)
绑定自定义事件时,回调要么配置在methods中然后通过this.getStudentName
传过来,要么用箭头函数,否则this指向会出问题。
3、解绑自定义事件
使用$off
解绑
$destroy
销毁组件实例(组件的所有自定义事件会失效)
<Student v-on:www="getStudentName" />
<template>
<div class="student">
<h2>学生姓名:{{ name }}</h2>
<h2>学生性别:{{ sex }}</h2>
<h2>学生年龄:{{ age }}</h2>
<button @click="add">点我年龄+1</button>
<button @click="sendStudentName">把学生名给App</button>
<button @click="unbind">解绑www事件</button>
<button @click="death">销毁当前Student组件的实例</button>
</div>
</template>
<script>
export default {
name: 'Student',
data() {
return {
name: 'potato',
sex: '女',
age: 18,
}
},
methods: {
add() {
this.age++
},
sendStudentName() {
//触发Student组件实例身上的www事件
this.$emit('www', this.name)
},
unbind() {
this.$off('www') //解绑一个自定义事件
// this.$off(['www', 'one', 'two']) //解绑多个自定义事件
// this.$off() //解绑所有自定义事件
},
death() {
this.$destroy() //销毁当前Student组件的实例,销毁后所有Student实例的自定义事件全部不奏效
},
},
}
</script>
<style scoped>
.student {
background-color: pink;
}
</style>
- 组件上写的
v-on
都会被当成自定义事件,即便是写@click
也会当成自定义事件,想要用原生DOM事件的话,需要加native
,比如@click.native = "demo"
4、总结
1、一种组件间通信的方式,适用于:子组件 ===> 父组件
2、使用场景:A是父组件,B是子组件,B想给A传数据,那么就要在A中给B的标签绑定自定义事件(事件的回调在A中,用来接收数据)。
3、绑定自定义事件:
(1) 第一种方式,在父组件中:
<Demo @www="test"/>或 <Demo v-on:www="test"/>
(2)第二种方式,在父组件中:
<Demo ref="demo"/>
......
mounted(){ this.$refs.xxx.$on('www',this.test) }
(3)若想让自定义事件只能触发一次,可以使用.once修饰符,或$once方法。
4、触发自定义事件:this.
e
m
i
t
(
′
a
t
g
u
i
g
u
′
,
数据
)
给谁绑的就找谁触发
5
、解绑自定义事件
t
h
i
s
.
emit('atguigu',数据)给谁绑的就找谁触发 5、解绑自定义事件this.
emit(′atguigu′,数据)给谁绑的就找谁触发5、解绑自定义事件this.off(‘atguigu’)
6、组件上也可以绑定原生DOM事件,需要使用native修饰符。
7、注意:通过this.
r
e
f
s
.
x
x
x
.
refs.xxx.
refs.xxx.on(‘atguigu’,回调)绑定自定义事件时,回调要么配置在methods中,要么用箭头函数,否则this指向会出问题!
5、案例:给TodoList添加自定义事件
Header和Footer用到了子传父(Item是孙传父了,自定义事件没发解决)
App里标签写,Header里触发,然后把值传过去。
此处只展示改动部分:文章来源:https://www.toymoban.com/news/detail-664721.html
- App.vue:
<TodolistHeader @addTodo="addTodo" />
<TodolistFooter
:todos="todos"
@checkAllTodo="checkAllTodo"
@clearAllTodo="clearAllTodo"
/>
- TodolistHeader.vue:
//3.借助App里的函数,把用户的输入从Header传给App里面的todos 然后再通过App把todos传给List,用这种捷径(借助App)就巧妙地实现了Header和List的兄弟组件通信
// this.addTodo(todoObj)
//使用自定义函数
this.$emit('addTodo', todoObj)
- TodolistFooter.vue:
methods: {
checkAll(e) {
// this.checkAllTodo(e.target.checked)
this.$emit('checkAllTodo', e.target.checked)
},
clearAll() {
// this.clearAllTodo() //点击调用App里边的方法,把所有为true的删掉
this.$emit('clearAllTodo')
},
},
此处不使用props了记得把props里的对应项删掉文章来源地址https://www.toymoban.com/news/detail-664721.html
到了这里,关于Vue2-浏览器本地存储(WebStorage)及完善TodoList案例、组件自定义事件及完善TodoList案例的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!