ionic-angular-与使用导航的两个页面中的相同组件发生冲突

时间:2018-07-20 10:13:11

标签: angular three.js ionic3 components lifecycle

我正在使用ionic-angular和三个js开发一个Android应用程序。
我有一个组件实现了三个js(用于显示2d网格)和使用此组件的3个页面。

当我想用组件绘制东西时,我使用事件(发布/订阅)。有用 !但是,当我使用navMenu在页面之间切换并且重用一个事件时,旧页面的所有组件都会捕获该事件。

我认为使用nav时页面和子组件被破坏了,我认为是对的,该组件被调用ngOnDestroy()。但是它仍然捕获事件,因此我尝试取消订阅ngOnDestroy(),但现在没有任何组件捕获事件。

这是我的代码:
app.component.ts

export class MyApp {
  @ViewChild("myNav") nav: NavController;

  rootPage: any = LearnPage;

  pages: Array<{title: string, component: any}>;

  constructor(public platform: Platform, public statusBar: StatusBar, public splashScreen: SplashScreen) {
    this.initializeApp();

    this.pages = [
      { title: 'Learn', component: LearnPage },
      { title: 'Work', component: WorkPage},
      { title: 'Play', component: PlayPage}
    ];

  }

  initializeApp() {
    this.platform.ready().then(() => {
      this.statusBar.styleDefault();
      this.splashScreen.hide();
    });
  }

  openPage(page) {
    this.nav.setRoot(page.component);
  }
}

app.html:

<ion-menu [content]="content">
<ion-header>
  <ion-toolbar>
    <ion-title>Menu</ion-title>
  </ion-toolbar>
</ion-header>

<ion-content>
  <ion-list>
    <button menuClose ion-item *ngFor="let p of pages" (click)="openPage(p)">
      {{p.title}}
    </button>
  </ion-list>
</ion-content>

页面来源,当前3个页面相同: HTML:

<ion-header>
  <ion-navbar>
    <button ion-button menuToggle>
      <ion-icon name="menu"></ion-icon>
    </button>
    <ion-title>Learn</ion-title>
  </ion-navbar>
</ion-header>


<ion-content>
  <div class="padding-default">
    <grid class="canvas-disable"></grid>
  </div>
  <ion-item no-lines class="padding-default">
    <ion-select class="default-select" [(ngModel)]="number" (ionChange)="onChange()">
      <ion-option *ngFor="let number of numbers" [value]="number">{{number}} {{shape}}</ion-option>
    </ion-select>
  </ion-item>
</ion-content>

.ts:

export class LearnPage {
  @ViewChild(Select) select: Select;

  shape: string = shapeNames.SQUARE;
  number: number = 1;
  numbers: number[] = Array.from(Array(100),(x,i)=>i+1);

  constructor(public events: Events, public eventNames: EventNames) {

  }

  ngAfterViewInit() {
    this.events.publish(this.eventNames.GRID_COUNT, this.number, this.shape);
  }

  onChange() {
    this.events.publish(this.eventNames.GRID_COUNT, this.number, this.shape);
  }
}

和网格组件:HTML:

<div #rendererContainer></div>

.ts:

export class GridComponent {
  @ViewChild('rendererContainer') rendererContainer: ElementRef;

  canvasWidth: any;
  grid: Shape[][];
  color: number = 0xff0000;

  renderer = new THREE.WebGLRenderer();
  scene = null;
  camera = null;
  mesh = null;

  constructor(public events: Events, public eventNames: EventNames) {
    this.canvasWidth = window.innerWidth * 86 / 100;
    this.grid = new Array<Array<Shape>>();
    for (let y = 0; y < 10; y++) {
      let row: Shape[] = new Array<Shape>();
      for (let x = 0; x < 10; x++) {
        row.push(new Shape(y * 10 + x));
      }
      this.grid.push(row);
    }

    this.scene = new THREE.Scene();
    this.camera = new THREE.OrthographicCamera(0, this.canvasWidth, 0, this.canvasWidth, 1, 1000);
    this.drawGrid();
    this.events.subscribe(this.eventNames.GRID_COUNT, (x, s) => { this.count(x, s); });
    console.log("Suscribe");
  }

  ngAfterViewInit() {
    this.renderer.setSize(this.canvasWidth, this.canvasWidth);
   this.rendererContainer.nativeElement.appendChild(this.renderer.domElement);
    this.renderer.render(this.scene, this.camera);
  }

  ngOnDestroy() {
    console.log("Grid ngOnDestroy");
    this.events.unsubscribe(this.eventNames.GRID_COUNT);
  }

  drawGrid() {
    let size = this.canvasWidth + 1;
    let divisions = 10;
    let gridHelper = new THREE.GridHelper(size, divisions, 0x000000, 0x000000);
    gridHelper.rotation.x = Math.PI / 2;
    gridHelper.position.z = -900;
    gridHelper.position.x = this.canvasWidth / 2;
    gridHelper.position.y = this.canvasWidth / 2;
    this.scene.add(gridHelper);

    let material = new THREE.MeshBasicMaterial({ color: 0xffffff, side: THREE.DoubleSide });
    let plane = new THREE.Mesh(new THREE.PlaneGeometry(this.canvasWidth, this.canvasWidth), material);
    plane.position.z = -1000;
    plane.position.x = this.canvasWidth / 2;
    plane.position.y = this.canvasWidth / 2;
    this.scene.add(plane);
  }

  drawMesh(shape: Shape, x, y) {
    let geometry = new THREE.BoxGeometry(this.canvasWidth / 11, this.canvasWidth / 11, this.canvasWidth / 11);
    let material = new THREE.MeshBasicMaterial({ color: this.color });
    this.mesh = new THREE.Mesh(geometry, material);
    this.mesh.position.z = -100;
    this.mesh.position.x = x * this.canvasWidth / 10 + this.canvasWidth / 20;
    this.mesh.position.y = y * this.canvasWidth / 10 + this.canvasWidth / 20;
    this.mesh.name = shape.id
    shape.mesh = this.mesh;
    this.scene.add(this.mesh);
    this.renderer.render(this.scene, this.camera);
    shape.filled = !shape.filled;
  }

  count(x: number, s: string) {
    console.log("Count event received");
    while (this.scene.children.length > 0) {
      this.scene.remove(this.scene.children[0]);
    }
    this.drawGrid();
    for (let i = 0; i < x; i++) {
      this.drawMesh(this.grid[i % 10][Math.floor(i / 10)], i % 10, Math.floor(i / 10));
    }
  }
}

可能有些东西我误解或滥用了,谢谢您的阅读和帮助。

1 个答案:

答案 0 :(得分:0)

我解决了我的问题。

在我的组件中,要获得宽度,请添加/删除我使用JQuery所做的类并设置动画。

let rowValues = $("#values")
let svgIndicator = $("svg#indicator")
let paragraphs = $(".bind-text")

选择器jquery错误,因为它将选择页面中的所有元素

这是结果

enter image description here

现在,我使用@ViewChildRenderer2选择元素来添加/删除类。 jQuery只是为左svg制作动画

// HTML ELMENTS
@ViewChild('rowValues') rowValues: ElementRef
@ViewChild('indicator') svgIndicator: ElementRef
@ViewChildren('bindText') paragraphs:QueryList<ElementRef>

现在一切正常

enter image description here