流星大火 - 反应式的单个状态助手
#javascript #编程 #meteorjs #blaze

今天,我优化了一些较旧的大火模板。我发现每个简单的状态访问都使用助手。一个非常不便和不必要的问题导致肿胀且合理的代码较少。

请看以下示例:

<template name="welcome">
  {{#if loadComplete}}
    <h1>Welcome, {{name}}</h1>
    <p>Today's date is {{date}}</p>
  {{else}}
     ...loading
  {{/if}}
</template>
import { ReactiveDict } from 'meteor/reactive-dict'

Template.welcome.onCreated(function () {
  const instance = this
  instance.state = new ReactiveDict()
  instance.state.set('date', new Date().toLocaleString())

  instance.autorun(() => {
    const user = Meteor.user()
    if (user) {
      instance.state.set({
        name: `${user.firstName} ${user.lastName}`,
        loadComplete: true
      })
    }
  })
})

此模板将需要三个助手才能从HTML部分渲染给定的逻辑:

Teplate.welcome.helpers({
  loadComplete () {
    return Template.instance().state.get('loadComplete')
  },
  name () {
    return Template.instance().state.get('name')
  },
  date () {
    return Template.instance().state.get('date')
  }
})

为什么这是个问题?

上面的代码在许多层面上都有问题。首先,它根本没有扩展。考虑一个不需要三个而不是10个以上变量的模板。

这将需要10个助手才能简单地访问。多么肿的代码!结果是更高的维护工作,重构工作(考虑重命名事物)以及对错误的倾向。

它也会尖叫以进行抽象,因为您看到每个助手的模式都有相同的模式。

幸运的是,我们可以将其合并到一个助手中,我想演示两种不同的方法:

接近A-将作为参数访问的国家变量的名称传递给帮手

Teplate.welcome.helpers({
  state (name) {
    return Template.instance().state.get(name)
  }
})

这种方法很简单,易于实现。辅助助手的名字以引号为state的参数。

<template name="welcome">
  {{#if state "loadComplete"}}
    <h1>Welcome, {{state "name"}}</h1>
    <p>Today's date is {{state "date"}}</p>
  {{else}}
     ...loading
  {{/if}}
</template>

这种方法的一个缺点是可读性降低,并且需要嵌套功能调用,以防您要将访问的状态传递给HTML部件的另一个助手。

方法b-将代理返回州,以访问属性名称的状态变量

这种方法创建了一个对state的新代理,该代理将.get(name)调用包装在Get-trap中:

import { ReactiveDict } from 'meteor/reactive-dict'

Template.welcome.onCreated(function () {
  const instance = this
  instance.state = new ReactiveDict()
  instance.state.set('date', new Date().toLocaleString())

  instance.autorun(() => {
    //...
  })

  instance.stateProxy = new Proxy( {}, {
    get: function (target, p, receiver) {
      return instance.state.get(p)
    }
  })
})

Teplate.welcome.helpers({
  state (name) {
    return Template.instance().stateProxy
  }
})

在这里,您可以通过点表示法访问变量,Wich看起来可读和直观:

<template name="welcome">
  {{#if state.loadComplete}}
    <h1>Welcome, {{state.name}}</h1>
    <p>Today's date is {{state.date}}</p>
  {{else}}
     ...loading
  {{/if}}
</template>

这种方法的潜在缺点是,您需要对代理的基本理解,以实施更复杂的案例。此外,点符号可以欺骗您(或其他人)思考,您正在处理一个普通的对象而不是状态对象。

概括

这篇小文章展示了两种方法来扩展模板或减少现有模板中的膨胀。选择哪一个取决于您和您的团队。

两种方法都允许进一步的抽象,例如默认情况下将statestate ()助手嵌入到每个模板中。我将在下一篇文章中证明这种方法作为后续。


关于我

我在Dev.to上定期发布文章,大约 Meteor javascript

您还可以在GitHubTwitterLinkedIn上找到(并与我联系)。

如果您喜欢阅读的内容并想支持我,则可以sponsor me on GitHubsend me a tip via PayPal

通过访问their blog*来跟上流星的最新发展,如果您像我一样进入流星并想向世界展示,则应查看Meteor merch store*