ค้นหาเว็บไซต์

angular 5: วิธีนำเข้า javascript สำหรับคอมโพเนนต์นี้โดยเฉพาะ ไม่ควรให้ใช้งานได้กับคอมโพเนนต์อื่น


ปัจจุบัน

ใน game.component.ts (เส้นทาง: /play)

import '../../assets/js/game.js';

export class PlayComponent implements OnInit {
    constructor() { }

    ngOnInit() {
    }

}

game.js โหลดได้ปกติและเริ่มเกมที่ domain.com/play

ปัญหา

เมื่อฉันโหลด home.component.ts (เส้นทาง: /) สคริปต์เกมก็ถูกนำเข้ามาและถูกแนบด้วย ฉันจะทำอย่างไรให้สคริปต์เกมโหลดเฉพาะที่ /play ได้? ฉันรู้ว่าฉันสามารถใส่สคริปต์ในฟังก์ชันและเรียกใช้เฉพาะในคอมโพเนนต์เกมได้ แต่ฉันอยากหลีกเลี่ยงการโหลด JS มากเกินไปในที่ที่ไม่จำเป็นจริงๆ

คำตอบ #1

ฉันไม่คิดว่าจะมีวิธีแบบ 'Angular' ในการทำสิ่งที่คุณต้องการ นอกจากการยุ่งเกี่ยวกับกระบวนการ boodstrap/Webpack

แค่ใช้ JavaScript ปกติ

โหลดสคริปต์ภายใน ngOnInit hook ของ PlayComponent ของคุณ ด้วยวิธีนี้ สคริปต์จะถูกโหลดเพียงครั้งเดียวเมื่อคอมโพเนนต์ถูกสร้างขึ้น คุณยังสามารถลบสคริปต์ใน ngOnDestroy hook ได้หากคุณต้องการ:

@Component({})
export class PlayComponent implements OnInit, OnDestroy {
    constructor(private assetService: AssetService) {}

    ngOnInit() {
        assetService.loadScript('/assets/js/game.js').then(data => {
            console.log(data); // {loaded: true, status: 'Loaded'}
        });
    }

    ngOnDestroy() {
        assetService.removeScript('/assets/js/game.js');
    }
}

@Injectable()
export class AssetService {
    removeScript(path: string) {
        // TODO: Remove DOM element that has attribute `data-path="${path}"`
    }

    loadScript(path: string): Promise<any> {
        return new Promise(resolve => {
            const script = document.createElement('script');
            script.type = 'text/javascript';
            script.src = path;
            script.setAttribute('data-path', path);

            // IE
            if (script.readyState) {
                script.onreadystatechange = () => {
                    if (script.readyState === 'loaded' || script.readyState === 'complete') {
                        script.onreadystatechange = null;
                        resolve({ loaded: true, status: 'Loaded' });
                    }
                };
            } else {
                script.onload = () => {
                    resolve({ loaded: true, status: 'Loaded' });
                };
            }

            script.onerror = (error: any) => resolve({ loaded: false, status: 'Loaded' });
            document.getElementsByTagName('head')[0].appendChild(script);
        });
    }
}