使用ui-router更改状态时如何保留范围数据? [英] How to preserve scope data when changing states with ui-router?

查看:80
本文介绍了使用ui-router更改状态时如何保留范围数据?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用AngularJS和ui-router构建一个单页Web应用程序.我有两个不同的州,一个父母和一个孩子.在父状态"spots"中,用户可以从ng-repeat中进行选择,并使用范围显示其选择.

I'm building a single page web app using AngularJS with ui-router. I have two different states, one parent and one child. In the parent state, 'spots', users can make a selection from an ng-repeat and their selection is shown using the scope.

当用户进行选择时,我用ng键单击fire一个使用$ state.go加载子状态明细"的函数.我想在子状态下加载它们的选择,但是范围数据似乎消失了?

When a user makes the selection, I have ng-click fire a function which uses $state.go to load the child state 'details'. I would like to load their selection in the child state, but it appears that the scope data is gone?

我尝试为每个状态使用相同的控制器. ui-sref也不起作用.

I've tried using the same controller for each state. ui-sref doesn't work either.

来自父州HTML模板

<div class="card-column mx-0" data-ng-click="makeSelection = true">

 <div class="card mx-0 mb-3 ng-scope" data-ng-click="showSpot(spot);" data-ng-repeat="spot in spots | filter:{'game':gameID} | filter:{'walking':distanceID} | filter:{'vehicle':vehicleID} | orderBy:'price' | filter as results">
   <div class="row no-gutters">

    <div class="col-sm-12 col-md-3 col-lg-3">
      <img src="{{ spot.image }}" alt="parking spot"/>
    </div>

    <div class="col-sm-12 col-md-9 col-lg-9">
      <div class="card-body px-4 pt-4">

        <h6 class="text-small-extra text-muted font-weight-normal text-uppercase"><span style="letter-spacing: .05rem;">{{ spot.type }}</span></h6>

        <h5 class="card-title">{{ spot.address }}</h5>

        <h4 class="text-muted float-md-right">${{ spot.price }}<span style="font-size: 1rem; font-weight: 400">/day</span></h4>

      </div>

    </div>

  </div>

</div>

控制器的摘录

$scope.showDetails = function() {
  $state.go('spots.details'); //my route...
}

$scope.showSpot = function(spot) {
  $scope.spot = spot;
  $scope.showDetails();
}

来自app.js的代码段

Snippet from app.js

.config(function($stateProvider, $urlRouterProvider) {

$urlRouterProvider.otherwise("/")

$stateProvider
.state('spots',{
  url: '/',
  templateUrl: "/parkit/master/spots-available.html",
  controller: 'parkitController'
})
.state('details', {
  parent: 'spots',
  url: '/details',
  templateUrl: '/parkit/master/details.html',
})
.state('statetwo', {
  url: '/statetwo',
  template: '<h1>State Two</h1>',
  controller: 'parkitController'
});

})

我希望用户选择会在触发ng-click之后显示在子状态上.

I expected the user selection to show on the child state after ng-click is fired.

推荐答案

您需要了解原型继承的工作方式.当父母使用

You need to under stand how prototypal inheritance works. When a parent puts a property value on the scope with

$scope.value = 'something';

在子组件中,如果您访问$ scope.value,则继承链将找到$ scope.value.

In a child component if you access $scope.value the inheritance chain will find $scope.value.

如果孩子设置了

$scope.otherValue = 'something';

如果遵循继承链,则不会找到otherValue的值并在子作用域上创建属性,而不是在继承的原型上创建属性,因此父组件和父级的任何其他子项都看不到它.

If follows the inheritance chain, doesn't find a value of otherValue and creates a property on the child scope, not the inherited prototype so the parent component and any other children of the parent do not see it.

您可以使用所谓的原型继承的点规则.如果父级在作用域上创建了一个称为数据的对象

You can use what is called the dot rule of prototypal inheritance. If the parent creates an object on the scope called something like data

$scope.data = { value: 'something' };

现在,如果孩子将一个属性放在数据对象上

Now if the child puts a property on the data object

$scope.data.otherValue = 'something';

它会查找数据对象,并在继承链中找到它,并且因为您正在向对象的实例添加属性,因此它对父级和父级的任何子级都是可见的.

It looks for the data object, finds it in the inheritence chain and because you are adding a property to an instance of an object it is visible to the parent and any children of the parent.

let parent = {
  value: 'some value',
  data: { value: 'some value' }
};

let child = Object.create(parent);

console.log(child.value); // Finds value on the prototype chain

child.newValue = 'new value'; // Does not affect the parent

console.log(parent.newValue);

child.data.newValue = 'new value'; // newValue is visible to the parent

console.log(parent.data.newValue);

简短的答案是永远不要注入$ scope并使用controllerAs语法.

Short answer is to just never inject $scope and use controllerAs syntax.

要在控制器之间共享数据,请使用注入到两个控制器中的服务.您在服务上具有了Spots集合,并使用路由参数来确定另一个控制器应使用哪个地点,或在另一个控制器上设置的名为currentSpot的服务上具有位置.

To share data between controllers you use a service that is injected to both controllers. You have the spots collection on the service and use a route param to identify which spot the other controller should use or have a place on the service called currentSpot set by the other controller.

服务是您在模块级别创建的单例对象,然后在其依赖项列表中要求它们的所有控制器都将获得相同的实例.它们是在控制器之间共享数据的首选方式,$ scope层次结构势必会引起混乱,因为它们的原型继承性质可能会造成混淆.子级$ scope原型是从其父级继承而来的,似乎您应该共享数据,但是当子级控制器设置属性时,父级不可见.

Services are a singleton object that you create at the module level and then all controllers that ask for them in their dependency list get the same instance. They are the preferred way to share data between controllers, $scope hierarchies are bound to lead to confusion as the prototypal inheritance nature of them can be confusing. A child $scope is prototypally inherited from it's parent, this seems like you should be sharing data but when a child controller sets a property it is not visible to the parent.

您正在学习一种过时的Angular编程方式.不再推荐使用$ scope注入.查看使用组件.组件是具有隔离范围并使用contollerAs语法的控制器的包装.孤立的作用域使人们更清楚地知道数据的来源.

You are learning an outdated way of Angular programming. Injecting $scope is no longer a recommended way. Look at using components. Components are a wrapper for a controller with an isolated scope and using contollerAs syntax. Isolated scopes make it much cleaner to know where data comes from.

看看我对这个问题的回答

Take a look at my answer on this question

尝试从位于另一个控制器中的一个控制器激活一个复选框

这篇关于使用ui-router更改状态时如何保留范围数据?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆