{ // 本例是一个比较复杂的,带有循环和条件渲染的,以及有各种事件处理函数的页面 version: '1.0.0', componentsMap: [ { componentName: 'View', package: 'rax-view', version: '^1.0.0', destructuring: false, exportName: 'View', }, { componentName: 'Text', package: 'rax-text', version: '^1.0.0', destructuring: false, exportName: 'Text', }, { componentName: 'Image', package: 'rax-image', version: '^1.0.0', destructuring: false, exportName: 'Image', }, { componentName: 'Page', package: 'rax-view', version: '^1.0.0', destructuring: false, exportName: 'Page', }, ], componentsTree: [ { componentName: 'Page', fileName: 'home', meta: { router: '/', }, state: { clickCount: 0, user: { name: '张三', age: 18, avatar: 'https://gw.alicdn.com/tfs/TB1Ui9BMkY2gK0jSZFgXXc5OFXa-50-50.png' }, orders: [ { title: '【小米智能生活】米家扫地机器人家用全自动扫拖一体机拖地吸尘器', price: 1799, coverUrl: 'https://gw.alicdn.com/tfs/TB1dGVlRfb2gK0jSZK9XXaEgFXa-258-130.png', }, { title: '【限时下单立减】Apple/苹果 iPhone 11 4G全网通智能手机正品苏宁易购官方旗舰店苹果11', price: 4999, coverUrl: 'https://gw.alicdn.com/tfs/TB18gdJddTfau8jSZFwXXX1mVXa-1298-1202.png', }, ], }, props: {}, lifeCycles: { didMount: { type: 'JSExpression', value: 'function didMount(){\n this.utils.Toast.show(`Hello ${this.state.user.name}!`);\n}', }, willUnmount: { type: 'JSExpression', value: 'function didMount(){\n this.utils.Toast.show(`Bye, ${this.state.user.name}!`);\n}', }, }, methods: { hello: { type: 'JSExpression', value: 'function hello(){\n this.utils.Toast.show(`Hello ${this.state.user.name}!`);\n console.log(`Hello ${this.state.user.name}!`); }', }, }, dataSource: { list: [ { id: 'urlParams', type: 'urlParams', }, // 示例数据源:https://shs.xxx.com/mock/1458/demo/user { id: 'user', type: 'fetch', options: { method: 'GET', uri: 'https://shs.xxx.com/mock/1458/demo/user', isSync: true, }, dataHandler: { type: 'JSExpression', value: 'function (response) {\nif (!response.success){\n throw new Error(response.message);\n }\n return response.data;\n}', }, }, // 示例数据源:https://shs.xxx.com/mock/1458/demo/orders { id: 'orders', type: 'fetch', options: { method: 'GET', uri: { type: 'JSExpression', value: 'this.state.user.ordersApiUri', }, isSync: true, }, dataHandler: { type: 'JSExpression', value: 'function (response) {\nif (!response.success){\n throw new Error(response.message);\n }\n return response.data.result;\n}', }, }, ], dataHandler: { type: 'JSExpression', value: 'function (dataMap) {\n console.info("All datasources loaded:", dataMap);\n}', }, }, children: [ { componentName: 'View', children: [ { componentName: 'Text', props: {}, children: 'Demo data source logic', }, ], }, { componentName: 'View', children: [ { componentName: 'Text', props: {}, children: '=== User Info: ===', }, ], }, { componentName: 'View', condition: { type: 'JSExpression', value: 'this.state.user', }, props: { style: { flexDirection: 'row' }, }, children: [ { componentName: 'Image', props: { source: { uri: { type: 'JSExpression', value: 'this.state.user.avatar', }, }, style: { width: '32px', height: '32px', }, }, }, { componentName: 'View', props: { onClick: { type: 'JSExpression', value: 'this.hello', }, }, children: [ { componentName: 'Text', children: { type: 'JSExpression', value: 'this.state.user.name', }, }, { componentName: 'Text', children: [ { type: 'JSExpression', value: 'this.state.user.age', }, '岁', ], }, ], }, ], }, { componentName: 'View', children: [ { componentName: 'Text', props: {}, children: '=== Orders: ===', }, ], }, { componentName: 'View', loop: { type: 'JSExpression', value: 'this.state.orders', }, loopArgs: ['order', 'index'], props: { style: { flexDirection: 'row' }, onClick: { type: 'JSExpression', value: 'function(){ this.utils.recordEvent(`CLICK_ORDER`, this.order.title) }', }, }, children: [ { componentName: 'View', children: [ { componentName: 'Image', props: { source: { uri: { type: 'JSExpression', value: 'this.order.coverUrl', }, }, style: { width: '80px', height: '60px', }, }, }, ], }, { componentName: 'View', children: [ { componentName: 'Text', children: { type: 'JSExpression', value: 'this.order.title', }, }, { componentName: 'Text', children: { type: 'JSExpression', value: 'this.utils.formatPrice(this.order.price, "元")', }, }, ], }, ], }, { componentName: 'View', props: { onClick: { type: 'JSExpression', value: 'function (){ this.setState({ clickCount: this.state.clickCount + 1 }) }', }, }, children: [ { componentName: 'Text', children: [ '点击次数:', { type: 'JSExpression', value: 'this.state.clickCount', }, '(点击加 1)', ], }, ], }, { componentName: 'View', children: [ { componentName: 'Text', props: {}, children: '操作提示:', }, { componentName: 'Text', props: {}, children: '1. 点击会员名,可以弹出 Toast "Hello xxx!"', }, { componentName: 'Text', props: {}, children: '2. 点击订单,会记录点击的订单信息,并弹出 Toast 提示', }, { componentName: 'Text', props: {}, children: '3. 最下面的【点击次数】,点一次应该加 1', }, ], }, ], }, ], utils: [ // 可以直接定义一个函数 { name: 'formatPrice', type: 'function', content: { type: 'JSExpression', value: 'function formatPrice(price, unit) { return Number(price).toFixed(2) + unit; }', }, }, // 在 utils 里面也可以用 this 访问当前上下文: { name: 'recordEvent', type: 'function', content: { type: 'JSExpression', value: 'function recordEvent(eventName, eventDetail) { \n this.utils.Toast.show(`[EVENT]: ${eventName} ${eventDetail}`);\n console.log(`[EVENT]: ${eventName} (detail: %o) (user: %o)`, eventDetail, this.state.user); }', }, }, // 也可以直接从 npm 包引入 (下例等价于 `import moment from 'moment';`) { name: 'moment', type: 'npm', content: { package: 'moment', version: '*', exportName: 'moment', }, }, // 可以引入子目录(下例等价于 `import clone from 'lodash/clone';`) { name: 'clone', type: 'npm', content: { package: 'lodash', version: '*', exportName: 'clone', destructuring: false, main: '/clone', }, }, { name: 'Toast', type: 'npm', content: { package: 'universal-toast', version: '^1.2.0', exportName: 'Toast', // TODO: 这个 exportName 是否可以省略?省略后默认是上一层的 name? }, }, ], css: 'page,body{\n width: 750rpx;\n overflow-x: hidden;\n}', config: { sdkVersion: '1.0.3', historyMode: 'hash', targetRootID: 'root', }, meta: { name: 'Rax App Demo', git_group: 'demo-group', project_name: 'demo-project', description: '这是一个示例应用', spma: 'spmademo', creator: '张三', }, }