存储数据------即将数据缓存. 这里用 localStorage 缓存. 这里还用到了深度监视.

Vue中组件通信的其他方式.

1. localStorage

localstorage 生命周期是永久, 这意味着除非用户显示的在浏览器提供的UI上清除 localStorage 信息, 否则这些信息将永远存在. 存放数据大小为一般为5 MB, 而且它仅在客户端(即浏览器)中保存, 不参与和服务器的通信.

localStorage 存储的数据都是以文件存储的, 数据格式都是文本类型(即字符串). 所以这就需要转换数据格式.

存储数据前: 利用JSON.stringify将对象转换成字符串

获取数据后: 利用JSON.parse将字符串转换成对象

1
2
3
4
5
6
JSON.stringify(Object)//将对象转换成字符串并返回
JSON.parse(str)//将字符串转换成对象并返回
localStorage.setItem("key","value");//以"key"为名称存储一个值"value"
localStorage.getItem("key");//获取名称为"key"的值
localStorage.removeItem("key");//删除名称为"key"的信息.
localStorage.clear();//清空localStorage中所有信息

2.存取时机

定义数据的时候, 将要用的数据从localStorage中取出数据. 当数据改变时, 将数据重新存到localStorage中.

提到了数据改变, 就用到了深度监视.

深度监视某个属性:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<script>
export default {
data () {
return {
//此时定义数据,从localStorage中将想要的数据取出.
//一开始localStorage中没有todos_key.
todos: JSON.parse(window.localStorage.getItem('todos_key') || '[]')
}
},
watch: {
todos: {
deep: true,//深度监视
handler: function (value) {
window.localStorage.setItem('todos_key', JSON.stringify(value))
}
}
}
//......//
}
</script>

3.数据存储优化

将上述的localStorage的读写过程封装在一个JS文件中.

4.组件间的通信

①自定义事件

之前我们组件之间的通信都是用的 propos 属性. 现在用自定义事件来进行组件通信.

自定义事件只能用于组件之间传递函数, 不能传递其他的.

一说到事件, 首先应考虑两点: ①绑定事件监听. ②触发(分发)事件.

在这里, 绑定自定义事件有两种方法:

  • ① @事件名=‘回调函数’. 例在Component标签对象上绑定myEvent事件: <Component @myEvent=“myEvent”/>. 这种方式只能用于父子组件之间的通信.
  • ② 利用 $on 函数给特定标签对象绑定事件. 先给该标签对象设置 ref 属性, 再用 this.$refs.xxx.$on(‘自定义事件名’, 回调函数).

触发事件的方式: 通过 $emit 函数触发自定义事件. this.$emit(‘自定义事件名’,参数…).

②消息订阅与发布

这种组件通信需要一个PubSub库.

通过 npm install --save pubsub-js 安装库到当前项目.

消息订阅可以类比绑定事件, 消息发布可以类比触发事件.

订阅消息与绑定事件都是一些异步操作, 在钩子函数 mounted 中书写相关代码即可.

消息订阅与发布的一种好处就是, 没有组件之间的限制, 任何组件之间都可以用.

步骤:

  • ①import库
  • ②在mounted中订阅消息 PubSub.subscribe(‘消息名’, 回调函数)
  • ③在需要时发布消息. PubSub.publish(‘消息名’, 参数…)
1
2
3
PubSub.subscribe('delToDos', (msg, index) => {//最好用箭头函数, 防止this出错
this.delToDos(index)
})

③slot

此种方式用于父组件向子组件传递标签数据. 在子组件的内部, 已经事先定义好了一些"插口", 父组件只需要说明把要显示的标签"插到"哪个插口即可. 这种方式不同于其他几种, 其他的都是传递的消息或数据.

这种方式适用于, 多个父组件共用一个子组件且要求的显示效果不同.

子组件声明插口, Child.vue:

1
2
3
4
5
6
7
8
9
10
11
<template>
<div class="demo">
<label>
<slot name="slot1"></slot>
</label>
<span>
<slot name="slot2"></slot>
</span>
<slot name="slot3"></slot>
</div>
</template>

父组件根据插口属性将标签插入子组件, Parent.vue:

1
2
3
4
5
6
7
8
9
<template>
<div class="demo">
<Child>
<input type="checkbox" slot="slot1"/>
<span slot="slot2" >Hello Slot2</span>
<button slot="slot3">清除已完成任务</button>
</Child>
</div>
</template>

评论