stenciljs 学习六 组件开发样式指南

2023-06-20,,

组件不是动作,最好使用名词而不是动词,

文件结构

每个文件一个组件。
每个目录一个组件。虽然将类似的组件分组到同一目录中可能是有意义的,但我们发现当每个组件都有自己的目录时,更容易记录组件。
实现(.tsx)和组件的样式应该位于同一目录中。

参考格式

├── card
│ ├── card.ios.scss
│ ├── card.md.scss
│ ├── card.scss
│ ├── card.tsx
│ └── test
│ └── basic
│ ├── e2e.js
│ └── index.html
├── card-content
│ ├── card-content.ios.scss
│ ├── card-content.md.scss
│ ├── card-content.scss
│ └── card-content.tsx
├── card-title
│ ├── card-title.ios.scss
│ ├── card-title.md.scss
│ ├── card-title.scss

命名

html 标签
当创建要在不同项目中使用的组件集合(如@ ionic / core)时,前缀具有重要作用。Web组件没有作用域
,因为它们是在网页中全局声明的,这意味着需要“唯一”前缀来防止冲突。前缀还有助于快速识别组件的集合。
此外,Web组件需要在标记名称中包含“ - ”短划线,因此使用第一部分命名组件是很自然的。
不建议使用“stencil”作为前缀
命名
组件不是动作,它们在概念上是“事物”。最好使用名词而不是动词,例如“动画”而不是“动画”。
“输入”,“制表符”,“导航”,“菜单”是一些例子。
修饰符
当几个组件相关和/或耦合时,最好共享名称,然后添加不同的修饰符,例如:

<ion-card>
<ion-card-header>
<ion-card-content>

组件(ts 类)

由于类是作用域的,因此组件的ES6类的名称应该没有前缀。没有碰撞的风险。

@Component({
tag: 'ion-button'
})
export class Button { ... } @Component({
tag: 'ion-menu'
})
export class Menu { ... }

typescript

遵循 tslint-ionic-rules
应该内联变量装饰器。

@Prop() name: string;
@Element() el: HTMLElement;

方法装饰器应该是多行的

@Listen('click')
onClick() {
...
}

尽可能使用私有变量和方法。
带有Method / Prop / Event / Component装饰器的代码应该有jsdocs

参考实例

@Component({
tag: 'ion-something',
styleUrl: 'something.scss',
styleUrls: {
ios: 'something.ios.scss',
md: 'something.md.scss',
wp: 'something.wp.scss'
},
host: {
theme: 'something'
}
})
export class Something { /**
* 1. Own Properties
* Always set the type if a default value has not
* been set. If a default value is being set, then type
* is already inferred. List the own properties in
* alphabetical order. Note that because these properties
* do not have the @Prop() decorator, they will not be exposed
* publicly on the host element, but only used internally.
*/
num: number;
someText = 'default'; /**
* 2. Reference to host HTML element.
* Inlined decorator
*/
@Element() el: HTMLElement; /**
* 3. State() variables
* Inlined decorator, alphabetical order.
*/
@State() isValidated: boolean;
@State() status = 0; /**
* 4. Internal props (context and connect)
* Inlined decorator, alphabetical order.
*/
@Prop({ context: 'config' }) config: Config;
@Prop({ connect: 'ion-menu-controller' }) lazyMenuCtrl: Lazy<MenuController>; /**
* 5. Public Property API
* Inlined decorator, alphabetical order. These are
* different than "own properties" in that public props
* are exposed as properties and attributes on the host element.
* Requires JSDocs for public API documentation.
*/
@Prop() content: string;
@Prop() enabled: boolean;
@Prop() menuId: string;
@Prop() type = 'overlay'; /**
* Prop lifecycle events SHOULD go just behind the Prop they listen to.
* This makes sense since both statements are strongly connected.
* - If renaming the instance variable name you must also update the name in @Watch()
* - Code is easier to follow and maintain.
*/
@Prop() swipeEnabled = true; @Watch('swipeEnabled')
swipeEnabledChanged(newSwipeEnabled: boolean, oldSwipeEnabled: boolean) {
this.updateState();
} /**
* 6. Events section
* Inlined decorator, alphabetical order.
* Requires JSDocs for public API documentation.
*/
@Event() ionClose: EventEmitter;
@Event() ionDrag: EventEmitter;
@Event() ionOpen: EventEmitter; /**
* 7. Component lifecycle events
* Ordered by their natural call order, for example
* WillLoad should go before DidLoad.
*/
componentWillLoad() {}
componentDidLoad() {}
componentWillEnter() {}
componentDidEnter() {}
componentWillLeave() {}
componentDidLeave() {}
componentDidUnload() {} /**
* 8. Listeners
* It is ok to place them in a different location
* if makes more sense in the context. Recommend
* starting a listener method with "on".
* Always use two lines.
*/
@Listen('click', { enabled: false })
onClick(ev: UIEvent) {
console.log('hi!')
} /**
* 9. Public methods API
* These methods are exposed on the host element.
* Always use two lines.
* Requires JSDocs for public API documentation.
*/
@Method()
open() {
...
} @Method()
close() {
...
} /**
* 10. Local methods
* Internal business logic. These methods cannot be
* called from the host element.
*/
prepareAnimation(): Promise<void> {
...
} updateState() {
...
} /**
* 11. hostData() function
* Used to dynamically set host element attributes.
* Should be placed directly above render()
*/
hostData() {
return {
attribute: 'navigation',
side: this.isRightSide ? 'right' : 'left',
type: this.type,
class: {
'something-is-animating': this.isAnimating
}
};
} /**
* 12. render() function
* Always the last one in the class.
*/
render() {
return (
<div class='menu-inner page-inner'>
<slot></slot>
</div>
);
}
}

参考资料

https://stenciljs.com/docs/style-guide

 
 
 
 

stenciljs 学习六 组件开发样式指南的相关教程结束。

《stenciljs 学习六 组件开发样式指南.doc》

下载本文的Word格式文档,以方便收藏与打印。