我正在尝试ionic2 beta9,并尝试使用离子滑动创建自定义组件,但出现错误。
父组件
<ion-content class="home" padding>
<ion-slides loop="true">
<slide-item *ngFor="let image of [1,2,3,4,5]" [imgIdx]="image"></slide-item>
</ion-slides>
</ion-content>
幻灯片项目自定义组件
<ion-slide>
<div class="bcontent">
<div class="bimg">
<img data-src="images/slide{{imgIdx}}.jpeg">
</div>
<p class="info">My text</p>
</div>
</ion-slide>
slide-item.ts
@Component({
selector: 'slide-item',
templateUrl: 'build/components/slide-item/slide-item.html',
directives: [Slides, Slide]
})
export class SlideItem {
@Input()
imgIdx: number;
constructor() {
console.log("SlideItem::constructor...imgIdx="+this.imgIdx);
}
}
我遇到以下错误:
zone.js:461
Unhandled Promise rejection: Template parse errors:
No provider for Slides ("
for more info on Angular 2 Components.
-->
[ERROR ->]<ion-slide>
<div class="bcontent">
<div class="bimg">
"): SlideItem@6:0
;区域:角度;任务:Promise.then;值:
BaseException {message: "Template parse errors:↵No provider for Slides ("↵ …↵ <div class="bimg">↵"):
SlideItem@6:0", stack: "Error: Template parse errors:↵No provider for Slid…ndroid_asset/www/build/js/app.bundle.js:30622:41)"}message:
"Template parse errors:↵No provider for Slides ("↵ for more info on Angular 2 Components.↵-->↵[ERROR ->]<ion-slide>↵ <div class="bcontent">↵ <div class="bimg">↵"): SlideItem@6:0"
stack: "Error: Template parse errors:↵No provider for Slides ("↵ for more info on Angular 2 Components.↵-->↵[ERROR ->]<ion-slide>↵ <div class="bcontent">↵ <div class="bimg">↵"): SlideItem@6:0↵ at new BaseException (file:///android_asset/www/build/js/app.bundle.js:1760:23)↵ at TemplateParser.parse (file:///android_asset/www/build/js/app.bundle.js:16401:19)↵ at file:///android_asset/www/build/js/app.bundle.js:14643:64↵ at ZoneDelegate.invoke (file:///android_asset/www/build/js/zone.js:323:29)↵ at Object.onInvoke (file:///android_asset/www/build/js/app.bundle.js:30631:41)↵ at ZoneDelegate.invoke (file:///android_asset/www/build/js/zone.js:322:35)↵ at Zone.run (file:///android_asset/www/build/js/zone.js:216:44)↵ at file:///android_asset/www/build/js/zone.js:571:58↵ at ZoneDelegate.invokeTask (file:///android_asset/www/build/js/zone.js:356:38)↵ at Object.onInvokeTask (file:///android_asset/www/build/js/app.bundle.js:30622:41)"__proto__: ErrorconsoleError @ zone.js:461_loop_1 @ zone.js:490drainMicroTaskQueue @ zone.js:494ZoneTask.invoke @ zone.js:426
最佳答案
为什么不起作用
我认为使用Slide和Slides组件的当前设计是不可能的。 ion-slide
必须是ion-slides
元素的子元素,并且必须能够在同一模板中找到其父幻灯片。
来源:
@Component({
selector: 'ion-slide',
template: '<div class="slide-zoom"><ng-content></ng-content></div>',
changeDetection: ChangeDetectionStrategy.OnPush,
encapsulation: ViewEncapsulation.None,
})
export class Slide {
ele: HTMLElement;
@Input() zoom: any;
constructor(
elementRef: ElementRef,
@Host() public slides: Slides
) {
this.ele = elementRef.nativeElement;
this.ele.classList.add('swiper-slide');
slides.rapidUpdate();
}
ngOnDestroy() {
this.slides.rapidUpdate();
}
}
您会看到父
Slides
是必需的,以便当动态添加或销毁Slide
时,它可以触发Slides
更新。它仅限于使用@Host
装饰器的当前模板。当您尝试在自定义模板中使用
ion-slide
时,会收到模板错误,因为模板中没有要传递给Slides
的Slide
对象。一种部分解决方案
我玩了这个,你可以像下面这样工作:
slides
对象的引用Slides
,牺牲了在动态添加/删除幻灯片Slides
的能力修改后的slides.ts源:
@Component({
selector: 'ion-slide',
template: '<div class="slide-zoom"><ng-content></ng-content></div>',
changeDetection: ChangeDetectionStrategy.OnPush,
encapsulation: ViewEncapsulation.None,
})
export class Slide {
ele: HTMLElement;
@Input() zoom: any;
constructor(
elementRef: ElementRef
) {
this.ele = elementRef.nativeElement;
this.ele.classList.add('swiper-slide');
}
}
和您的幻灯片项目:
@Component({
selector: 'slide-item',
templateUrl: 'slide-item.html',
})
export class SlideItem {
@Input()
imgIdx: number;
constructor(elementRef: ElementRef) {
console.log("SlideItem::constructor...imgIdx="+this.imgIdx);
elementRef.nativeElement.classList.add('swiper-slide');
}
}
我说这是一个局部解决方案,因为您必须修改离子源,并且因为现在您必须在添加/删除幻灯片时手动调用update
Slides
更新。我确实在进一步修改离子源方面保持了一些进展,以在添加/删除幻灯片(包括您自己的自定义幻灯片容器)上维持自动更新。但是与下面的选项相比,这并不值得。
部分解决方案2
Slide
的代码非常简单。最好是直接定义自己的组件(而不是包装ion-slide
):@Component({
selector: 'slide-item',
templateURL: 'slite-item.html',
changeDetection: ChangeDetectionStrategy.OnPush,
encapsulation: ViewEncapsulation.None,
})
export class SlideItem {
ele: HTMLElement;
@Input() zoom: any;
@Input() imgIdx: number;
constructor(
elementRef: ElementRef
) {
this.ele = elementRef.nativeElement;
this.ele.classList.add('swiper-slide');
console.log("SlideItem::constructor...imgIdx="+this.imgIdx)
}
}
和模板
<div class="slide-zoom bcontent">
<div class="bimg">
<img data-src="images/slide{{imgIdx}}.jpeg">
</div>
<p class="info">My text</p>
</div>
我称此为部分解决方案还因为您必须维护一些与Ionic镜像的额外源。如果离子载玻片的实现发生变化,则可能必须更新自定义载玻片。
改进的解决方案
Here is a SO answer about extending a component。我还没有使它起作用,因为到目前为止,它与Angular无关(
ComponentMetaData
不再存在),但是我认为这是一种更好的方法。您将使用此装饰器导入和扩展Slide
组件。export function CustomComponent(annotation: any) {
return function (target: Function) {
var parentTarget = Object.getPrototypeOf(target.prototype).constructor;
var parentAnnotations = Reflect.getMetadata('annotations', parentTarget);
var parentAnnotation = parentAnnotations[0];
Object.keys(parentAnnotation).forEach(key => {
if (isPresent(parentAnnotation[key])) {
annotation[key] = parentAnnotation[key];
}
});
var metadata = new ComponentMetadata(annotation);
Reflect.defineMetadata('annotations', [ metadata ], target);
}
}
您的模板将与先前的解决方案相同,但该类将简化为以下内容。
import { Slide } from 'ionic-angular';
@CustomComponent({
selector: 'slide-item',
templateURL: 'slite-item.html'
})
export class SlideItem extends Slide {
@Input() imgIdx: number;
}
关于ionic2 - 定制组件带 ionic 滑轨,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/37979660/