vuejs реактивность сложных объектов - PullRequest
0 голосов
/ 11 октября 2018

Я использую Vue.js 2.5.17 У меня есть два компонента: App (родительский) и TreeNode (дочерний), которые отображают древовидную структуру элементов глубоко вложенного объекта.Каждый узел в дереве представлен компонентом TreeNode, который является рекурсивным компонентом.

компонент TreeNode

const TreeNode = Vue.component('TreeNode', {
    name: 'TreeNode',
    template: '#treenode',
    props: {
      model: Object,
    },
    data() {
      return {
        open: false,
      };
    },
    computed: {
      isExpandable() {
        return this.model.children &&
          this.model.children.length;
      },
    },
    methods: {
      toggle() {
        if (this.isExpandable) {
          this.open = !this.open;
        }
      },
    },
  });

шаблон TreeNode

<script type="text/x-template" id="treenode">
  <li>
    <input type="checkbox" :id="model.name" style="display:none;"/>
    <label :for="model.name" style="color:gray;" @click="toggle">
      {{ model.name }}
      {{ model.data.example }}
    </label>
    <ul v-show="open" v-if="isExpandable">
      <TreeNode
        class="item"
        v-for="(model, index) in model.children"
        :key="index"
        :model="model">
      </TreeNode>
    </ul>
  </li>
</script>

шаблон компонента приложения

<script type="text/x-template" id="oulist">
  <div>
    <div id="unitsTable" class="row filterlist treelist b_widget2" style="width:85%;">
      <div class="css-treeview">
          <TreeNode
            class="item"
            :model="items">
          </TreeNode>
      </div>
    </div>
</script>

Компонент приложения

const App = Vue.component('App', {
    template: '#oulist',
    components: {
      TreeNode,
    },
    data() {
      return {
        items: { 
          name: 'item1',
          data: { example: '1' },
          children: [
            { 
              name: 'item11',
              children: [],
              data: { example: '1' },
            },
            {
              name: 'item12',
              children: [
                { name: 'item121', children: [], data: { example: '1' } },
                { name: 'item122', children: [], data: { example: '1' } },
              ],
              data: { example: '1' },
            },
          ],
        },
      };
    },
    methods: {
      updateItem(currNode, name, data) {
        if (currNode.name === name) {
          Object.assign(currNode.data, data);
          this.items = Object.assign({}, this.items); // tried to create a new object here and overwrite it, but it didn't help
          return;
        }
        if (currNode.children) {
          currNode.children.forEach(c => this.updateItem(c, name, data));
        }
      },
    },
});

Приведенный выше объект является лишь примером, у моего реального объекта гораздо больше вложенных уровней и элементов на уровень.

Проблема в том,Я сталкиваюсь с тем, что всякий раз, когда свойство глубоко в моем объекте элементов изменяется (точнее, примерное свойство объекта данных внутри узла), DOM не обновляется.Я прочитал предупреждения о реактивности и увидел, что добавление новых свойств не является реактивным по умолчанию, но я не добавляю новые свойства здесь, просто изменяю существующие.

Когда данные из узла дерева обновляются, я пересекаюобъект, чтобы найти правильный узел и обновить его свойства следующим образом:

updateItem(currNode, name, data) {
  if (currNode.name === name) {
    Object.assign(currNode.data, data);
    this.items = Object.assign({}, this.items); // tried to create a new object here and overwrite it, but it didn't help
    return;
  }
  if (currNode.children) {
    currNode.children.forEach(c => this.updateItem(c, name, data));
  }
},

this.updateItem(this.items, 'item121', { example: 'newVal' });

Любые советы?Спасибо!

РЕДАКТИРОВАТЬ: данные всегда изменяются только в родительском (App) компонент.

...