【Meteor】isolate 和 constant
发布于 11 年前 作者 a272121742 5297 次浏览 最后一次编辑是 8 年前

isolate 和 constant

Metoer除了Handlebars已经提供的widtheachifunless,另外还提供了2个隐藏的全局helper——isolateconstant。经过查询,这些都在Meteor官方包templatingdeftemplate.js文件中,仔细看看还会发现他修改了原版Handlebarseach函数。

讲解准备

构建一个Meteor项目,然后修改默认项目的html文件:

<head>
    <title>isolate和constant</title>
</head>

<body>
<div>
    {{> main}}
</div>
</body>

<template name="main">
    <button onclick="javascript:$('input').val('填补空白')">填补所有空白</button>
    <div>
        {{> A}}
        {{> B}}
        {{> C}}
        {{> D}}
        {{> E}}
        {{> F}}
    </div>
</template>

<template name="A">
    <div style="background:#9cc">
        <input/>Session.get('A') = {{data}}
        {{> A_a}}
        {{> A_b}}
    </div>
</template>
<template name="A_a">
    <div>
        <input/>Session.get('A_a') = {{data}}
        {{> A_a_1}}
    </div>
</template>
<template name="A_b">
    <div>
        <input/>Session.get('A_b') = {{data}}
        {{> A_b_1}}
    </div>
</template>
<template name="A_a_1">
    <div>
        <input/>Session.get('A_a_1') = {{data}}
    </div>
</template>
<template name="A_b_1">
    <div>
        <input/>Session.get('A_b_1') = {{data}}
    </div>
</template>

<template name="B">
    <div style="background:#cc9">
        <input/>Session.get('B') = {{data}}
        {{> B_a}}
        {{> B_b}}
    </div>
</template>
<template name="B_a">
    <div>
        &#123;&#123;#constant&#125;&#125;<br/>{{#constant}}<input/>{{/constant}}Session.get('B_a') = {{data}}<br/>&#123;&#123;/constant&#125;&#125;
        {{> B_a_1}}
    </div>
</template>
<template name="B_b">
    <div>
        <input/>Session.get('B_b') = {{data}}
        {{> B_b_1}}
    </div>
</template>
<template name="B_a_1">
    <div>
        <input/>Session.get('B_a_1') = {{data}}
    </div>
</template>
<template name="B_b_1">
    <div>
        <input/>Session.get('B_b_1') = {{data}}
    </div>
</template>

<template name="C">
    <div style="background:#c9c">
        <input/>Session.get('C') = {{data}}
        {{> C_a}}
        {{> C_b}}
    </div>
</template>
<template name="C_a">
    <div>
        <input/>Session.get('C_a') = &#123;&#123;#isolate&#125;&#125;{{#isolate}}{{data}}{{/isolate}}&#123;&#123;/isolate&#125;&#125;
        {{> C_a_1}}
    </div>
</template>
<template name="C_b">
    <div>
        <input/>Session.get('C_b') = {{data}}
        {{> C_b_1}}
    </div>
</template>
<template name="C_a_1">
    <div>
        {{#isolate}}<input/>{{/isolate}}Session.get('C_a_1') = {{data}}
    </div>
</template>
<template name="C_b_1">
    <div>
        <input/>Session.get('C_b_1') = {{data}}
    </div>
</template>
<template name="D">
    <div>
        <input/>Session.get('D') = {{data}}
    </div>
</template>
<template name="E">
    <div>
        <input/>_.contains(Session.get('list'),'E') = {{hasE}}
    </div>
</template>
<template name="F">
    <div>
        <input/>_.contains(Session.get('list'),'F') = {{hasF}} (isolateValue(fn)包裹)
    </div>
</template>

再来修改js文件:

if (Meteor.isClient) {
    Session.set('A','A');
    Session.set('A_a','A_a');
    Session.set('A_a_1','A_a_1');
    Session.set('A_b','A_b');
    Session.set('A_b_1','A_b_1');
    Session.set('B','B');
    Session.set('B_a','B_a');
    Session.set('B_a_1','B_a_1');
    Session.set('B_b','B_b');
    Session.set('B_b_1','B_b_1');
    Session.set('C','C');
    Session.set('C_a','C_a');
    Session.set('C_a_1','C_a_1');
    Session.set('C_b','C_b');
    Session.set('C_b_1','C_b_1');
    Session.set('D','D');
    Template.A.data = function(){return Session.get('A')};
    Template.A_a.data = function(){return Session.get('A_a')};
    Template.A_a_1.data = function(){return Session.get('A_a_1')};
    Template.A_b.data = function(){return Session.get('A_b')};
    Template.A_b_1.data = function(){return Session.get('A_b_1')};
    Template.B.data = function(){return Session.get('B')};
    Template.B_a.data = function(){return Session.get('B_a')};
    Template.B_a_1.data = function(){return Session.get('B_a_1')};
    Template.B_b.data = function(){return Session.get('B_b')};
    Template.B_b_1.data = function(){return Session.get('B_b_1')};
    Template.C.data = function(){return Session.get('C')};
    Template.C_a.data = function(){return Session.get('C_a')};
    Template.C_a_1.data = function(){return Session.get('C_a_1')};
    Template.C_b.data = function(){return Session.get('C_b')};
    Template.C_b_1.data = function(){return Session.get('C_b_1')};
    Template.D.data = Session.get('D');
    Template.E.hasE = function(){
      return _.contains(Session.get('list'),'E');
    };
    Template.F.hasF = function(){
      return isolateValue(function(){
        return _.contains(Session.get('list'),'F');
      });
    }
}

如果你不介意样式,可以不放下面的。

*{
  font-size: 8px;
}
div{
  border:1px solid #999;
  border-bottom: none;
  border-right: none;
  margin:2px auto 2px 50px;
}

input{
  border:1px solid black;
  height:12px;
  line-height: 12px;
}

最后运行项目。(Session值可以通过控制台手动更改)

注意:填补所有空白就是让所有input标签都填充一个内容。

测试一

动作:

1.填补所有空白 --> Session.set(‘A’,‘任意值’) 2.填补所有空白 --> Session.set(‘A_a’,‘任意值’) 3.尝试修改所有以A开头的其他Session值

结果:

1.Session变化所在的模板A发生重绘,该模板下的所有子模板都发生重绘 2.Session变化所在的模板A_a发生重绘,该模板下的所有子模板发生重绘,但他的父模板没有发生重绘 3.尝试其他的,结果同2

结论:

1.Session发生变化的当前模板发生重绘,写入到信息都被重置 2.重绘只发生在当前和子模板,即向下传递,而不会向上传递

测试二

动作:

1.填补所有空白 --> Session.set(‘B’,‘任意值’) 2.填补所有空白 --> Session.set(‘B_a’,‘任意值’) 3.尝试修改所有以B开头的其他Session值

结果:

1.Session变化所在的模板B发生重绘,唯独被{{#constant}}{{/constant}}所包裹的输入标签没有变化。 2.Session变化所在的模板B_a因为被{{#constant}}{{/constant}}包裹,所以没变化,但其子模板重绘了。 3.结果同测试一结果

结论:

1.重绘对constant包裹的内容无效 2.constant不影响重绘的向下传递

测试三

动作:

1.填补所有空白 --> Session.set(‘C’,‘任意值’) 2.填补所有空白 --> Session.set(‘C’,‘任意值’) 3.尝试修改所有以C开头的其他Session值

结果:

1.Session变化所在的模板C发生重绘,其子模板同样发生重绘 2.Session变化所在的模板C_a,被{{#isolate}}{{/isolate}}包裹的数据发生变化,但模板及其子模板没发生重绘 3.结果同测试一结果

结论:

1.isolate包裹的数据会发生变化 2.isolate除此之外的任何模板都不会发生改变

constant

中文含义很明显,“不变”的意思,主要用在DOM元素保持其可视化不变。如果包裹了helper,数据会变化,但是显示不会变化(大家自行测试)。

isolate

中文含义是“隔离”,能将动态数据与外界隔离。表示数据的变化不会影响外围的任何模板。如果包裹了DOM,不会影响重绘的执行。

测试四

动作:

1.填补所有空白 --> Session.set(‘D’,‘任意值’) 2.填补所有空白 --> Session.set(‘C’,‘C’);(始终设置为他的原始值)

结果:

1.模板D没有重绘 2.模板C没有重绘

结论:

1.helper如果是函数返回,将能保持动态句柄,否则是死数据 2.数据更新为与之前一致是不会刷新模板的

测试五

动作:

  1. 填补所有空白 --> Session.set(‘list’,[‘A’,‘B’,‘C’,‘D’,‘E’]);
  2. 填补所有空白 --> Session.set(‘list’,[‘A’,‘B’,‘C’,‘D’,‘E’,‘F’]);
  3. 填补所有空白 --> Session.set(‘list’,[‘A’,‘B’,‘C’,‘D’,‘F’]);

结果:

1.list中包含E,数据变为true,模板重绘 2.list中仍然包含E,数据保持true,但模板依旧重绘 3.list中不包含E,数据变为false,模板重绘

结论:

1.无论Session如何改变,都会重绘他所在模板

疑问:

如果将测试二、三的结论用在本次测试中,我们可以使得模板不重绘。虽然解决了他一直重绘的情况,但某些时候,我希望在返回true的情况下重绘,这样就无法实现了。下面就要使用Meteor的扩展包isolate了。

测试六

在运行项目前,先引入isolate-value包。

动作:

  1. 填补所有空白 --> Session.set(‘list’,[‘A’,‘B’,‘C’,‘D’,‘E’,‘F’]);
  2. 填补所有空白 --> Session.set(‘list’,[‘A’,‘B’,‘C’,‘D’,‘E’,‘F’,‘G’]);
  3. 填补所有空白 --> Session.set(‘list’,[‘A’,‘B’,‘C’,‘D’,‘G’]);

结果:

1.Session变化,但_.contains(Session.get('list'),'F')返回结果不变时,模板不重绘

结论:

1.isolateValue函数包裹能将Session的变化延迟到返回结果中

isolate-value

这个包只有一个API,就是isolateValue(fn),并且它是全局的。如果是将Session本身的某个值取出来返回(Session作为返回值),他自己会判断是否与上次一致,如果与上次不一致,则重绘Session所在模板。而有时,我们需要经过Session的计算返回结果(Session作为中间值,运算结果作为返回值)。当Session变化时,即使返回值结果保持与之前一致,但仍旧重绘模板,有时这并不是我们需要的,而isolateValue能为我们解决这个问题。

isolateValue还扩展了原equals的不足,使得他能比较对象类型。

1 回复
回到顶部