Disclaimer: Ceci est ma première tentative de création d'une application MVVM pour laquelle je n'ai pas encore travaillé avec vue.js. Il se peut donc que mon problème soit le résultat d'un problème plus fondamental.
À mon avis, j'ai deux types de blocs avec des cases à cocher:
L'objet sous-jacent est structuré comme ceci:
{
"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
}
]
}
]
}
]
}
Mes objectifs
Sélection des cases à cocher:
Décochez les cases
Un utilisateur peut cliquer sur un bouton "effacer" qui désactive toutes les cases à cocher d'une liste (sélectionné = faux). Cette action doit également déclencher les méthodes qui désactivent éventuellement les cases à cocher et met à jour les icônes, etc.
Ma méthode actuelle (ce qui ne semble pas tout à fait correct)
v-model
.v-on="change: checkboxChange(this)"
. Je pense que je dois faire cette partie différemment v-on="click: clearList(this)"
Le problème avec ma configuration actuelle est que l’événement change ne se déclenche pas lorsque les cases à cocher sont effacées par programme (c’est-à-dire non par interaction de l’utilisateur).
Ce que je voudrais plutôt
Pour moi, la chose la plus logique à faire serait d'utiliser this.$watch
Et de suivre les modifications apportées au modèle, au lieu d'écouter les événements DOM.
Une fois qu'il y a un changement, je devrais alors identifier quel élément exact a changé et agir en conséquence. J'ai essayé de créer une fonction $watch
Qui observe le tableau blocks
. Cela semble bien comprendre les modifications, mais il renvoie l'objet complet, par opposition à l'attribut individuel qui a changé. De plus, il manque à cet objet des attributs d'aide utiles, tels que $parent
.
Je peux penser à quelques moyens astucieux de faire fonctionner l'application (par exemple, déclencher manuellement des événements de changement dans ma méthode clearList, etc.), mais mon cas d'utilisation semble plutôt standard. Je m'attends donc à ce qu'il existe un moyen beaucoup plus élégant de gérer cela.
Vous pouvez utiliser la méthode 'watch'. Par exemple, si vos données sont:
data: {
block: {
checkbox: {
active:false
},
someotherprop: {
changeme: 0
}
}
}
Vous pouvez faire quelque chose comme ça:
data: {...},
watch: {
'block.checkbox.active': function() {
// checkbox active state has changed
this.block.someotherprop.changeme = 5;
}
}
Si vous voulez regarder l'objet dans son ensemble avec toutes ses propriétés, et pas seulement une propriété, vous pouvez le faire à la place:
data() {
return {
object: {
prop1: "a",
prop2: "b",
}
}
},
watch: {
object: {
handler(newVal, oldVal) {
// do something with the object
},
deep: true,
},
},
notez handler
et deep: true
Étant donné que personne n’a répondu et que j’ai résolu le problème, j’ai pensé qu’il serait peut-être utile d’afficher ma solution. Veuillez noter que je ne suis pas sûr que ma solution est de savoir comment résoudre ce type de problème, cela fonctionne cependant.
Au lieu d'utiliser cet écouteur d'événement v-on="change: checkboxChange(this)"
, j'utilise maintenant une directive personnalisée qui écoute à la fois les attributs de modèle sélectionnés et désactivés, comme ceci: v-on-filter-change="selected, disabled"
.
La directive ressemble à ceci:
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
}
},
La clause if semble un peu compliquée, mais je ne pouvais pas trouver un autre moyen. Au moins tout fonctionne.
Cela sera peut-être utile à quelqu'un dans le futur.
Autre solution non mentionnée ici: Utilisez l’option deep
.
watch:{
block: {
handler: function () {console.log("changed") },
deep: true
}
}