NativeScript APP 开发概览

NativeScript 是一个使用 JavaScript、TypeScript 或任何转译为 JavaScript 的框架,为 iOS、Android、visionOS 等平台构建真正原生应用程序的框架。

项目概述

NativeScript 提供:

  • 直接原生 API 访问 - 大多数平台 API 无需包装器,无需插件
  • 跨平台开发 - 单一代码库支持多个平台
  • 框架灵活性 - 支持 Angular、Vue、Solid、Svelte、React 或纯 TypeScript
  • 原生性能 - 纯原生 UI 渲染

项目结构

典型的 NativeScript 项目结构:

复制代码
my-app/
├── App_Resources/           # 平台特定资源 (图标, 配置, 原生代码)
│   ├── Android/            # Android 特定资源
│   │   └── src/main/res/   # Android 资源 (drawable, values 等)
│   └── iOS/                # iOS 特定资源
│       └── src/            # Swift/ObjC 原生代码
├── src/                    # 应用程序源代码
│   ├── app.ts              # 应用程序入口点
│   ├── app.css             # 全局样式
│   └── ...                 # 组件, 页面等
├── nativescript.config.ts  # NativeScript 配置
├── package.json            # 依赖项
├── tsconfig.json           # TypeScript 配置
└── webpack.config.js       # 构建配置 (Vite 中可选)

核心导入

始终从 @nativescript/core 导入:

typescript 复制代码
import {
  Application,
  Observable,
  Frame,
  Page,
  Color,
  Utils,
  Device,
  Screen,
  isAndroid,
  isIOS,
  File,
  Folder,
  knownFolders,
  Http,
  ImageSource,
  ObservableArray,
} from '@nativescript/core'

UI 组件

布局容器

  • GridLayout - 表格式布局,带有行和列
  • StackLayout - 将子元素垂直或水平堆叠
  • FlexboxLayout - 类似 CSS Flexbox 的布局
  • AbsoluteLayout - 使用绝对坐标定位子元素
  • DockLayout - 将子元素停靠到边缘
  • WrapLayout - 将子元素换行到下一行/列

导航组件

  • Frame - 导航容器
  • Page - 屏幕内容容器
  • ActionBar - 顶部导航栏

常用组件

  • Label - 文本显示
  • Button - 可点击按钮
  • TextField - 单行文本输入
  • TextView - 多行文本输入
  • Image - 图像显示
  • ListView - 可滚动列表,支持视图回收
  • ScrollView - 可滚动容器
  • WebView - 内嵌网页浏览器
  • Switch, Slider, Progress, ActivityIndicator
  • DatePicker, TimePicker, ListPicker
  • SearchBar, SegmentedBar, TabView

最佳实践

1. 视图绑定 - 使用直接属性绑定

不良做法:

xml 复制代码
<Label text="{{ getMyText() }}" />

良好做法:

xml 复制代码
<Label text="{{ myText }}" />

直接属性绑定提供 1-1 数据投影,以获得最佳的视图渲染性能。

2. ListView - 为条件布局使用模板选择器

不良做法: 在 ListView 项目内使用 v-if/ngIf 会导致滚动期间的视图创建/销毁。

良好做法: 为不同的行布局使用 itemTemplateSelector

xml 复制代码
<ListView items="{{ items }}" itemTemplateSelector="{{ selectTemplate }}">
  <ListView.itemTemplates>
    <template key="header">
      <Label text="{{ title }}" class="header" />
    </template>
    <template key="item">
      <Label text="{{ name }}" />
    </template>
  </ListView.itemTemplates>
</ListView>
typescript 复制代码
selectItemTemplate(item, index, items) {
  return item.isHeader ? 'header' : 'item';
}

3. 可见性 vs v-if/ngIf

  • v-if/ngIf - 完全销毁/重建视图 (滚动期间开销大)
  • visibility: 'collapse'hidden: true - 隐藏视图但不销毁它
  • visibility: 'hidden' - 隐藏但保留布局空间

对于滚动等性能关键场景,请使用 hiddenvisibility

4. iOS 代理 - 始终保留引用

不良做法:

typescript 复制代码
controller.delegate = MyDelegateImpl.initWithOwner(this)

良好做法:

typescript 复制代码
this.delegateRef = MyDelegateImpl.initWithOwner(this)
controller.delegate = this.delegateRef

不保留代理引用会导致垃圾回收问题。

5. 定时器和间隔 - 始终清理

typescript 复制代码
// 存储引用
this.intervalId = setInterval(() => { /* ... */ }, 1000)

// 在适当的生命周期中清理
clearInterval(this.intervalId)

失控的定时器会导致内存泄漏和意外行为。

扩展原生类

Android (使用 @NativeClass 装饰器)

typescript 复制代码
@NativeClass()
class MyButton extends android.widget.Button {
  constructor() {
    super()
    return global.__native(this)
  }

  setEnabled(enabled: boolean): void {
    this.super.setEnabled(enabled)
  }
}

iOS (使用 @NativeClass 装饰器)

typescript 复制代码
@NativeClass()
class MyViewController extends UIViewController {
  static ObjCProtocols = [UITableViewDelegate]
  
  viewDidLoad(): void {
    super.viewDidLoad()
    // 设置代码
  }
}

// 在其他地方使用时正确导出
export { MyViewController }

单文件中的跨平台原生类

typescript 复制代码
let customClass
function setupCustomClass() {
  if (__ANDROID__) {
    @NativeClass()
    class CustomClass extends android.view.View {
      // Android 实现
    }
    customClass = CustomClass
  } else {
    @NativeClass()
    class CustomClass extends NSObject {
      // iOS 实现
    }
    customClass = CustomClass
  }
}
setupCustomClass()

使用 Observable 进行数据绑定

typescript 复制代码
import { Observable, EventData } from '@nativescript/core'

export class ViewModel extends Observable {
  private _counter: number = 0

  get counter(): number {
    return this._counter
  }

  set counter(value: number) {
    if (this._counter !== value) {
      this._counter = value
      this.notifyPropertyChange('counter', value)
    }
  }

  onTap(args: EventData) {
    this.counter++
  }
}

平台条件判断

除了所有 NativeScript 捆绑器 (webpack, vite 等) 提供的全局宏外,@nativescript/core 还提供了各种条件辅助函数:

typescript 复制代码
import { isAndroid, isIOS, isVisionOS } from '@nativescript/core'

if (isAndroid) {
  // Android 特定代码
}

if (isIOS) {
  // iOS 特定代码
}

if (isVisionOS) {
  // visionOS 特定代码
}

// 构建时宏 (针对其他平台编译时会被移除)
if (__ANDROID__) {
  // 仅编译为 Android
}

if (__IOS__) {
  // 仅编译为 iOS
}

if (__VISIONOS__) {
  // 仅编译为 visionOS
}

if (__APPLE__) {
  // 编译为 iOS 和 visionOS
}

if (__DEV__) {
  // 仅开发环境代码
}

平台特定文件

使用平台后缀实现完全不同的实现:

  • my-component.android.ts - 仅 Android
  • my-component.ios.ts - 仅 iOS

或者在同一文件中使用条件判断,适用于有平台差异的共享逻辑。

使用 Workers 的多线程

typescript 复制代码
// main-thread.ts
const worker = new Worker(new URL('./my-script.worker', import.meta.url))

worker.postMessage({ data: 'process this' })

worker.onmessage = (e) => {
  console.log('Result:', e.data)
}

worker.onerror = (e) => {
  console.error('Worker error:', e.message)
}

// 完成后始终终止
worker.terminate()
typescript 复制代码
// my-script.worker.ts
self.onmessage = (e) => {
  const result = processData(e.data)
  self.postMessage(result)
}

手势

typescript 复制代码
import { GestureTypes, GestureEventData } from '@nativescript/core'

// 在代码中
view.on(GestureTypes.tap, (args: GestureEventData) => {
  console.log('Tapped!')
})

// 可用手势:
// tap, doubleTap, longPress, swipe, pan, pinch, rotation, touch

CSS 动画

css 复制代码
@keyframes fadeIn {
  from { opacity: 0; }
  to { opacity: 1; }
}

.animate-in {
  animation-name: fadeIn;
  animation-duration: 0.3s;
  animation-fill-mode: forwards;
}

可动画的 CSS 属性

  • opacity
  • background-color
  • transform: translate(x, y)
  • transform: scale(x, y)
  • transform: rotate(deg)

添加原生代码

使用 CLI 添加原生代码文件:

bash 复制代码
# Swift
ns native add swift AwesomeClass

# Objective-C
ns native add objective-c OtherClass

# Kotlin
ns native add kotlin com.company.AwesomeClass

# Java
ns native add java com.company.OtherClass

文件放置在 App_Resources/{platform}/src/ 中。

框架特定模式

纯 TypeScript

typescript 复制代码
import { Application } from '@nativescript/core'
Application.run({ moduleName: 'app-root' })

Angular

typescript 复制代码
import { Component, NO_ERRORS_SCHEMA } from '@angular/core'
import { NativeScriptCommonModule } from '@nativescript/angular'

@Component({
  selector: 'app-root',
  templateUrl: './app.html',
  imports: [NativeScriptCommonModule],
  schemas: [NO_ERRORS_SCHEMA], // NativeScript 元素必需
})
export class App {}

Vue

typescript 复制代码
import { createApp } from 'nativescript-vue'
import Home from './Home.vue'

createApp(Home).start()

Solid

tsx 复制代码
const App = () => {
  return (
    <stackLayout>
      <label text="Hello Solid!" />
    </stackLayout>
  )
}

Svelte

svelte 复制代码
<script lang="ts">
  let message = 'Hello Svelte!'
</script>

<stackLayout>
  <label text={message} />
</stackLayout>

React

tsx 复制代码
const App = () => {
  return (
    <stackLayout>
      <label text="Hello React!" />
    </stackLayout>
  )
}

配置 (nativescript.config.ts)

typescript 复制代码
import { NativeScriptConfig } from '@nativescript/core'

export default {
  id: 'org.nativescript.myapp',
  appPath: 'src',
  appResourcesPath: 'App_Resources',
  android: {
    v8Flags: '--expose_gc',
    markingMode: 'none',
  },
  ios: {
    // iOS 特定配置
  },
} as NativeScriptConfig

安全配置

NativeScript 包含安全选项,用于控制敏感运行时行为,特别是关于远程 ES 模块导入。

远程模块安全

NativeScript 支持从远程 URL 动态 import()。这在开发期间很有用,但在生产环境中存在安全影响,因为 NativeScript 代码具有对原生平台 API 的直接访问权限 (文件系统、钥匙串、网络、摄像头等)。

模式 远程模块
调试 ✅ 始终允许
生产 ❌ 默认阻止

在生产环境中启用远程模块

如果需要在生产环境中使用远程 ES 模块,请明确选择加入:

typescript 复制代码
import { NativeScriptConfig } from '@nativescript/core'

export default {
  id: 'org.nativescript.myapp',
  appPath: 'src',
  
  security: {
    allowRemoteModules: true
  }
} as NativeScriptConfig

使用白名单 (推荐)

限制为特定可信来源:

typescript 复制代码
export default {
  // ...
  security: {
    allowRemoteModules: true,
    remoteModuleAllowlist: [
      'https://cdn.yourcompany.com/modules/',
      'https://esm.sh/@yourorg/'
    ]
  }
} as NativeScriptConfig

白名单使用前缀匹配 --- 如果 URL 以任何条目开头,则允许该 URL。

安全最佳实践

  • 默认保持生产环境安全 - 除非必要,否则不要启用
  • 使用狭窄的白名单 - 特定路径,而不是宽泛域名
  • 在 URL 中固定版本 - 使用不可变、带版本的 URL
  • 切勿使用用户控制的 URL - 注入漏洞风险

有关全面的安全指南,请参阅 安全指南

常用 CLI 命令

bash 复制代码
# 创建新项目
ns create myApp --template @nativescript/template-blank

# 在设备/模拟器上运行
ns run android
ns run ios

# 在设备/模拟器上调试
ns debug android
ns debug ios

# 禁用 HMR 以进行标准实时重载
ns debug android --no-hmr
ns debug ios --no-hmr

# 构建发布版
ns build android --release
ns build ios --release

# 清理项目 (在 App_Resources 更改后运行)
ns clean

# 添加原生代码
ns native add swift MyClass
ns native add objective-c OtherAwesomeClass
ns native add kotlin com.example.MyClass
ns native add java com.company.OtherAwesomeClass

自定义视图的属性系统

typescript 复制代码
import { Property, View } from '@nativescript/core'

class MyView extends View {
  // 定义自动同步原生的属性
}

export const myProperty = new Property<MyView, string>({
  name: 'myProperty',
  defaultValue: '',
  affectsLayout: true,
})

myProperty.register(MyView)

追踪和错误处理

Trace 模块提供了超越 console.log 的强大调试和错误处理功能:

  • 控制记录哪些类别的消息
  • 通过单次调用禁用所有追踪以用于生产
  • 创建自定义追踪写入器以进行专门输出
  • 实现自定义错误处理器以进行崩溃报告

基础追踪设置

typescript 复制代码
import { Trace } from '@nativescript/core'

// 1. 设置要追踪的类别 (在 app.ts 中)
Trace.setCategories(Trace.categories.concat('MyApp', 'MyApp.Network'))

// 2. 启用追踪
Trace.enable()

// 3. 在整个应用程序中写入追踪消息
Trace.write('User logged in', 'MyApp', Trace.messageType.info)
Trace.write('API call failed', 'MyApp.Network', Trace.messageType.error)

// 4. 在生产环境中禁用
if (!__DEV__) {
  Trace.disable()
}

内置追踪类别

typescript 复制代码
Trace.categories.VisualTreeEvents  // 视图生命周期事件
Trace.categories.Layout            // 布局计算
Trace.categories.Style             // CSS/样式
Trace.categories.ViewHierarchy     // 视图树变化
Trace.categories.NativeLifecycle   // 原生平台生命周期
Trace.categories.Navigation        // Frame 导航
Trace.categories.Binding           // 数据绑定
Trace.categories.BindingError      // 数据绑定错误
Trace.categories.Error             // 一般错误
Trace.categories.Animation         // 动画事件
Trace.categories.Transition        // 页面过渡
Trace.categories.All               // 所有类别

// 将内置类别与自定义类别结合
Trace.setCategories(Trace.categories.concat('MyCategory1', 'MyCategory2'))

消息类型

typescript 复制代码
Trace.messageType.log   // 0 - 一般日志
Trace.messageType.info  // 1 - 信息
Trace.messageType.warn  // 2 - 警告
Trace.messageType.error // 3 - 错误

自定义追踪写入器

创建自定义写入器以格式化输出或将日志发送到外部服务:

typescript 复制代码
import { Trace, TraceWriter } from '@nativescript/core'

const TimestampTraceWriter: TraceWriter = {
  write(message, category, type) {
    const timestamp = new Date().toISOString()
    const typeLabel = ['LOG', 'INFO', 'WARN', 'ERROR'][type] || 'LOG'
    
    console.log(`[${timestamp}] [${typeLabel}] [${category}] ${message}`)
    
    // 可选: 发送到外部日志服务
    if (type === Trace.messageType.error) {
      sendToLogService({ timestamp, category, message, type })
    }
  }
}

// 用自定义写入器替换默认写入器
Trace.clearWriters()
Trace.addWriter(TimestampTraceWriter)

自定义错误处理器

注册自定义错误处理器以进行集中错误管理:

typescript 复制代码
import { Trace, TraceErrorHandler } from '@nativescript/core'

const errorHandler: TraceErrorHandler = {
  handlerError(err: Error) {
    if (__DEV__) {
      // 开发: 记录详细错误
      Trace.write(
        `${err.message}\n${err.stack}`,
        'unhandled-error',
        Trace.messageType.error
      )
      // 可选地重新抛出以在调试器中查看
      throw err
    } else {
      // 生产: 报告给分析/崩溃报告
      reportToCrashlytics(err)
    }
  }
}

// 注册错误处理器 (在 app.ts 中)
Trace.setErrorHandler(errorHandler)

// 将错误传递给处理器
try {
  riskyOperation()
} catch (err) {
  Trace.error(err)
}

全局应用程序错误事件

处理未捕获的错误和 Promise 拒绝:

typescript 复制代码
import { Application } from '@nativescript/core'

// 未捕获的 JavaScript 错误
Application.on(Application.uncaughtErrorEvent, (args) => {
  const error = args.error
  console.error('Uncaught error:', error.message)
  console.error('Stack:', error.stack)
  
  // 报告给崩溃服务
  reportError(error)
  
  // 可选地防止应用程序崩溃 (谨慎使用)
  // args.cancel = true
})

// 未处理的 Promise 拒绝
Application.on(Application.discardedErrorEvent, (args) => {
  console.error('Unhandled promise rejection:', args.error)
  reportError(args.error)
})

完整错误处理设置

typescript 复制代码
// app.ts - 推荐的错误处理设置
import { Application, Trace, TraceErrorHandler } from '@nativescript/core'

// 1. 设置追踪类别
Trace.setCategories(Trace.categories.concat('App', 'App.Error'))

// 2. 在开发环境中启用追踪
if (__DEV__) {
  Trace.enable()
}

// 3. 自定义错误处理器
const errorHandler: TraceErrorHandler = {
  handlerError(err: Error) {
    Trace.write(err.message, 'App.Error', Trace.messageType.error)
    
    if (!__DEV__) {
      // 发送到 Sentry, Crashlytics 等
      reportToCrashService({
        message: err.message,
        stack: err.stack,
        timestamp: Date.now()
      })
    }
  }
}
Trace.setErrorHandler(errorHandler)

// 4. 全局错误处理器
Application.on(Application.uncaughtErrorEvent, (args) => {
  Trace.error(args.error)
})

Application.on(Application.discardedErrorEvent, (args) => {
  Trace.error(args.error)
})

// 5. 启动应用程序
Application.run({ moduleName: 'app-root' })

追踪 API 快速参考

typescript 复制代码
// 类别
Trace.setCategories(categories: string)      // 设置允许的类别
Trace.addCategories(categories: string)      // 添加到现有类别
Trace.isCategorySet(category: string)        // 检查类别是否已设置

// 写入
Trace.write(message, category, type?)        // 写入追踪消息
Trace.error(error: Error | string)           // 将错误传递给处理器

// 写入器
Trace.addWriter(writer: TraceWriter)         // 添加自定义写入器
Trace.removeWriter(writer: TraceWriter)      // 移除写入器
Trace.clearWriters()                         // 移除所有写入器

// 错误处理
Trace.setErrorHandler(handler)               // 设置自定义错误处理器
Trace.getErrorHandler()                      // 获取当前错误处理器

// 启用/禁用
Trace.enable()                               // 启用追踪
Trace.disable()                              // 禁用追踪
Trace.isEnabled()                            // 检查是否已启用

性能提示

  1. 最小化布局嵌套 - 深层层次结构会损害性能
  2. 使用 GridLayout - 对于复杂布局最灵活且性能最好
  3. 避免方法绑定 - 使用属性绑定代替
  4. 使用模板选择器 - 用于条件 ListView 行
  5. 在滚动期间优先使用 hidden/visibility - 而不是 v-if/ngIf
  6. 清理资源 - 定时器、监听器、观察器
  7. 使用 Workers - 用于将繁重计算移出主线程
  8. 优化图像 - 为每种密度提供适当大小的图像

Android Drawable 密度

将图像放置在适当文件夹中:

  • App_Resources/Android/src/main/res/drawable-mdpi/ - 1x
  • App_Resources/Android/src/main/res/drawable-hdpi/ - 1.5x
  • App_Resources/Android/src/main/res/drawable-xhdpi/ - 2x
  • App_Resources/Android/src/main/res/drawable-xxhdpi/ - 3x
  • App_Resources/Android/src/main/res/drawable-xxxhdpi/ - 4x

iOS 资产目录

将图像放置在 App_Resources/iOS/Assets.xcassets/ 中,并带有适当的 @2x@3x 后缀。

创建自定义视图元素

当内置元素无法满足需求时,创建自定义原生元素。

自定义视图的组成

每个自定义 NativeScript 视图必须包含:

  • (必需) 扩展任何 NativeScript View 的类
  • (必需 ) createNativeView: 构造并返回平台原生视图
  • (可选 ) initNativeView: 创建后执行初始化
  • (可选 ) disposeNativeView: 移除时清理资源

自定义视图的项目结构

复制代码
./my-custom-view/
  ├── common.ts          # 共享逻辑
  ├── index.android.ts   # Android 实现
  ├── index.ios.ts       # iOS 实现
  └── index.d.ts         # 类型定义

基础自定义视图示例

typescript 复制代码
import { View } from '@nativescript/core'

export class CustomView extends View {
  createNativeView() {
    // iOS: 返回 UIView 实例
    // Android: 返回 android.view.View 实例
  }

  initNativeView() {
    // 初始化代码
  }

  disposeNativeView() {
    // 清理代码
  }
}

扩展现有视图

可以扩展现有的任何 NativeScript 视图:

typescript 复制代码
import { GridLayout, Label, Color, Property, booleanConverter, CoreTypes } from '@nativescript/core'

export class Checkbox extends GridLayout {
  checked = false
  defaultColor = new Color('#dddddd')
  selectionColor = new Color('#4CAF50')
  private _iconLabel: Label

  constructor() {
    super()
    this.horizontalAlignment = 'center'
    this.verticalAlignment = 'middle'

    this._iconLabel = new Label()
    this._iconLabel.text = String.fromCharCode(0xf764) // 圆形图标
    this._iconLabel.className = 'mat' // Material Design Icons 字体
    this._iconLabel.color = this.defaultColor
    this.addChild(this._iconLabel)
  }

  toggle() {
    this.checked = !this.checked
    this._iconLabel.text = this.checked 
      ? String.fromCharCode(0xf5e0)  // 勾选标记
      : String.fromCharCode(0xf764)  // 圆形
    this._iconLabel.color = this.checked ? this.selectionColor : this.defaultColor
  }
}

定义可自定义属性

typescript 复制代码
import { Property, booleanConverter, Color } from '@nativescript/core'

const checkedProperty = new Property<Checkbox, boolean>({
  name: 'checked',
  defaultValue: false,
  valueConverter: booleanConverter,
})

const sizeProperty = new Property<Checkbox, number>({
  name: 'size',
  defaultValue: 24,
  affectsLayout: true,
})

const selectionColorProperty = new Property<Checkbox, Color>({
  name: 'selectionColor',
  equalityComparer: Color.equals,
  valueConverter: (v) => new Color(v),
})

// 实现 setNative 处理器
export class Checkbox extends GridLayout {
  [checkedProperty.setNative](value: boolean) {
    this.checked = value
    this._updateVisual()
  }

  [sizeProperty.setNative](value: number) {
    this._iconLabel.fontSize = value
  }

  [selectionColorProperty.setNative](value: Color) {
    this.selectionColor = value
  }
}

// 注册属性
checkedProperty.register(Checkbox)
sizeProperty.register(Checkbox)
selectionColorProperty.register(Checkbox)

按框架注册自定义元素

TypeScript (XML)

xml 复制代码
<Page xmlns:custom="./checkbox">
  <StackLayout>
    <custom:Checkbox checked="true" size="32" />
  </StackLayout>
</Page>

Angular

typescript 复制代码
import { registerElement } from '@nativescript/angular'
import { Checkbox } from './checkbox'
registerElement('Checkbox', () => Checkbox)

Vue

typescript 复制代码
import { registerElement } from 'nativescript-vue'
import { Checkbox } from './checkbox'
registerElement('Checkbox', () => Checkbox)

Svelte

typescript 复制代码
import { registerNativeViewElement } from '@nativescript-community/svelte-native/dom'
import { Checkbox } from './checkbox'
registerNativeViewElement('checkbox', () => Checkbox)

React

typescript 复制代码
import { registerElement } from 'react-nativescript'
import { Checkbox } from './checkbox'
registerElement('checkbox', () => Checkbox)

Solid

typescript 复制代码
import { registerElement } from 'dominative'
import { Checkbox } from './checkbox'
registerElement('checkbox', Checkbox)

自定义现有视图元素

扩展现有元素以自定义行为:

typescript 复制代码
// index.ios.ts - 使用更大字体的自定义 ListPicker
import { ListPicker } from '@nativescript/core'

export class CustomListPicker extends ListPicker {
  private _delegate: ListPickerDelegateImpl

  initNativeView() {
    this._delegate = ListPickerDelegateImpl.initWithOwner(new WeakRef(this))
    this.nativeViewProtected.delegate = this._delegate
  }
}

@NativeClass()
class ListPickerDelegateImpl extends NSObject implements UIPickerViewDelegate {
  static ObjCProtocols = [UIPickerViewDelegate]
  private _owner: WeakRef<ListPicker>

  static initWithOwner(owner: WeakRef<ListPicker>): ListPickerDelegateImpl {
    const delegate = ListPickerDelegateImpl.new() as ListPickerDelegateImpl
    delegate._owner = owner
    return delegate
  }

  pickerViewViewForRowForComponentReusingView(pickerView: UIPickerView, row: number): UIView {
    const owner = this._owner?.deref()
    const label = UILabel.new()
    label.font = UIFont.systemFontOfSize(26) // 自定义字体大小
    label.text = owner?.items[row]
    label.textAlignment = NSTextAlignment.Center
    return label
  }
}

createNativeView 平台示例

typescript 复制代码
// iOS
createNativeView() {
  const config = WKWebViewConfiguration.new()
  return new WKWebView({ frame: CGRectZero, configuration: config })
}

// Android  
createNativeView() {
  return new android.webkit.WebView(this._context)
}

资源

https://docs.nativescript.org/assets/agentic/NATIVESCRIPT.md