最近在做一个WEBAPP项目,在使用$emit、$on做父子、兄弟节点数据传入的时候遇到很多问题,今天总结并分享一下。
一、单页面应用数据传输
Vue.js 的$emit与$on的基本概念我就不描述了,使用它大致是在根节点上定义一个“事件通道”,如下:
也就是另外定义一个Vue的实例,然后我的应用的单页面应用,只有一个根节点,通过router-view来渲染子页面,结构如下:
$emit的意思是“发送”,而$on是监听$on是瞬时的,所以在$emit还没有发送数据,$on就已经在监听了,他们之间需要写一个自定义函数,这个函数个人理解为两者之间的“标示”,用户区分不同的自定义函数,当然$on需要一个回调函数用来接受参数。。。。大致的结构如下:
接下来切入问题点,入坑开始。。。。
(1)在单页面应用中,$on、$emit需要在页面已经创建的情况下才能有效果
如我在登录页面进行登录,然后拿到用户信息、权限之类的,然后我在“订单”页面使用$on来监听登录页面是否登录或者是否登录成功,如果登录成功,则在订单页面可以查看到用户订单,如果失败,则订单页面返回登录页面。
可是在点击TAB跳转的时候,其实是在做页面create和destroy的动作,也就是做就算我登录成功了,如果监听页面没有被创建,是拿不到值的。
(2) $router与$route
这两个弄了我个把小时,在使用$router.push('/XXX',params:{XX:XX})的时候,一直拿不到传递过来的params,在网上搜了半天,才发现要写 $route.params.XX才能拿到值,在网上页面看明白两者的区别,大致如下:
$router为VueRouter实例
$route为当前router跳转对象,可以获取name、path、query、params等
(3)深入响应式
在给$emit设置参数的时候,将一个局部对象传递给了vue的data选项,然后再将这个对象传入$emit的自定义函数中:
然后在看看,console.log:
{__ob__:Observer}是什么鬼?而且子页面接受的参数也是这个,查询以后才知道:
Vue中的__ob__是保存Observer对象的,用来记录是否已经做过数据的“响应式化”,也就是是否已经被Observer处理过,最终是为了用Object.defineProperty进行数据的双向绑定。
也就是“user_info”这个对象被响应式化了,然后给你返回一个{__ob__:Observer},这个东西当然不能当作参数传入进去,另外为什么会被响应式化,是因为JS两种传值方式:
传值传递、传址传递
转值传递是参数的一个副本,形参副本数据改变,不会影响到原来的值
传址传递是在数组、对象赋值后,如果对这个数组、对象的属性、值进行操作,其原来的数组、对象也会发生改变,应用他们引用的是同一个地址
所以,当"user_info"赋值给this的时候,触发了this的set函数,将其响应式化,然后"user_info"也发生了改变