angularjs前端框架_智能前端和哑后端:AngularJS中的持久状态

angularjs前端框架

状态是您与网站互动时由您生成的某种事物,例如,通过单击按钮或在文本字段中键入一些文本。 此状态位于浏览器的RAM中,由JavaScript对象(例如数组,字符串和对象)组成。

在本文中,我们将探讨采用这些数组和对象并将其持久化的模式。 为此,我们需要一些聪明的方法来将临时的“垃圾”与我们不能丢失的重要内容分开。

入门

假设我们有一个对象数组,每个对象中都有“临时”键。 在将对象数组发送到持久性存储( localStorage或Ajax)中时,我们不希望这些键具有持久性。

在示例中,我将向您展示,我们将使用AngularJS应用程序。 在其中,我们将不需要持久化的东西放到每个对象中。 对于保持持久性不重要的所有内容都以下划线开头。

这是我们开始HTML代码:

<div ng-repeat="thing in things track by thing.id"
     ng-click="thing._expanded=!thing._expanded">
    <div ng-if="thing._expanded">
        EXPANDED VIEW
    </div>
    <div ng-if="!thing._expanded">
        collapsed view
    </div>
</div>

这是为它提供动力的小型JavaScript代码:

angular
  .module('app', [])
  .controller('Ctrl', ($scope) => {
    $scope.things = [
      {id: 1, key: 'Value'},
      {id: 2, key: 'Value2'},
      {id: 3, key: 'Value3'},
    ]
  });

如果您想现场观看此示例, 请观看此演示

请参阅CodePen上的SitePoint( @SitePoint )提供的Pen XXNdab

很可爱吧? 真的很实用。

关于持久存储的思考

现在假设我们要保留$scope.things 。 关闭选项卡后,可能是我们想返回的待办事项列表。 当我们回来时,很多这些浅表属性(例如_expanded_dateAsString )都是我们不想在持久性存储中混乱的东西。 我们之所以这样做,是因为它们可以很容易地重新生成或重置,而又不会失去有价值的东西。 也许我们担心内存,其中一些临时状态项很重。

假设我们要将其保留在localStorage 。 我们需要做的如下所示:

localStorage.setItem('mystuff', JSON.stringify($scope.things));

但是,这将在我们不想记住的对象中保存很多其他内容(再次,因为它们可以重新生成,或者因为它们根本不值得保存)。

因此,我们需要做的第一件事就是克隆它们。 要克隆数组,您必须编写这样JavaScript代码(我在这里使用ECMAScript6 ):

let copy = Array.from(myArray)

但是,如果数组是一个充满对象(即字典)的数组,那么我们必须做更多的魔术:

let copy = Array.from(
  myArray,
  (item) => Object.assign({}, item)
);

这样,我们得到了一个深层的副本

这是我们修改该副本的机会,以便为持久保存做好准备。 事不宜迟,下面是执行此操作的代码:

let copy = Array.from(myArray, (item) => {
  let obj = Object.assign({}, item)
  for (let key of Object.keys(obj)) {
    if (key.startsWith('_') || key === '$$hashKey') {
      delete obj[key]
    }
  }
  return obj
});

如果您想现场观看此示例, 请观看此演示

$$hashKey东西是什么?

AngularJS将一个名为$$hashKey的键放入正在渲染的每个对象中(如果它认为需$$hashKey )。 这样,它可以在内部知道发生了什么变化以及没有发生什么变化。 AngularJS中有一个内置实用程序,我们可以用来剥离它们:

angular.toJson(myObject);

免费学习PHP!

全面介绍PHP和MySQL,从而实现服务器端编程的飞跃。

原价$ 11.95 您的完全免费

您可以在此处找到有关它的文档

如果我们像ng-repeat="thing in things" Things ng-repeat="thing in things"这样重复,AngularJS将把这些键放入。但是要避免这种情况,我们可以使用跟踪键,例如:

ng-repeat="thing in things track by thing.id"

它不会被放入。

无论哪种方式,由于我们可能正在构建可用于各种AngularJS构造的实用工具,因此剥离那些$$hashKey东西可能是一个很好的主意。

把它放在一起

我们的第一个演示应用程序相当愚蠢,因为您永远不会将任何东西“输入”到状态中,因此保存它毫无意义。 首先,让我们更改演示应用程序,以便它实际获取值得保存的输入。 该应用程序将成为“周日志”,您可以在其中键入一周中每天的工作。

让我们先构建它,以使骨骼起作用。 以下是我们需要HTML代码:

<div ng-app="app">
  <div ng-controller="Ctrl">
    
    <div ng-repeat="week in weeks track by week.date">
      <h3 ng-click="week._expanded=!week._expanded">
        Week of {{ week._date | date: 'EEEE MMM d' }} - {{ week._end | date: 'EEEE d, yyyy' }}
        <span ng-if="week._expanded">(click to close)</span>
        <span ng-if="!week._expanded">(click to edit)</span>
      </h3>
      <div ng-if="week._expanded" class="expanded">
        <table>
          <tr ng-repeat="day in week._days">
            <td>{{ day.name }}</td>
            <td><input type="text" ng-model="day.text" ng-blur="saveWeeks()"></td>
          </tr>
        </table>
      </div>
    <div ng-if="!week._expanded" class="collapsed">
      <table>
        <tr ng-repeat="day in week._days">
          <td><b>{{ day.name }}</b></td>
          <td>{{ day.text }}</td>
        </tr>
      </table>
    </div>
    </div>
    <hr>
    <p>
      Click to edit the week entries. After reloading the page you
      get back what you typed last.
    </p>
    <p>
      A useful extension of this would be to be able to add new weeks. And make it infinitely prettier. 
    </p>
  </div>
</div>

这是JavaScript代码:

angular.module('app', [])
.controller('Ctrl', ($scope) => {
  const weekdays = [
    [0, 'Monday'],
    [1, 'Tuesday'],
    [2, 'Wednesday'],
    [3, 'Thursday'],
    [4, 'Friday'],
    [5, 'Saturday'],
    [6, 'Sunday'],
  ]
  let dressUp = (weeks) => {
    // add internally needed things
    weeks.forEach((week) => {
      week._date = Date.create(week.date)
      week._end = week._date.clone()
      week._end.addDays(6)
      week._days = [];
      weekdays.forEach((pair) => {
        week._days.push({
          index: pair[0],
          name: pair[1],
          text: week.days[pair[0]] || ''
        })
      })
    })
  }
  
  let dressDown = (weeks) => {
    // week.days is an object, turn it into an array
    weeks.forEach((week) => {
      week._days.forEach((day) => {
        week.days[day.index] = day.text || ''
      })
    })
  }
  
  // try to retrieve from persistent storage
  $scope.weeks = JSON.parse(
    localStorage.getItem('weeks') || '{"weeks":[]}'
  ).weeks
  if (!$scope.weeks.length) {
    // add a first default
    let monday = Date.create().beginningOfISOWeek().format('{yyyy}-{MM}-{dd}')
    $scope.weeks.push({date: monday, days: {}})
  }
  
  // when retrieved it doesn't have the internal 
  // stuff we need for rendering, so dress it up
  dressUp($scope.weeks)
  
  $scope.saveWeeks = () => {
    // copy from _days to days
    dressDown($scope.weeks)
    // make a deep copy clone
    let copy = Array.from($scope.weeks, (item) => {
      let obj = Object.assign({}, item)
      for (let key of Object.keys(obj)) {
        if (key.startsWith('_') || key === '$$hashKey') {
          delete obj[key]
        }
      }
      return obj
    })
    // actually save it persistently
    localStorage.setItem('weeks', JSON.stringify({weeks: copy}))
  }
});

这里显示了现场演示

请参阅CodePenSitePoint@SitePoint )的笔每周日志

那里发生了很多事。

该演示应用程序使用localStorage来保持持久性。 加载应用程序后,它会检索过去保存的内容,如果那里没有任何内容,它将创建第一个示例。 然后,它将显示星期,您可以编辑条目。 一旦您模糊了任何输入字段,它就会开始保存过程。 首先,它修改了状态(从列表week._days复制到对象week.days ),其次,它创建了一个深层副本克隆,当这样做时,它将删除我们认为不需要保留的所有键。 最后,它将其存储在localStorage

尝试打开演示应用程序,输入内容,在输入字段中模糊显示,然后刷新整个页面,您应该会看到输入的数据仍然在那里。

毅力与超越

有人可能会嘲笑浏览器中的localStorage是持久性的概念。 它仅存储在您的设备中,如果您丢失了设备或完全擦除了个人资料,则表明存储空间已消失。 更加持久的解决方案是在云中建立适当的数据库。 一个备份和复制的东西,没什么。 但是,这超出了本文的范围,并且扩展此操作非常简单。 因为我们将JSON存储在localStorage ,这意味着Ajax仅发送我们要保存的内容将变得非常容易,而您不必担心列或类型。

显然,如果您沿Ajax路线走,那么在输入字段更改中保存所有重大信息可能会过多。 但是,由于每个ng-blur知道您编辑了星期几和星期几,因此Ajax可以只发送该特定日期的更改。 读者,请多多练习。

结论

这是现实的吗? 是的! 可以缩放吗? 是的,它确实。

我们正在进入一个时代,前端变得越来越智能,后端变得越来越笨拙。 这意味着您将很多业务逻辑放在前端代码中,并要求后端仅执行真正的基本任务(例如“仅存储此blob!”)。 如果您要构建那些花哨的离线优先应用程序之一,则需要开始考虑将所有状态保留在Web应用程序中,并且不能依赖于服务器始终可用。 最终必须如此。

现在,您需要将后端视为同步服务器。 这并不意味着你必须发送一切来回,但你想要做的是在前端后端都和复杂的业务逻辑的最后一件事情的整个斑点,如果你想脱机先应用体验,您必须向前端倾斜以了解发生魔术的地方。

另外,将业务逻辑放入前端并将后端视为“哑巴”,这意味着您可以对后端技术变得更加不可知。 这些后端技术正忙于提供,备份和快速。 上面提到的演示应用程序使用localStorage但是很容易用KintoPouchDBFirebase替换。 这些都是非常可扩展的平台。 因此,这种模式确实可以扩展。

翻译自: https://www.sitepoint.com/persisting-state-in-angularjs/

angularjs前端框架

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值