2015-05-08 2 views
24

Отказ от ответственности: Это моя первая попытка создания MVVM-приложения. Я также не работал с vue.js раньше, так что вполне возможно, что моя проблема является результатом более фундаментальной проблемы ,Vue JS Просмотр глубоко вложенного объекта


На мой взгляд, у меня есть два типа блоков с флажками:

  • Тип 1: Блок/флажков
  • Тип 2: блок/заголовки/флажков

Базовым объект структурирован следующим образом:

{ 
    "someTopLevelSetting": "someValue", 
    "blocks": [ 
    { 
     "name": "someBlockName", 
     "categryLevel": "false", 
     "variables": [ 
     { 
      "name": "someVarName", 
      "value": "someVarValue", 
      "selected": false, 
      "disabled": false 
     } 
     ] 
    }, 
    { 
     "name": "someOtherBlockName", 
     "categryLevel": "true", 
     "variables": [ 
     { 
      "name": "someVarName", 
      "value": "someVarValue", 
      "categories": [ 
      { 
       "name": "SomeCatName", 
       "value": "someCatValue", 
       "selected": false, 
       "disabled": false 
      } 
      ] 
     } 
     ] 
    } 
    ] 
} 

Мои цели

Выбор флажки:

  1. Пользователь нажимает на флажке, установлен флажок (выбрано = истина)
  2. метод вызывается, чтобы проверить, есть ли другие флажки должны быть отключено (disabled = true). (Если этот метод действительно отключен либо, он также называет себя снова, потому что другие элементы могут быть в свою очередь, зависит от пункта инвалидов)
  3. Другой метод обновляет некоторые другие вещи, как иконки и т.д.

Очистка Флажки

Пользователь может нажать кнопку «Очистить», которая отменяет все флажки в списке (selected = false). Это действие должно также вызывать методы, которые при необходимости выключает флажков и обновляет иконки и т.д.

Мой текущий метод(который, кажется, не совсем верно)

  • Выбранный атрибут Data- модель привязана к проверенному состоянию элемента флажка с помощью v-model.
  • Отключенный атрибут (из модели) связан с классом элемента и отключенным атрибутом. Это состояние задается вышеупомянутым методом.
  • Чтобы инициализировать методы, которые отключают флажки и меняют некоторые значки, я использую директиву v-on="change: checkboxChange(this)". Я думаю, что мне нужно сделать эту часть по-разному метода
  • clearList называется через v-on="click: clearList(this)"

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

То, что я хотел бы вместо
мне наиболее логичным, что нужно сделать было бы использовать this.$watch и отслеживать изменения в модели, а прослушивание событий DOM.

После того, как произойдут изменения, мне нужно будет определить, какой именно предмет был изменен, и действовать по этому поводу. Я попытался создать функцию $watch, которая наблюдает массив blocks. Это, похоже, отлично подходит для изменений, но возвращает полный объект, в отличие от индивидуального атрибута, который изменился. Также этот объект не имеет некоторых удобных вспомогательных атрибутов, таких как $parent.

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

ответ

7

Поскольку никто не ответил, и я решил/работал вокруг проблемы, я подумал, что это полезно для публикации моего решения. Обратите внимание, что я не уверен, что мое решение заключается в том, как эти типы вещей следует решать, но это работает.

Вместо использования этого прослушивателя событий v-on="change: checkboxChange(this)" Теперь я использую настраиваемую директиву, которая прослушивает как выбранный, так и отключенный атрибут модели, например: v-on-filter-change="selected, disabled".

Директива выглядит следующим образом:

directives: { 
    'on-filter-change': function(newVal, oldVal) { 
     // When the input elements are first rendered, the on-filter-change directive is called as well, 
     // but I only want stuff to happen when a user does someting, so I return when there is no valid old value 
     if (typeof oldVal === 'undefined') { 
      return false; 
     } 
     // Do stuff here 
     // this.vm is a handy attribute that contains some vue instance information as well as the current object 
     // this.expression is another useful attribute with which you can assess which event has taken place 
    } 
}, 

Условный пункт кажется немного Hacky, но я не мог найти другой способ. По крайней мере, все это работает.

Возможно, это будет полезно кому-то в будущем.

55

Вы можете использовать метод «часы» .. например, если ваши данные:

data: { 
    block: { 
     checkbox: { 
      active:false 
     }, 
     someotherprop: { 
      changeme: 0 
     } 
    } 
} 

Вы могли бы сделать что-то вроде этого:

data: {...}, 
watch: { 
    'block.checkbox.active': function() { 
     // checkbox active state has changed 
     this.block.someotherprop.changeme = 5; 
    } 
} 
+1

.selected и .disabled - это свойства анонимных переменных объектов, которые относятся к массиву переменных. Ваш пример работает, потому что это всего лишь один объект, а не массив. – Hendrik

+0

Я сделал что-то вроде block.checkbox.active, но это не сработает, пока я не добавлю их в "", как вы упомянули выше. Благодарю. Он работает сейчас. –

5

Если вы хотите посмотреть, как объект вы можете сделать это не следующим образом:

data() { 
    return { 
     object: { 
      prop1: "a", 
      prop2: "b", 
     }  
    } 
}, 
watch: { 
    object: { 
     handler(newVal, oldVal) { 
      // do something with the object 
     }, 
     deep: true, 
    }, 
}, 

уведомление handler и deep: true

+0

Спасибо за это. Однако, поскольку мой вопрос старше двух лет, и с тех пор я не использовал Vue, я не могу проверить, работает ли это. – Hendrik

+1

@ Хендрик не беспокоится, я надеюсь, что это поможет кому-то, кто имеет такую ​​же проблему. – peerbolte

+0

Знаете ли вы, что я должен делать, если я только хочу смотреть 'prop1'? –

2

Другое решение, не упомянутое здесь: Используйте опцию deep.

watch:{ 
    block: { 
    handler: function() {console.log("changed") }, 
    deep: true 
    } 
} 
Смежные вопросы