Angularjs 如何在不使用$scope的情况下在同级组件之间传递数据?

Angularjs 如何在不使用$scope的情况下在同级组件之间传递数据?,angularjs,components,angularjs-controlleras,Angularjs,Components,Angularjs Controlleras,我正在以这种方式制作一个包含3个子组件的组件: <header-component> <side-component> <main-component> 主组件包含英雄列表。 header组件包含两个按钮,用于将主组件上的视图切换为列表视图或网格视图 现在的问题是将数据从header组件传递到main组件。因此,当我单击“网格”按钮时,主要内容上的视图应更改为“网格视图”,行视图也是如此 如何在angular 1.5中的子组件之间传递数据 使用自定义事件

我正在以这种方式制作一个包含3个子组件的组件:

<header-component>
<side-component>
<main-component>

主组件包含英雄列表。 header组件包含两个按钮,用于将主组件上的视图切换为列表视图或网格视图

现在的问题是将数据从header组件传递到main组件。因此,当我单击“网格”按钮时,主要内容上的视图应更改为“网格视图”,行视图也是如此


如何在angular 1.5中的子组件之间传递数据

使用自定义事件来实现这一点。 您可以使用事件分派器
$emit(name,args)在应用程序中传递消息;或$broadcast(名称,args)
您可以使用方法$on(name,listener)侦听此事件

希望能有帮助

参考:

例如: 您可以从标题组件通知如下更改

$rootScope.$emit("menu-changed", "list");
您可以在主组件指令中监听更改,如

$rootScope.$on("menu-changed", function(evt, arg){
  console.log(arg);
});
组件方法 我建议您采用角度2分量法和使用/方法。如果这样做,您将能够轻松地迁移到Angular 2,因为组件在概念上是相同的(只是语法不同)。这就是你做这件事的方法

所以我们基本上希望header和主要组件与header共享一段状态,以便能够更改它。我们可以使用几种方法使其工作,但最简单的方法是使用中间父控制器属性。因此,假设父控制器(或组件)定义了头(可读取和修改)和主(可读取)组件都要使用的
视图
属性

标题组件:输入和输出

下面是简单标题组件的外观:

.component('headerComponent', {
  template: `
    <h3>Header component</h3>
    <a ng-class="{'btn-primary': $ctrl.view === 'list'}" ng-click="$ctrl.setView('list')">List</a>
    <a ng-class="{'btn-primary': $ctrl.view === 'table'}" ng-click="$ctrl.setView('table')">Table</a>
  `,
  controller: function() {
    this.setView = function(view) {
      this.view = view
      this.onViewChange({$event: {view: view}})
    }
  },
  bindings: {
    view: '<',
    onViewChange: '&'
  }
})
主要组件:输入

主组件更简单,它只需要定义它接受的输入:

.component('mainComponent', {
  template: `
    <h4>Main component</h4>
    Main view: {{ $ctrl.view }}
  `,
  bindings: {
    view: '<'
  }
})
.component('mainponent'{
模板:`
主要成分
主视图:{{$ctrl.view}
`,
绑定:{
视图:“尽管父组件方法(通过属性传递数据)是一个完美有效但很好的实现,我们可以使用存储工厂以更简单的方式实现同样的功能。

基本上,数据由
存储
保存,这在两个组件范围内都被引用,当状态发生变化时,可以对UI进行反应式更新

例如:

然后,在您的组件中,您应该有如下内容:

angular
.module('YourApp')
.component('headerComponent'{
//注入存储依赖项
管理员(商店){
//获取存储引用并将其绑定到范围:
//现在,对存储数据所做的每一次更改都将
//自动更新您的组件UI
this.state=Store.get();
//…您的代码
},
模板:`
...
...
...
`
})
.component('main component'{
//这里也一样,我们需要注入商店
管理员(商店){
//“切换视图”按钮的回调
this.switchViewType=(type)=>{
//更改存储数据:
//不需要通知什么的
set({viewType:type});
};
//…您的代码
},
模板:`
切换到电网
切换到世界其他地区
...
`
如果要查看工作示例

这样,您还可以启用2个或N个组件之间的通信。您只需:

  • 注入存储依赖项
  • 确保将存储数据链接到组件范围
  • 就像上面的例子(

    在现实世界中,典型的应用程序需要管理大量数据,因此以某种方式对数据域进行逻辑拆分更有意义。按照相同的方法可以添加更多的存储工厂。例如,管理当前记录的用户信息和外部资源(即目录)您可以构建一个
    UserStore
    加上一个
    CatalogStore
    ——或者
    UserModel
    CatalogModel
    ;这些实体也是集中与后端通信、添加自定义业务逻辑等事务的好地方。
    Store
    将全权负责数据管理>工厂

    请记住,我们正在对存储数据进行变异。虽然这种方法非常简单明了,但可能无法很好地扩展,因为它会产生。如果您想要更高级的东西(不变性、纯函数、单状态树等),请查看,或者如果您最终想要切换到Angular 2,请查看

    希望这有帮助!:)

    你不必按角度2的方式来做,因为以防万一 有时你会迁移…如果你觉得这样做有意义的话就去做


    完全一样。为了明确起见,Subash Selvaraj的建议不是我推荐的。相反,我建议你采用角度2分量法,并使用输入/输出法。如果你这样做,你将能够轻松迁移到ng2。如果你感兴趣,我可以发布答案。否则,你当然可以o自定义事件,但我认为不是这样。我使用的是controllerAs语法和vm变量,所以我不想使用$scope或$rootscope。我很想看看你是如何解决这个问题的。我假设很多开发人员会发现你的答案很有用。所以请这样做。我很想看看子组件如何相互通信实际上,我不想在这个问题上使用$scope或$rootscope。我可以使用controllerAs语法和vm变量使其工作吗?@BesaNeziri如果是这样,您可以使用factory在它们之间共享数据
    .component('mainComponent', {
      template: `
        <h4>Main component</h4>
        Main view: {{ $ctrl.view }}
      `,
      bindings: {
        view: '<'
      }
    })
    
    <header-component view="root.view" on-view-change="root.view = $event.view"></header-component>
    <main-component view="root.view"></main-component>
    
    angular
        .module('YourApp')
        // declare the "Store" or whatever name that make sense
        // for you to call it (Model, State, etc.)
        .factory('Store', () => {
            // hold a local copy of the state, setting its defaults
            const state = {
                data: {
                  heroes: [],
                  viewType: 'grid'
                }
            };
            // expose basic getter and setter methods
            return {
                get() {
                    return state.data;
                },
                set(data) {
                    Object.assign(state.data, data);
                },
            };
        });
    
    angular
        .module('YourApp')
        .component('headerComponent', {
            // inject the Store dependency
            controller(Store) {
                // get the store reference and bind it to the scope:
                // now, every change made to the store data will
                // automatically update your component UI
                this.state = Store.get();
    
                // ... your code
            },
            template: `
                <div ng-show="$ctrl.state.viewType === 'grid'">...</div>
                <div ng-show="$ctrl.state.viewType === 'row'">...</div>
                ...
            `
        })
        .component('mainComponent', {
            // same here, we need to inject the Store
            controller(Store) {
                // callback for the switch view button
                this.switchViewType = (type) => {
                    // change the Store data:
                    // no need to notify or anything
                    Store.set({ viewType: type });
                };
    
                // ... your code
            },
            template: `
                <button ng-click="$ctrl.switchViewType('grid')">Switch to grid</button>
                <button ng-click="$ctrl.switchViewType('row')">Switch to row</button>
                ...
            `