vue 学科年级学段多级联动需求 跨组件如何监听 如何解决vue-communicatio监听多个参数的问题 以及vue-communicatio的注意事项

最近的项目中有这么一个需求
vue 学科年级学段多级联动需求 跨组件如何监听 如何解决vue-communicatio监听多个参数的问题 以及vue-communicatio的注意事项_第1张图片
先解释一下需求
顶部是一个多级联动的组件,用来选择学段,年级和科目,同时左侧的教材和知识点的树形结构受到顶部三个字段的影响,随之变动而变动

顶部的联动解决方案是使用 watch 监听,这应该是个很常见的方案,不多赘述

主要是左侧与顶部的联动,因为这是两个组件,首先要解决传值的问题,我的第一想法是vuex,但感觉有点繁琐,后来发现了 一个组件叫做 vue-communication 地址如下

https://www.npmjs.com/package/vue-communication

这个组件主要解决的就是跨组件监听和传值,我查看了文档发现
vue 学科年级学段多级联动需求 跨组件如何监听 如何解决vue-communicatio监听多个参数的问题 以及vue-communicatio的注意事项_第2张图片
ok 非常完美

直接上手,具体安装引入和使用可以查看文档,非常简单

mounted() {
 var self = this;
 this.$sender("watch-SideBar-Tab", "activeSubjectId", function (nv, ov) {
      console.log("我是sidebar");
      if (nv !== ov) {
        getKnowLedgeTree(nv).then((res) => {
          res.data.forEach((item) => {
            self.$set(item, "icon", "iconfont icon-wenjian");
          });
          self["_data"]["menuListForKnowledge"] = res.data;
        });
      }
    });
}

这里面要注意一点 this.$sender 的回调中获取不到 this 可以是定义一个变量等于 this

var self = this

因为左侧导航栏的知识点只和顶部的科目有关,所以到这一步确实成功了,知识点的树形结构会随着科目的变化而变化

但是我在对接教材的时候发现,教材是受两个变量的影响除了科目 还有一个年级
这就说明我们需要监听顶部组件的两个变量

但是文档里并没有写可以监听多个变量,我试着将两个变量组合成一个object,但是组件报错,只能接受一个基本类型的数据,不能接受引用类型的数据,我又试着再写一个
this.$sender,同时在顶部组件再写一个 $receiver,组件再次报错,也就是说组件只能监听一个变量?

摸索半天没有摸索出跨组件监听如何监听多个变量的写法

这时我发现组件还有个发送数据的方法,并且可以发送多次

vue 学科年级学段多级联动需求 跨组件如何监听 如何解决vue-communicatio监听多个参数的问题 以及vue-communicatio的注意事项_第3张图片
我想了下,既然左侧组件要监听顶部组件中的多个数据,那么我在顶部组件中先对我要监听的多个数据进行监听 (watch)然后,再将值发送给左侧组件不是一个效果吗

ok,直接上手

顶部组件代码

//顶部组件
watch: {
    activeStageId: async function (val) {
      // console.log(val);
      const gradeRes = await this.getGrade(val);
      this.gradeList = gradeRes.data.gradeList;
    },
    activeGradeId: async function (val, ov) { //需要监听的 年级Id
      // console.log(val);
      // console.log(ov);
      const subjectRes = await this.getSubject(val);
      this.subjectList = subjectRes.data;
      this.$sender('data-SideBar-Tab', //发送数据 (年级id改变)
      {graN: this.activeGradeId, graO: ov, sub: this.activeSubjectId})
    },
    activeSubjectId: async function(val, ov) { //需要监听的 科目Id
      // const editionRes = await this.getBookEdition(val)
      // const knowLedgeRes = await this.getKnowLedgeTree(val)
      this.$sender('data-SideBar-Tab',  //发送数据 (科目id改变)
      {subN: this.activeSubjectId, subO: ov, gra: this.activeGradeId})
      // console.log(knowLedgeRes)
    }
  },

左侧组件代码

created() {
    let self = this;
    this.$receiver("data-SideBar-Tab",  function (data) {
      if (data.graN) {
        // console.log(data, '年级修改');
        self.getBookEdition(data.sub, data.graN)
        //说明年级修改
      } else if (data.subN) {
        // console.log(data, '科目修改');
        //科目修改
        getKnowLedgeTree(data.subN).then((res) => {
          res.data.forEach((item) => {
            self.$set(item, "icon", "iconfont icon-wenjian");
          });
          self["_data"]["menuListForKnowledge"] = res.data;
        });
        self.getBookEdition(data.subN, data.gra)
      }
    });
  },

这里还要说明一点,在顶部导航中可以写多个

this.$sender

用来发送多个数据
但是在接受数据的组件中只需要写一次

this.$receiver

这个 receiver 会多次触发,每次触发都会获取到传过来的数据
也就是说年级改变的时候 会触发一次 receiver 获取到新的年级id
科目改变的时候 还会触发一次 receiver 获取到新的科目id

你可以将传过来的数据添加自定义key值用来区分到底传过来的是什么

就像这一段

this.$sender('data-SideBar-Tab',  //发送数据
      {subN: this.activeSubjectId, subO: ov, gra: this.activeGradeId})

虽然写在created里,但是这个会多次触发,不用担心

拿到数据就可以做接下来的操作了,获取教材树形结构的数据

再说个问题:
有可能只切换学科,不切换年级以及另一种切换年级不切换学科,这种情况不常见,切换年级会自动选择该年级的第一门学科,
按道理各年级的科目id应该是不一致的,但是如果有年级的相同科目的id是相同的话会出现一个问题,我在测试的时候就遇到了

回顾一下我们监听年级和科目id的代码

1.在顶部组件中先监听,一旦改变就发送给左侧组件
2.在左侧组件中接受

现在问题就是如果相同年级切换科目时,我在改变科目的时候,年级id可能出现不会改变的情况,那么左侧组件就获取不到传过来的 年级id,那调试接口的时候可能 年级id 就为undefined,所以我在传值的时候,在科目id改变时将当前的年级id一起传过去,防止年级id没有变化,没变就用当前值,在年级id改变时将当前的科目id也传过去,防止科目id没变化

 this.$sender('data-SideBar-Tab', //发送数据 (年级id改变)
      {graN: this.activeGradeId, graO: ov, sub: this.activeSubjectId})
      // sub 就是当前科目id

 this.$sender('data-SideBar-Tab',  //发送数据 (科目id改变)
      {subN: this.activeSubjectId, subO: ov, gra: this.activeGradeId})
      //gra就是当前年级id

你可能感兴趣的:(vue.js,javascript,ecmascript)