【问题标题】:ngFor and click eventsngFor 和点击事件
【发布时间】:2020-12-11 12:49:38
【问题描述】:

我是第一次从 React 转向 Angular,并试图适应它。如何仅为我想要的项目而不是 JSON 列表中的每个项目执行单独的单击事件?

Logout() 服务有效。如果我不这样做;使用 ngFor 并将 click 事件直接传递给它应该做的事情的模板。但不是当我从 ngFor 中的 JSON 传递它时。我想我总是可以回到另一条路,但现在我很好奇。有趣的是,我添加了一个 alert() 并且事件正在触发,而不是注销功能中的 AuthService...

模板

<a
   *ngFor="let usermenuitem of usermenu; let i = index"
   [routerLink]="usermenuitem.link"
   (click)="usermenuitem.goto()">
   {{usermenuitem.title}}
</a>

组件

export class AuthorisedTopNavComponent implements OnInit {

  usermenu:Object[] = [
    {
      title: 'Account',
      link: '/account',
      icon:"ua-home.svg",
      goto: ()=>{},
    },
    {
      title: 'Membership',
      link: '/membership',
      icon:"ua-home.svg",
      goto: ()=>{},
    },
    {
      title: 'Logout',
      link: '/',
      icon:"ua-home.svg",
      goto: this.logoff,
    },
  ]

  constructor (
    public authService: AuthService
  ) {}  

  ngOnInit() {}


  logoff() {
    this.authService.logout('/');
  }

}

【问题讨论】:

  • 你试过 ()=> this.logoff() 吗?
  • 我怀疑 this 没有绑定到正确的上下文。
  • 试试this.logoff.bind(this)
  • @OwenKelvin BOOYAA !!!做得很好!如果你想要信用,请在此获得一个更简单的答案。谢谢
  • 在同一个标​​签中使用 [routerLink] 和 (click) 很奇怪。我认为使用goto:()=&gt;this.logoff() 可以工作,但我不确定

标签: javascript angular


【解决方案1】:

问题分析

代码步骤和功能按照您的解释工作

Logout() 服务有效。如果我不这样做;使用 ngFor...

那么发生了什么?为什么服务没有被调用?

让我们考虑一下步骤...

  1. 您拨打*ngFor
<a (click)="usermenuitem.goto()" ... >
<a (click)="usermenuitem.goto()" ... >
<a (click)="usermenuitem.goto()" ... >
...
  1. 现在我们分解usermenuitem.goto()。对于以前,这只是() =&gt; {},因此它们将按预期工作。我们的重点是goto: this.logoff,

所以我们只是在做类似下面的事情

const goto = this.logoff
goto()

class myObject {
  constructor() {
    this.name = 'Peter'
  }
  name = 'My Name';
  static sayName () {
    console.log('Say ' + this.name )
  }
}
console.log("Message 1 => ")
myObject.sayName()
console.log("Message 2 => ")
const p = myObject.sayName
p()

如果您运行上面的代码,您会看到第一种方法有效,但第二种方法无效!它会抛出 this 未定义的错误。

这就是你面临的问题。您的代码正在丢失 this 上下文,因此无法正常工作。 alert() 等其他函数可以使用,但 this 的任何函数都将无法使用。

解决方案

要解决此问题,您只需确保不会丢失 this 上下文

选项 1

分配一个变量来存储this,例如that = this。我从来没有在 Angular 中使用过这个选项,但在 vanilla js 中效果很好

选项 2

只需绑定this。这通常是最简单的选择。在您的情况下,您可以简单地使用 this.logoff.bind(this) 并且您的代码应该可以工作

选项 3

使用箭头函数

这是最简单的选择。只需将您的 logoff 函数更改为

logoff = () => {
    this.authService.logout('/');
  }

关于这种方法的一个gotcha 是,如果您使用的是 TS 版本 4+,您可能会遇到与属性排列相关的问题,否则它可以工作

【讨论】:

    【解决方案2】:

    您可以在模板上附加点击事件并传递用户菜单对象

       <a
       *ngFor="let usermenuitem of usermenu; let i = index"
       [routerLink]="usermenuitem.link"
       (click)="goto(usermenuitem)">
       {{usermenuitem.title}}
    </a>
    

    组件

    export class AuthorisedTopNavComponent implements OnInit {
    
      usermenu:Object[] = [
        {
          title: 'Account',
          link: '/account',
          icon:"ua-home.svg",
          goto: ()=>{},
        },
        {
          title: 'Membership',
          link: '/membership',
          icon:"ua-home.svg",
          goto: ()=>{},
        },
        {
          title: 'Logout',
          link: '/',
          icon:"ua-home.svg",
          goto: this.logoff,
        },
      ]
    
      constructor (
        public authService: AuthService
      ) {}  
    
      ngOnInit() {}
    
    
      logoff() {
        this.authService.logout('/');
      }
    
     goto(usermenu){
      if(usermenu.title === 'logout'){
            this.logoff()
        }
     }
    
    }
    

    希望这有帮助吗?

    【讨论】:

    • 谢谢,但我认为这不是一个好习惯。这是一个很好的技巧,但这仅在标题为注销时才有效。如果标题曾经更改为 signoff 或 logoff 或其他内容,则事件处理程序也必须修改。
    猜你喜欢
    • 1970-01-01
    • 2019-12-17
    • 1970-01-01
    • 2019-10-04
    • 1970-01-01
    • 2012-09-07
    • 2016-11-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多