- 版本:1.2.0
- GitHub: https://github.com/BinaryNate/nativescript-component
- NPM: https://npmjs.net.cn/package/nativescript-component
- 下载
- 昨天: 0
- 上周: 0
- 上个月: 12
NativeScript组件
一种简单的方法来创建无需Angular的可重用NativeScript组件。
优点
- 简单的API 用于定义组件并将其属性绑定到它。
- 单个组件 的多个实例可以用于一个页面。
- 每个组件实例都会自动获得其自己的 独立状态。
- 自动绑定 XML属性到组件的绑定上下文。
- 父组件可以安全地将依赖项传递给其子组件,因为外部组件在嵌套组件之前初始化。
- 自动绑定传递给组件视图的上下文属性
navigate()
和showModal()
。 - 默认情况下,组件实例将在其视图的
unloaded
事件上自动 销毁。 - 可以将组件定义为 单例,以便在整个应用程序的生命周期内保持单个实例。
安装
npm install nativescript-component --save
示例
示例 1:sample-groceries应用
此示例 将从 NativeScript入门指南 中的标准sample-groceries应用更新为使用ES 6和nativescript-component进行基于组件的设计。为了参考,您可以将其与 原始版本 进行比较。
示例 2:嵌套组件
在此示例中,我们将创建一个名为 details-page
的父组件,该组件使用名为 editable-text
的另一个组件的多个实例,允许用户查看和编辑数据记录。
目录结构
app
|
|-- components
|
|-- details-page
| |
| |-- details-page.xml
| |-- details-page.js
|
|-- editable-text
|
|-- editable-text.xml
|-- editable-text.js
出于简洁起见,此示例中省略了样式,但将组件的样式分组在其目录中(例如 details-page/details-page.css
和 editable-text/editable-text.css
)是良好的实践。查看Nativescript的LESS 和 SASS 预编译插件以获取干净的样式。
details-page.xml
该 details-page
组件的模板由一个 ActionBar
组成,该 ActionBar
只有一个控件:一个按钮,用于在“视图”模式和“编辑”模式之间切换UI;以及一个列出我们的字段(姓名和姓氏)的 GridLayout
。
<Page navigatingTo="onNavigatingTo" xmlns:e="components/editable-text">
<Page.actionBar>
<ActionBar title="User Details">
<ActionItem text="Edit" ios.position="right" tap="edit" visibility="{{ controls.edit, controls.edit ? 'collapsed' : 'visible' }}"/>
<ActionItem text="Save" ios.position="right" tap="save" visibility="{{ controls.edit, controls.edit ? 'visible' : 'collapsed' }}"/>
</ActionBar>
</Page.actionBar>
<StackLayout>
<GridLayout columns="*,*" rows="auto,auto">
<Label text="First Name" col="0" row="0"/>
<e:editable-text class="name" record="{{ user }}" fieldName="firstName" controls="{{ controls }}" col="1" row="0"/>
<Label text="Last Name" col="0" row="1"/>
<e:editable-text class="name" record="{{ user }}" fieldName="lastName" controls="{{ controls }}" col="1" row="1"/>
</GridLayout>
</StackLayout>
</Page>
注意事项
-
属性
navigatingTo="onNavigatingTo"
将组件的内置onNavigatingTo()
钩子连接起来,该钩子在视图加载时实例化组件。 -
属性
xmlns:e="components/editable-text"
定义了一个名为 "e" 的命名空间,以便我们的组件可以在XML中以<e:editable-text/>
的形式引用。 -
在属性
visibility="{{ controls.edit, controls.edit ? 'collapsed' : 'visible' }}"
中,将controls.edit
传递为{{ }}
的第一个参数,以便指示NativeScript,嵌套的edit
属性应该是观察表达式后的数据源,而不是包含它的controls
对象。此要求在 NativeScript数据绑定文档 中进行了记录。
details-page.js
对于此示例,假设另一个页面通过调用 navigate()
来导航到我们的 details-page
组件。
frames.topmost().navigate({
moduleName: 'components/details-page/details-page',
context: {
user: new Observable({ firstName: 'Brendan', lastName: 'Eich' })
}
});
《details-page》组件的JavaScript文件将看起来像这样
import { Observable } from 'data/observable';
import Component from 'nativescript-component';
class DetailsPage extends Component {
/**
* Place initialization code in `init`, which is automatically called
* after the parent is initialized and before child components are initialized.
*
* @override
*/
init() {
this.set('controls', new Observable({ edit: false }));
}
/**
* Switches the UI from view mode to edit mode.
*/
edit() {
/** @todo: Check if `this.set('controls.edit', true)` correctly sets the nested proeprty and, if not, implement support for that. */
let options = this.get('controls');
options.set('edit', true);
}
/**
* Switches the UI from edit mode to view mode.
*/
save() {
let options = this.get('controls');
options.set('edit', false);
}
}
DetailsPage.export(exports);
注意事项
-
在组件的父组件(如果有)初始化后,会自动调用内置的
init
钩子。重写此钩子以使用内置方法和属性进行任何设置。this.get()
和this.set()
用于在组件的绑定上下文中获取和设置属性。以这种方式设置的属性可以在组件的模板中显示。 -
传递给
navigate()
的参数会自动绑定到组件的绑定上下文,这意味着在我们的示例中,user
参数可以通过this.get('user')
在JavaScript中访问,并在XML模板中作为{{ user }}
可用。 -
export()
用于以NativeScript运行时期望的格式导出类。
editable-text.xml
可以通过其父组件(《details-page》)在“查看”模式和“编辑”模式之间切换《editable-text》组件,因此其模板有一个只读的<Label/>
,在“查看”模式下显示,以及一个可编辑的<TextField/>
,在“编辑”模式下显示。
<StackLayout loaded="onLoaded">
<Label id="label" visibility="{{ controls.edit, controls.edit ? 'collapsed' : 'visible' }}"/>
<TextField id="input" visibility="{{ controls.edit, controls.edit ? 'visible' : 'collapsed' }}"/>
</StackLayout>
editable-text.js
《editable-text》组件从其父组件接受三个参数
record
- 包含我们想要查看和编辑的属性的数据记录对象fieldName
- 我们想要查看和编辑的record
对象中属性的名称controls
- 包含属性的对象,允许父组件动态控制子组件。在这个例子中,我们只使用单个controls.edit
属性来指示文本字段是否处于编辑模式。
import Component from 'nativescript-component';
class EditableText extends Component {
/**
* @override
*/
init() {
// Set up the two-way binding for the data record's specified property.
// This must be done in JavaScript, because NativeScript's XML binding expressions don't currently support dynamic
// property names.
let label = this.view.getViewById('label'),
input = this.view.getViewById('input'),
record = this.get('record'),
fieldName = this.get('fieldName');
label.bind({
sourceProperty: fieldName,
targetProperty: 'text',
twoWay: true
}, record);
input.bind({
sourceProperty: fieldName,
targetProperty: 'text',
twoWay: true
}, record);
}
}
EditableText.export(exports);
注意事项
-
作为XML属性传递的参数会自动设置在组件的绑定上下文中,并可以使用
this.get()
访问。 -
组件的视图可以通过
this.view
访问。 -
通常不需要像在
init
中这样手动设置绑定,但在这个情况下需要这样做,以便允许fieldName
属性动态指定我们感兴趣的属性名称。
有关更多信息,请参阅API文档。
注意事项
在ListView.itemTemplate
或Repeater.itemTemplate
中嵌入组件
- 由于nativescript-component允许每个列表项都有自己的独立状态,因此它很好地服务于这种场景。
- 然而,正如在sample-groceries应用中所注明的,你必须注意,在这种情况下,列表项会自动设置为组件的绑定上下文,最重要的是,它是
不可变
的。 - 这意味着在你列表项组件中,你不能使用
this.set('foo', foo)
来在绑定上下文中设置新属性以在模板中显示该属性;相反,你必须在该对象作为数组传递给ListView
的items
属性之前设置该属性。 - 你仍然可以使用
this.foo = foo
来设置组件的实例属性,但它们不会在组件的模板中可用。
贡献
找到一个问题或有一个功能的想法?请随时提交PR或打开一个问题。
构建
此模块使用ES 6实现并转换为ES 5以导出。要构建源代码
npm run build
还有一个git预提交钩子,在提交时自动构建,因为dist目录已提交。
代码检查
npm run lint