องค์ประกอบที่ไม่รู้จัก - เชิงมุม 2 พร้อมวัสดุเชิงมุม 2

คราวนี้เอาหัวโขกกำแพงเลย ฉันได้รับข้อผิดพลาดเมื่อเรียกใช้แอป เชิงมุม 2 โดยใช้ SystemJS และวัสดุเชิงมุม ไม่เข้าใจว่าทำไม ฉันกำลังใช้โครงการ Angular-seed: https://github.com/mgechev/angular-seed. ฉันเพิ่มเนื้อหาผ่านแนวทางนี้: https://github.com/mgechev/angular-seed/wiki/Integration-with-AngularMaterial2.

ข้อผิดพลาด:

Unhandled Promise rejection: Template parse errors: 'md-toolbar' is not a known element:

home.component.html

<md-toolbar>Test</md-toolbar>

การกำหนดค่า SystemJS

this.NPM_DEPENDENCIES = [ ...this.NPM_DEPENDENCIES, {src: '@angular/material/core/theming/prebuilt/indigo-pink.css', inject: true} // {src: 'jquery/dist/jquery.min.js', inject: 'libs'}, // {src: 'lodash/lodash.min.js', inject: 'libs'}, ]; this.addPackageBundles({ name:'@angular/material', path:'node_modules/@angular/material/bundles/material.umd.js', packageMeta:{ main: 'index.js', defaultExtension: 'js' } });

โปรดทราบว่าดูเหมือนว่าไฟล์กำลังโหลดในเบราว์เซอร์เมื่อตรวจสอบแหล่งที่มาด้วยเครื่องมือ dev

โมดูลแอป

...
import { MaterialModule } from '@angular/material';

@NgModule({
  imports: [BrowserModule, HttpModule, MaterialModule.forRoot(), AppRoutingModule, AboutModule, HomeModule, SharedModule.forRoot()],
  ...

package.json

  "dependencies": {
    "@angular/common": "~2.4.0",
    "@angular/compiler": "~2.4.0",
    "@angular/core": "~2.4.0",
    "@angular/forms": "~2.4.0",
    "@angular/http": "~2.4.0",
    "@angular/material": "^2.0.0-beta.2",
    "@angular/platform-browser": "~2.4.0",
    "@angular/platform-browser-dynamic": "~2.4.0",
    "@angular/router": "~3.4.1",
    "core-js": "^2.4.1",
    "intl": "^1.2.5",
    "rxjs": "~5.0.3",
    "systemjs": "0.19.41",
    "zone.js": "^0.7.4"
  }
  ...

ส่วนประกอบภายในบ้าน

import { Component, OnInit } from '@angular/core';
import { NameListService } from '../shared/name-list/name-list.service';

/**
 * This class represents the lazy loaded HomeComponent.
 */
@Component({
  moduleId: module.id,
  selector: 'sd-home',
  templateUrl: 'home.component.html',
  styleUrls: ['home.component.css'],
})
export class HomeComponent implements OnInit {
...

ถาม - ฉันจะแก้ไขปัญหาองค์ประกอบที่ไม่รู้จักนี้ได้อย่างไร ขอบคุณ!


person karns    schedule 25.02.2017    source แหล่งที่มา
comment
ตรวจสอบภายใน package.json เวอร์ชันวัสดุของคุณ   -  person kind user    schedule 25.02.2017
comment
นำเข้า MaterialModule เท่านั้น แทนที่จะเป็น MaterialModule.forRoot() และตรวจสอบ   -  person micronyks    schedule 25.02.2017
comment
@Kinduser - เพิ่ม package.json สำหรับคุณ   -  person karns    schedule 25.02.2017
comment
@micronyks - นั่นไม่ได้แก้ไขหรือเปลี่ยนแปลงข้อผิดพลาดขอบคุณ   -  person karns    schedule 25.02.2017
comment
คุณได้รับข้อผิดพลาดอะไรบ้าง?   -  person Aravind    schedule 25.02.2017
comment
HomeComponent มีการประกาศภายใน HomeModule หรือไม่   -  person snorkpete    schedule 06.03.2017


คำตอบ (3)


ดังที่เวอร์ชันล่าสุดบอกว่า (2.0.0-beta.3 cesium-cephalopod (2017) -04-07)) คุณต้องนำเข้า MdToolbarModule ในโมดูลที่โหลด home.component

หากโมดูลเป็น home.module ให้โหลด MdToolbarModule ตรงนั้น ดังนี้:

import { MdToolbarModule } from '@angular/material';

@NgModule({
    imports: [
        ...
        MdToolbarModule, // HERE YOU IMPORT THE TOOLBAR MODULE. IF YOU WANT ONLY THIS MODULE IN YOUR BUILD
        ...
],
...

สิ่งนี้จำเป็นเนื่องจาก AOT และ Lazy Load นี่เป็นวิธีเดียวที่ Angular สามารถลบโค้ดที่ไม่จำเป็นได้ หากคุณไม่โหลดโมดูลในทุกโมดูลที่ต้องการสิ่งนี้ คอมไพเลอร์จะไม่มีทางรู้ว่าใครใช้สิ่งนี้ และจะต้องผนวกโมดูลนั้นในส่วนประกอบทั้งหมด แม้ว่าจะไม่ใช่ส่วนประกอบที่ขี้เกียจก็ตาม

เหตุผลที่คุณไม่จำเป็นต้องโหลด MaterialModule ในส่วนประกอบอื่น ๆ แต่ใน app.module ก็คือ app.module เป็นจุดเริ่มต้นของคุณและจะถูกโหลดเสมอไม่ว่าคุณจะโหลดโมดูลขี้เกียจตัวใดก็ตาม เราสามารถพูดได้ว่า app.module เป็นบิดาของทุกโมดูล ไม่ว่าจะขี้เกียจหรือไม่ก็ตาม

ดังนั้น หากคุณโหลดโมดูลใน app.module โดยใช้ forRoot() หมายความว่าคุณสร้างอินสแตนซ์ส่วนกลางของโมดูล services และส่วนประกอบย่อยทั้งหมดจะสามารถเข้าถึงบริการ thaqt ได้ นี่คือเหตุผลที่คุณไม่จำเป็นต้องโหลด material.module ใน home.module อีกครั้ง เนื่องจาก MaterialModule ใช้เพื่อโหลดบริการที่ Material ใช้เพื่อเชื่อมต่อส่วนประกอบของวัสดุ นั่นคือทั้งหมดที่ MaterialModule ทำ

ส่วนประกอบวัสดุแต่ละรายการเป็นแบบ Plug-and-Play หากคุณโหลด MaterialModule ไว้ในส่วนประกอบหลักแล้ว

สำหรับโมดูลที่โหลดโดยไม่มี forRoot() คุณจะไม่มีบริการซิงเกิลตัน ดังนั้นคุณจะต้องโหลดในทุกองค์ประกอบ ทั้งหมดนี้จำเป็นเพื่อให้ต้นไม้สั่นได้ดีขึ้น โดยที่คุณมีเพียงสิ่งที่คุณต้องการในการสร้างเท่านั้น

person Bruno João    schedule 06.03.2017
comment
กระทรวงสาธารณสุข! แน่นอนว่ามันเป็นสิ่งที่ชัดเจนมาก ขอขอบคุณที่คุณมองหาสิ่งนี้ เป็นเพราะโครงการเมล็ดพันธุ์ที่ฉันใช้มีโมดูลแยกกัน... คุณจะสามารถอธิบาย ทำไม พวกเขาจึงตัดสินใจใส่แต่ละส่วนประกอบลงในโมดูลของตัวเองได้หรือไม่? - person karns; 07.03.2017
comment
สำหรับฉัน แต่ละโมดูลเป็นรายละเอียดการใช้งานภายในของ Angular Material จนถึงจุดหนึ่ง พวกเขาเคยแนะนำให้คุณนำเข้าแต่ละโมดูลที่คุณใช้อยู่ แต่ด้วยการย้ายไปยังการสนับสนุนการเขย่าต้นไม้ที่ดีขึ้น ตอนนี้พวกเขาระบุ MaterialModule เป็นโมดูลที่คุณควรนำเข้า - person snorkpete; 07.03.2017
comment
@vinagreti ฉันไม่คิดว่าความคิดเห็นของคุณถูกต้อง เขาจำเป็นต้องนำเข้า MaterialModule ใน HomeModule ไม่ว่าเขาจะนำเข้าใน AppModule แล้วหรือไม่ก็ตาม และเนื่องจากการนำเข้า MaterialModule มีอยู่แล้ว การนำเข้า MdToolbarModule จึงทำให้ซ้ำซ้อน - person snorkpete; 07.03.2017
comment
@Snorkpete ฉันได้อัปเดตการตอบกลับพร้อมรายละเอียดเพิ่มเติมแล้ว - person Bruno João; 07.03.2017
comment
@vinagreti คุณพูดถูกเกี่ยวกับบริการ - เมื่อคุณนำเข้า MaterialModule ลงใน AppModule บริการของมันจะสามารถเข้าถึงได้จาก root injector ซึ่งโดยทั่วไปหมายความว่าคุณสามารถใช้บริการ MaterialModule ได้จากทุกที่ อย่างไรก็ตาม สิ่งเดียวกันนี้ไม่เป็นความจริงสำหรับการประกาศ (ส่วนประกอบ คำสั่ง ไปป์ เช่น สิ่งที่คุณใช้ในเทมเพลตของคุณ) สำหรับการประกาศของ MaterialModule คุณต้องนำเข้าพวกมันในทุกโมดูลที่คุณใช้ (หรืออีกครั้ง นำเข้าโมดูลอื่นที่ส่งออก MaterialModule) - person snorkpete; 07.03.2017
comment
B@Snorkpete ฉันได้อัปเดตการตอบกลับพร้อมรายละเอียดเพิ่มเติมแล้ว แต่เกี่ยวกับความซ้ำซ้อน คำสั่งของคุณไม่ถูกต้อง มันเป็นเรื่องของการโหลดแบบขี้เกียจ MaterialModule เป็นกาวสำหรับส่วนประกอบต่างๆ ไม่ใช่ส่วนประกอบและเป็นโมดูลสำหรับส่วนประกอบทั้งหมด มันเป็นเพียงบริการจำนวนมากที่ใช้โดยโมดูลวัสดุ คุณจะต้องโหลดโมดูลในทุกโมดูลที่ต้องการสิ่งนี้ นี่เป็นวิธีเดียวที่ Angular สามารถรู้ได้ว่าโมดูลที่โหลดแบบ Lazy ต้องการโมดูลอื่น (mdToolbarModule ในกรณีนี้) เพื่อแทรกลงในโมดูลที่โหลดแบบ Lazy หรือไม่ - person Bruno João; 07.03.2017
comment
@Snorkpete ฉันไม่พบเอกสารเกี่ยวกับเรื่องนี้ แต่สำหรับฉัน ฉันโหลดเฉพาะ MaterialModule ใน app.module และในเด็ก ๆ ฉันโหลดเฉพาะโมดูลส่วนประกอบเป็น mdInputModule mdIconModule และทอท.ก็ทำงานได้อย่างมีเสน่ห์ คุณสามารถพูดถูกเมื่อคุณบอกว่าเราต้องโหลด แต่กรณีการใช้งานไม่ได้พิสูจน์ประเด็นของคุณ - person Bruno João; 07.03.2017
comment
@vinagreti ในตัวอย่างเดียวกันของคุณ ลองนำเข้า MaterialModule (แทน MdInputModule) ในองค์ประกอบลูกแล้วคุณจะได้พฤติกรรมที่เหมือนกันทุกประการ ประเด็นคือ: คุณต้องนำเข้าโมดูลที่มีส่วนประกอบที่คุณต้องการใช้ในทุกโมดูลที่คุณต้องการใช้ ไม่ว่าคุณจะนำเข้าโดยการนำเข้า MaterialModule หรือโดยการนำเข้าแต่ละโมดูล (MdInputModule, MdToolbarModule ฯลฯ ) ค่อนข้างจะค่อนข้าง โดยพลการ แต่ถ้าคุณมีโมดูลฟีเจอร์ แค่นำเข้า MaterialModule ใน AppModule แล้วจัดการให้เสร็จนั้นไม่เพียงพอ คุณต้องนำเข้าสู่โมดูลคุณลักษณะของคุณด้วย - person snorkpete; 07.03.2017
comment
ให้เราสนทนาต่อในการแชท - person Bruno João; 07.03.2017

@karns คุณพูดถึงปัญหาที่มีอยู่ใน HomeComponent และฉันสังเกตเห็นว่าในรายการนำเข้าของคุณมี HomeModule

HomeComponent เป็นของ HomeModule นั้นหรือไม่

หากเป็นเช่นนั้น คุณได้นำเข้า MaterialModule เข้าสู่ HomeModule ของคุณหรือไม่

คุณต้องนำเข้า MaterialModule (หรือโมดูลที่ส่งออก MaterialModule) ลงในทุกโมดูลที่อาจใช้ส่วนประกอบ Angular Material ในเทมเพลต

person snorkpete    schedule 06.03.2017
comment
ขอบคุณสำหรับคำตอบสน็อก มันถูกต้อง แต่ฉันจะยอมรับคำตอบของ Vinagreti เนื่องจากเขามีโค้ดตัวอย่าง โหวตเห็นด้วย - person karns; 07.03.2017

ตัวเลือกที่ 1 :

  1. ตรวจสอบให้แน่ใจว่าคุณใช้คำสั่งด้านล่างเพื่อติดตั้งเนื้อหาลงในแอปของคุณ

    npm install --save @angular/material
    
  2. ไปที่ node_modules และตรวจสอบว่ามีไฟล์เหล่านี้อยู่หรือไม่

    node_modules/@angular/material/bundles/material.umd.js
    @angular/material/core/theming/prebuilt/indigo-pink.css
    
  3. หากมีสองไฟล์ข้างต้นอยู่

    • Delete the materials folder
    • ติดตั้งอีกครั้ง
    • ก่อนการติดตั้ง ให้ตรวจสอบว่ามีการพึ่งพาในไฟล์ package.json หรือไม่
    • ตรวจสอบทันทีว่ามีไฟล์ข้างต้นอยู่หรือไม่
  4. ในแท็บเครือข่ายของเครื่องมือสำหรับนักพัฒนา ตรวจสอบว่าคุณมีดังต่อไปนี้

ป้อนคำอธิบายรูปภาพที่นี่

ตัวเลือกที่ 2 :

หากวิธีแก้ปัญหาข้างต้นไม่ได้ผล ให้ลองทำเช่นนี้

  1. รวมไฟล์ด้านล่างใน index.html ป้อนคำอธิบายรูปภาพที่นี่
  2. ในไฟล์ config.js ของคุณ ลบ บรรทัด @angular/material และใช้การอ้างอิง cdn ด้านล่าง

    '@เชิงมุม/วัสดุ': 'https://unpkg.com/@angular/material/bundles/material.umd.js',

การสาธิตสด เพื่อแสดงว่าการอ้างอิง cdn ใช้งานได้

อัปเดต 1: นักวางระเบิดทำงานได้ดีในขณะนี้ คุณสามารถดูได้

คำอธิบายสำหรับตัวเลือกที่ 2 คือการใช้การอ้างอิง cdn ซึ่งไม่สนใจว่าคุณได้ติดตั้ง node_module หรือไม่ ในกรณีส่วนใหญ่จะใช้งานได้อย่างแน่นอน หากลิงก์ cdn นี้แก้ไขปัญหาของคุณได้ อัปเดตฉัน เราจะลองแก้ไขตัวเลือก 1 ในกรณีของคุณ

person Aravind    schedule 25.02.2017
comment
น่าเสียดายที่ตัวเลือกที่ 1 ใช้งานไม่ได้ ไฟล์อยู่ที่นั่นและยังคงมีข้อผิดพลาด คุณช่วยอธิบายรายละเอียดเกี่ยวกับตัวเลือก 2 bullet #2 หน่อยได้ไหม ฉันสมมติว่าคุณหมายถึงการกำหนดค่า SystemJS คุณสามารถให้บริบทสำหรับการเปลี่ยนแปลงรหัสได้หรือไม่? - person karns; 27.02.2017
comment
@karns จะตรวจสอบและอัปเดตให้คุณทราบในบางครั้ง - person Aravind; 28.02.2017
comment
ขอขอบคุณสำหรับความช่วยเหลือ Aravind ขอขอบคุณอย่างยิ่งที่ตรวจสอบเรื่องนี้ และคุณมีคำแนะนำที่เป็นประโยชน์ซึ่งช่วยจำกัดปัญหาให้แคบลงในที่สุด แต่ก็ไม่ได้แก้ปัญหา แต่คนอื่นๆ ก็ตอบถูก - person karns; 07.03.2017