Lien original : Créer un grand arbre
Dans un projet auquel j'ai participé récemment, le framework vue.js a été utilisé dans le front-end . Pendant cette période, il y a eu un La fonction nécessite dynamiquement l'ajout de propriétés à un objet lié. Mais dans les applications pratiques, un problème se pose : après l'ajout d'attributs à l'objet, le contenu du composant lié à l'objet ne change pas. Le composant doit être à nouveau actualisé avant que son contenu ne change au contenu modifié.
Au début, je pensais que l'attribut n'avait pas été ajouté avec succès, car à mon avis v-model
est lié dans les deux sens et ne sera pas dans un état non mis à jour. Après avoir vérifié la surveillance dans Devtools, j'ai constaté que les attributs spécifiés étaient ajoutés à l'objet correspondant.
Alors, je suis allé consulter la documentation officielle et j'ai trouvé l'explication officielle : Comment Vue.js suit les modifications
Lorsque vous transmettez un objet JavaScript normal dans une instance Vue en tant qu'option
data
, Vue parcourra toutes les propriétés de cet objet et utiliseraObject.defineProperty
pour convertir toutes ces propriétés en getter/setter.Object.defineProperty
est une fonctionnalité d'ES5 qui ne peut pas être supprimée, c'est pourquoi Vue ne prend pas en charge les navigateurs IE8 et inférieurs.Chaque instance de composant correspond à une instance watcher, qui enregistre les propriétés des données "touchées" en tant que dépendances pendant le processus de rendu du composant. Plus tard, lorsque le setter de la dépendance est déclenché, l'observateur sera averti, provoquant un nouveau rendu de son composant associé.
Notes sur la détection des changements
En raison des limitations de JavaScript, Vue ne peut pas détecter les modifications apportées aux tableaux et objets. Il existe néanmoins des moyens de contourner ces limitations et de les maintenir réactifs.
Vue ne peut pas détecter l'ajout ou la suppression d'une propriété . Étant donné que Vue effectuera une conversion getter/setter sur la propriété lors de l'initialisation de l'instance, la propriété doit exister sur l'objet data
pour que Vue la convertisse en réactif. Par exemple :
<span style="display: block; background: url(https://imgkr.cn-bj.ufileos.com/97e4eed2-a992-4976-acf0-ccb6fb34d308.png); height: 30px; width: 100%; background-size: 40px; background-repeat: no-repeat; background-color: #1E1E1E; margin-bottom: -7px; border-radius: 5px; background-position: 10px 10px;"></span><code class="hljs" style="overflow-x: auto; padding: 16px; color: #DCDCDC; display: -webkit-box; font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; font-size: 12px; -webkit-overflow-scrolling: touch; padding-top: 15px; background: #1E1E1E; border-radius: 5px;">var vm = new Vue({<br/> data:{<br/> a:1<br/> }<br/>})<br/><br/>// `vm.a` 是响应式的<br/><br/>vm.b = 2<br/>// `vm.b` 是非响应式的<br/></code>
Vue ne permet pas d'ajouter dynamiquement des propriétés réactives au niveau racine aux instances déjà créées. Cependant, vous pouvez ajouter des propriétés réactives aux objets imbriqués à l'aide de la méthode Vue.set(object, propertyName, value)
. Par exemple, pour :
<span style="display: block; background: url(https://imgkr.cn-bj.ufileos.com/97e4eed2-a992-4976-acf0-ccb6fb34d308.png); height: 30px; width: 100%; background-size: 40px; background-repeat: no-repeat; background-color: #1E1E1E; margin-bottom: -7px; border-radius: 5px; background-position: 10px 10px;"></span><code class="hljs" style="overflow-x: auto; padding: 16px; color: #DCDCDC; display: -webkit-box; font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; font-size: 12px; -webkit-overflow-scrolling: touch; padding-top: 15px; background: #1E1E1E; border-radius: 5px;">Vue.set(vm.someObject, <span class="hljs-string" style="color: #D69D85; line-height: 26px;">'b'</span>, 2)<br/></code>
Vous pouvez également utiliser la méthode d'instance vm.$set
, qui est également un alias pour la méthode globale Vue.set
:
<span style="display: block; background: url(https://imgkr.cn-bj.ufileos.com/97e4eed2-a992-4976-acf0-ccb6fb34d308.png); height: 30px; width: 100%; background-size: 40px; background-repeat: no-repeat; background-color: #1E1E1E; margin-bottom: -7px; border-radius: 5px; background-position: 10px 10px;"></span><code class="hljs" style="overflow-x: auto; padding: 16px; color: #DCDCDC; display: -webkit-box; font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; font-size: 12px; -webkit-overflow-scrolling: touch; padding-top: 15px; background: #1E1E1E; border-radius: 5px;">this.<span class="hljs-variable" style="color: #BD63C5; line-height: 26px;">$set</span>(this.someObject,<span class="hljs-string" style="color: #D69D85; line-height: 26px;">'b'</span>,2)<br/></code>
Parfois, vous devrez peut-être attribuer plusieurs de nouvelles valeurs à une propriété d'objet existante, par exemple en utilisant Object.assign()
ou _.extend()
. Cependant, les nouvelles propriétés ajoutées à l'objet de cette manière ne déclencheront pas de mise à jour. Dans ce cas, vous devez créer un nouvel objet avec les propriétés de l'objet d'origine et de l'objet que vous souhaitez mélanger.
<span style="display: block; background: url(https://imgkr.cn-bj.ufileos.com/97e4eed2-a992-4976-acf0-ccb6fb34d308.png); height: 30px; width: 100%; background-size: 40px; background-repeat: no-repeat; background-color: #1E1E1E; margin-bottom: -7px; border-radius: 5px; background-position: 10px 10px;"></span><code class="hljs" style="overflow-x: auto; padding: 16px; color: #DCDCDC; display: -webkit-box; font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; font-size: 12px; -webkit-overflow-scrolling: touch; padding-top: 15px; background: #1E1E1E; border-radius: 5px;">// 代替 `Object.assign(this.someObject, { a: 1, b: 2 })`<br/>this.someObject = Object.assign({}, this.someObject, { a: 1, b: 2 })<br/></code>
Il s'agit d'une solution d'affectation d'objets. Après avoir adopté la solution officielle this.$set(object, key, value)
, l'effet de mise à jour en temps réel est effectivement obtenu. Parallèlement, pour les tableaux et autres situations, vous pouvez consulter les documents officiels restants
Comme l'a dit le responsable "En raison des limitations de JavaScript, Vue ne peut pas détecter les changements dans les tableaux et objets , mais pourquoi." ? Que va-t-il se passer ?
借用 Segmentfault UKer 的回答:
ECMAScript中有两种属性:数据属性 和 访问器属性; 数据属性的描述符为:Configurable,Enumerable,Writable,Value; 访问器属性的描述符为:Configurable, Enumerable,set,get。
当我们使用new Vue(obj)
,其内部发生了大体如下代码的转换,即,将数据属性转换为了访问器属性
<span style="display: block; background: url(https://imgkr.cn-bj.ufileos.com/97e4eed2-a992-4976-acf0-ccb6fb34d308.png); height: 30px; width: 100%; background-size: 40px; background-repeat: no-repeat; background-color: #1E1E1E; margin-bottom: -7px; border-radius: 5px; background-position: 10px 10px;"></span><code class="hljs" style="overflow-x: auto; padding: 16px; color: #DCDCDC; display: -webkit-box; font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; font-size: 12px; -webkit-overflow-scrolling: touch; padding-top: 15px; background: #1E1E1E; border-radius: 5px;"><span class="hljs-keyword" style="color: #569CD6; line-height: 26px;">function</span> Vue(obj){<br/> obj.data.keys().forEach((prop, index) => {<br/> Object.defineProperty(obj.data, prop, {<br/> <span class="hljs-function" style="color: #DCDCDC; line-height: 26px;"><span class="hljs-title" style="color: #DCDCDC; line-height: 26px;">set</span></span>(){<br/> //可以在此处进行事件监听<br/> },<br/> <span class="hljs-function" style="color: #DCDCDC; line-height: 26px;"><span class="hljs-title" style="color: #DCDCDC; line-height: 26px;">get</span></span>(){<br/> <br/> }<br/> })<br/> })<br/> <span class="hljs-built_in" style="color: #4EC9B0; line-height: 26px;">return</span> obj;<br/> }<br/></code>
但是当我们后面再次使用普通的赋值,仅仅是赋值了一个数据属性的,这个属性是不会具有访问器属性的事件监听功能的。
至此,v-model
绑定数据不实时更新的问题方才得到了解决。
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!