Vue一个案例引发的动态组件与全局事件绑定总结

作者 : 开心源码 本文共2768个字,预计阅读时间需要7分钟 发布时间: 2022-05-12 共114人阅读

技术这东西真的不能光靠看,看是没有的,你必需要动手实践,只有在实战项目中才能发现问题,才能发现我们没有掌握的知识点,而后发现问题处理问题,我们的能力才能得以提升,要不然就有点眼高手低了。

基于这个想法于是就开始自己去撸了一个旅游网站,旅游网站嘛避免不了城市的选择,所以在实现城市选择列表的时候碰到的少量问题,以及处理办法今天就记录下来做一个总结。

城市列表选择组件

首先说说我们要实现一个什么样的城市选择组件:

  1. 输入框获取焦点时,显示组件
  2. 点击城市列表升级输入框的城市显示
  3. 点击其余空白处组件隐藏
  4. 在切换到其余组件时,选择的城市保留而不是被重置

下面我们就一步一步的来拆解

第一步

输入框获取焦点后显示组件很简单,我们给输入框绑定焦点事件而后给组件传入一个显示的状态就可,我们把 isShowCityList 传递给城市选择组件控制行为。

<el-input     @focus="isShowCityList=true"    placeholder="请输入目的地"></el-input>

第二步

我们也不做过多的表述本文想更多的是详情动态组件与全局事件的绑定,利用的是子组件给父组件利用自己设置事件 $emit 传给父组件。

第三步

需要我们去点击其余地方城市组件被隐藏,有些同学的第一印象可能是利用 input 的 blur 事件(就是失去焦点事件),只需我们的 input 失去焦点时,我们就隐藏。

其实我的第一印象也是如此,但是我们绑定的是 input 的失去焦点事件以后,当我们选择城市列表的时候也是 input 失去焦点的时候,所以我们就无法选取城市。显然这种思路是不行的。

所以这里我们只能去用到 Vue 的全局事件的绑定,而后去进行一个判断我们点击的节点是哪里,假如是城市组件以外我们就进行隐藏操作。

我们在 mounted 钩子函数中,进行如下操作。

mounted() {    document.addEventListener("click", e => {        console.log('全局事件被触发');        if (!this.$refs.searchCity.contains(e.target)) {            this.isLoadCityList = false;        }    });}

OK,进行这一步之后,我们的问题得到理解决,只需我们点击这个容器以外的地方就会隐藏城市列表组件,我以为算是结束了,不过那是不可能的,还是我太年轻了,这样做的后果就是不论我们点击任何一个地方它都会触发这个事件,即便是我们切换到其余组件时,事件照样会被触发,显然这个不是我们想要的,由于当前事件会被无限触发,无疑会给我们带来不可预见的问题。

我们需要的最好效果一定是当前的全局事件就在当前的组件下产生作用,当我们切换到其余组件时,事件自动删除,于是我可能想到的就是利用 beforeDestroy 钩子函数去删除这个全局事件。也就是当我们切换到其余组件时,去删除这个全局事件。

beforeDestroy() {    document.removeEventListener("click", () => {      //...    });}

你以为这样我还就能处理问题了吗?显然还是不能,还是太年轻,只是这样我们是解除不了绑定的事件,那我们该怎样办呢?其实这里面有一个坑,大坑,由于这个大坑自己不知道,差了许多资料也没查出来,由于差的思路错了,最后在一个群里问了一个大佬,才得出答案,不得不说与前辈交流很重要啊,能帮你少踩很多坑。

这里假如想要解除绑定,解除和绑定的两个回调函数必需一致,什么意思呢?看代码你就明白。假如不这么操作,你是解除不掉事件的,至于更深的起因我也不怎样明白了,以后再去查阅少量资料。

methods: {  isSearchCityNode(e) {    if (!this.$refs.searchCity.contains(e.target)) {      console.log("全局事件被触发");      this.isLoadCityList = false;    }  }  },mounted() {    document.addEventListener("click", this.isSearchCityNode);},beforeDestroy() {    document.removeEventListener("click", this.isSearchCityNode);}

第四步

需要我们在切换组件的时候保留我们选择的城市,假如不保留我们每次切换到其余组件时,我们选择的城市都会被重置为默认值,这个体验一定是肯差的,也不是我们想要的。

被重置的起因则是我们在每次在不同的组件进行切换的时候,组件都会进行新建与销毁,这也会导致重复渲染问题对性能也是不友好的。

那么我们该如何去解决这个问题呢? 我这里使用了 keep-alive 去处理这个问题,那么 keep-alive 该如何使用以及作用是什么呢?

<keep-alive>  <component v-bind:is="currentTabComponent"></component></keep-alive>

包裹动态组件时,会缓存不活动的组件实例,而不是销毁它们,它自身不会渲染一个 DOM 元素,也不会出现在父组件链中。

但是当我们使用 的时候,我们的 beforeDestroy 钩子函数就会失效,导致我们第三步的全局事件的解绑就不能执行了,起因是我们的组件是被缓存起来,并没有被销毁。自然会失效,但是我们并不慌,当我们使用 时,activated 和 deactivated 两个钩子函数被触发。

activated:keep-alive 组件激活时调用。

deactivated:keep-alive 组件停用时调用。

所以我们不难发现,我们完全可以使用这两个钩子去实现我们全局事件的绑定与解绑,简直完美。

activated() {    document.addEventListener("click", this.isSearchCityNode);},deactivated() {    document.removeEventListener("click", this.isSearchCityNode);}

总结

通过一个城市列表组件的案例,详情了我们在 Vue 中如何绑定全局事件以及进行优化,肯定要记住事件的绑定与解除哪里有一个大坑。

我们通过 可以创立一个可以缓存的组件,而且会新添加两个钩子函数提供我们使用

文中如有不足之处,欢迎大神拍砖!

本次给大家推荐一个免费的学习群,里面概括移动应用网站开发,css,html,webpack,vue node angular以及面试资源等。
对web开发技术感兴趣的同学,欢迎加入Q群:943129070,不论你是小白还是大牛我都欢迎,还有大牛整理的一套高效率学习路线和教程与您免费分享,同时每天升级视频资料。
最后,祝大家早日学有所成,拿到满意offer,快速升职加薪,走上人生巅峰。

说明
1. 本站所有资源来源于用户上传和网络,如有侵权请邮件联系站长!
2. 分享目的仅供大家学习和交流,您必须在下载后24小时内删除!
3. 不得使用于非法商业用途,不得违反国家法律。否则后果自负!
4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解!
5. 如有链接无法下载、失效或广告,请联系管理员处理!
6. 本站资源售价只是摆设,本站源码仅提供给会员学习使用!
7. 如遇到加密压缩包,请使用360解压,如遇到无法解压的请联系管理员
开心源码网 » Vue一个案例引发的动态组件与全局事件绑定总结

发表回复