Vue项目笔记 Ant Design Vue Breadcrumb 面包屑 多层对象单向数据绑定问题

Vue项目笔记 Ant Design Vue Breadcrumb 面包屑 多层对象单向数据绑定问题

博客已搬运至掘金,欢迎访问!
主页https://juejin.cn/user/2524134429703063

问题描述

Ant Design Vue Breadcrumb面包屑.,采用和 vue-router 进行结合使用的方法。
组件中routes和实例数据单向绑定(v-bind),通过更新routes来更新breadcrumb。

实际操作中在更新了routes之后,实例数据更新了,但breadcrumb并没有更新,
检查之后发现应该是因为绑定的数据对象是多层的结构,而数据更新发生在其中的某一部分,所以没有重新渲染

<template>
  <div class="index">
    <section>
      <div id="content">
        <a-breadcrumb class="contentBreadcrumb" :routes="routes">
          <template slot="itemRender" slot-scope="{ route, routes, paths }">
            <span v-if="routes.indexOf(route) === routes.length - 1">
              {{ route.breadcrumbName }}
            </span>
            <router-link v-else :to="`${basePath}/${paths.join('/')}`">
              {{ route.breadcrumbName }}
            </router-link>
          </template>
        </a-breadcrumb>

        <h1>obj: {{ obj }}</h1>

        <h1>arr: {{ arr }}</h1>

        <nav>
          <router-link
            to=""
            @click.native="
              render_breadcrumb({
                path: `A`,
                breadcrumbName: `信息A`,
              })
            "
          >
            <div class="tab_label">
              <span> 信息A</span>
            </div>
          </router-link>
          <router-link
            to=""
            @click.native="
              render_breadcrumb({
                path: `B`,
                breadcrumbName: `信息B`,
              })
            "
          >
            <div class="tab_label">
              <span> 信息B</span>
            </div>
          </router-link>
          <router-link
            to=""
            @click.native="
              render_breadcrumb({
                path: `C`,
                breadcrumbName: `信息C`,
              })
            "
          >
            <div class="tab_label">
              <span> 信息C</span>
            </div>
          </router-link>
        </nav>
      </div>
    </section>
  </div>
</template>

<script>
export default {
  name: "Index",
  components: {},
  props: {
    // msg: String,
  },
  data() {
    return {
      msg: "Welcome to Your Vue.js App",

      basePath: "",
      routes: [
        {
          path: "",
          breadcrumbName: "首页",
        },
        {
          path: "",
          breadcrumbName: "信息公开",
        },
        {
          path: "",
          breadcrumbName: "最新信息",
        },
      ],

      arr: [{ ax: 1 }, { ay: 2 }, { az: 3 }],

      obj: { ox: 1, oy: 2, oz: 3 },
    };
  },
  watch: {

    routes(val, preVal) {
      console.log("routes change");
    },

    obj(val, preVal) {
      console.log("obj change");
    },

    arr(val, preVal) {
      console.log("arr change");
    },
  },
  methods: {
    render_breadcrumb(breadcrumb_item) {

      this.routes[this.routes.length - 1] = {
        path: "",
        breadcrumbName: `${breadcrumb_item.breadcrumbName}`,
      };

      console.log(this.routes);

    //   this.routes = [
    //     {
    //       path: "",
    //       breadcrumbName: "首页",
    //     },
    //     {
    //       path: "",
    //       breadcrumbName: "信息公开",
    //     },
    //     {
    //       path: "",
    //       breadcrumbName: `${breadcrumb_item.breadcrumbName}`,
    //     },
    //   ];

    //   console.log(this.routes);


    //   this.obj[this.obj.length - 1] = {
    //     path: "",
    //     breadcrumbName: `${breadcrumb_item.breadcrumbName}`,
    //   };

    //   console.log(this.obj);


    //   this.obj = [
    //     { ox: 1 },
    //     { oy: 2 },
    //     { oz: `${breadcrumb_item.breadcrumbName}` },
    //   ];

    //   console.log(this.obj);
    },
  },
};
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped lang="scss">
h3 {
  margin: 40px 0 0;
}
ul {
  list-style-type: none;
  padding: 0;
}
li {
  display: inline-block;
  margin: 0 10px;
}
a {
  color: #42b983;
}

#content {
  margin: auto;
  width: 65%;
  padding: 50px 0;
}

.contentBreadcrumb {
  font-size: 1rem;
  font-weight: 500;
  margin: 0 0 15px 0;
}

nav {
  margin: 50px 0;
}

nav .tab_label {
  width: 15%;
  margin: 15px 0;
  padding: 15px 25px;
  background-color: #409eff;
  color: #fff;
  font-weight: 700;
  text-align: center;
  border-radius: 1px;
}
</style>

问题原因和分析

原因

实例中定义的数据是一个多层的对象,如果通过对象内部的方法去更新部分数据,数据更新了,Vue实例可能无法监测到数据的变化,所以不会重新渲染(不知道这样表达准不准确)

分析
  1. 如果像这部分代码一样只更新部分数据,数据更新了,但breadcrumb并没有更新

    通过控制台打印的数据可知,数据更新了,但侦听器并没有监测到数据的变化

render_breadcrumb(breadcrumb_item) {

      this.routes[this.routes.length - 1] = {
        path: "",
        breadcrumbName: `${breadcrumb_item.breadcrumbName}`,
      };

      console.log(this.routes);

    
    },

在这里插入图片描述

  1. 将全部数据重新赋值,数据更新了,breadcrumb更新了
    通过控制台打印的数据可知,数据更新了,侦听器监测到了数据的变化
render_breadcrumb(breadcrumb_item) {
      //   this.routes[this.routes.length - 1] = {
      //     path: "",
      //     breadcrumbName: `${breadcrumb_item.breadcrumbName}`,
      //   };

      //   console.log(this.routes);

      this.routes = [
        {
          path: "",
          breadcrumbName: "首页",
        },
        {
          path: "",
          breadcrumbName: "信息公开",
        },
        {
          path: "",
          breadcrumbName: `${breadcrumb_item.breadcrumbName}`,
        },
      ];

      console.log(this.routes);

      
    },

在这里插入图片描述

猜想

为什么Vue实例侦听器并没有监测到数据的变化,没有重新渲染数据?

可能是因为如果通过实例数据去访问更新对象的部分数据,改变的是对象本身的数据,而实例数据和对象之间的引用关系并没有发生变化,所以侦听器并没有监测到数据的变化

通过给实例数据重新,实例数据和原来的对象之间的引用关系发生了变化,实例数据引用了新的对象,侦听器监测到数据的变化,重新渲染数据

解决方法

  1. 给实例数据重新赋值
  2. 通过Vue计算属性(computed)和侦听器(watch).
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值