App package for real machine debugging.Node environment, use npm i or yarn to install the dependencies.Note: If the running result of the developer tool is inconsistent with the running result of the real machine, please refer to the debugging operation of the real machine.
❣️ Basic TYML, TYSS, and related syntax of Smart MiniApp.
❣️ Smart MiniApp page, component, combination development.
❣️ Introduction and usage of some APIs.
❣️ The built-in Smart MiniApp extension capability is supplemented, including theme adaptation, multi-language, etc.
❣️ Other extension capabilities, including component library, gesture library, chart library, animation library, etc.
├── project.tuya.json
├── app.js
├── app.json
├── app.tyss
├── assets
│ └── images
│ └── tab
│ └─ component.png
├── i18n
│ └── strings.json
├── components
│ └── foo
│ ├── index.js
│ ├── index.json
│ ├── index.tyml
│ └── index.tyss
├── pages
│ └── page
│ ├── index.js
│ ├── index.json
│ ├── index.tyml
│ └── index.tyss
├── theme.json
├── package.json
└── node_modules
index.less file is required, index.tyss only supports CSS.data corresponding to PageMustache syntax (double curly brackets) to wrap variables, which can act on content, component properties (required within double quotes), control properties (required within double quotes), keywords (required within double quotes) within double quotation marks), operations, ternary operations, arithmetic operations, logical judgments, string operations, etc. See more.<!--tyml-->
<view> {{message}} </view>
// page.js
Page({
data: {
message: "Hello MINA!",
},
});
<!--tyml-->
<view ty:for="{{array}}"> {{item}} </view>
// page.js
Page({
data: {
array: [1, 2, 3, 4, 5],
},
});
<!--tyml-->
<view ty:if="{{view == 'WEBVIEW'}}"> WEBVIEW </view>
<view ty:elif="{{view == 'APP'}}"> APP </view>
<view ty:else="{{view == 'MINA'}}"> MINA </view>
// page.js
Page({
data: {
view: "MINA",
},
});
<!--tyml-->
<template name="staffName">
<view>
FirstName: {{firstName}}, LastName: {{lastName}}
</view>
</template>
<template is="staffName" data="{{...staffA}}"></template>
<template is="staffName" data="{{...staffB}}"></template>
<template is="staffName" data="{{...staffC}}"></template>
// page.js
Page({
data: {
staffA: { firstName: "Hulk", lastName: "Hu" },
staffB: { firstName: "Shang", lastName: "You" },
staffC: { firstName: "Gideon", lastName: "Lin" },
},
});
##Apps
Register the Miniapp. Accepts an Object parameter, which specifies the Miniapp's lifecycle callback, etc.
App() ** must be called in ** app.js **, must be called and can only be called once. Otherwise, unexpected effects will occur. **
onLaunch: Triggered when the Miniapp initialization is completed, and only triggered once globally.onShow: Triggered when the Miniapp starts or enters the foreground display from the background.onHide: Triggered when the Miniapp enters the background from the foreground.onError: Triggered when a script error or API call error occurs in the Miniapp.onPageNotFound: Triggered when the page to be opened by the Miniapp does not exist.onThemeChange: Triggered when the system switches themes.Sample code
App({
onLaunch(options) {
// Do something initial when launch.
},
onShow(options) {
// Do something when show.
},
onHide() {
// Do something when hide.
},
onError(msg) {
console.log(msg);
},
globalData: "I am global data",
});
App instance of the Miniapp through the getApp method in js (page or component).Sample code
//other.js
var appInstance = getApp();
console.log(appInstance.globalData); // I am global data
##Page
Object type parameter, which specifies the initial data of the page, lifecycle callbacks, event handlers, etc.data is the initial data used by the first render of the page.
Sample code
<view>{{text}}</view>
<view>{{array[0].msg}}</view>
Page({
data: {
text: "init data",
array: [{ msg: "1" }, { msg: "2" }],
},
});
Page.setData. setData is asynchronous.Sample code
<view bind:tap="viewTap">{{num}}</view>
Page({
data: {
num: 0,
},
viewTap: function () {
this.setData({
num: this.data.num + 1,
});
},
});
onLoad: Fired when the page loads. A page will only be called once, and the parameters in the path to open the current page can be obtained in the parameters of onLoad.onShow: Triggered when the page is displayed/switched to the foreground.onReady: Triggered when the page's initial rendering is complete. A page will only be called once, indicating that the page is ready to interact with the view layer.onHide: Triggered when the page is hidden/cut into the background.onUnload: Triggered when the page is unloaded.onPullDownRefresh: Listen to user pull down refresh events.onReachBottom: Listen to the user's bottom-up event.Sample code
//index.js
Page({
data: {
text: "This is page data.",
},
onLoad: function (options) {
// Do some initialize when page load.
},
onShow: function () {
// Do something when page show.
},
onReady: function () {
// Do something when page ready.
},
onHide: function () {
// Do something when page hide.
},
onUnload: function () {
// Do something when page close.
},
onPullDownRefresh: function () {
// Do something when pull down.
},
onReachBottom: function () {
// Do something when page reach bottom.
},
});
Object to describe the logical interaction behavior of the component. See more.// file /components/foo/index.js
Component({
options: Object,
properties: Object,
observers: Object,
data: Object,
methods: Object,
behaviors: Array,
lifetimes: Object,
pageLifetimes: Object,
relations: Array,
});
type. See more.properties can listen for changes in property values through observer().Sample code
Component({
properties: {
myName: {
type: String,
value: "smart",
observer: function (newValue, oldValue) {
// do something
},
},
},
});
properties) and data (data) fields. See more.Component({
observers: {
"value1, value2": function (value1, value2) {
// trigger when this.setData corresponds to data
},
"some.subfield": function (subfield) {
// Triggered when this.data.some.subfield is set using setData
// (Other than that, setting this.data.some with setData will also fire)
subfield === this.data.some.subfield;
},
"arr[12]": function (arr12) {
// Triggered when this.data.arr[12] is set using setData
// (Other than that, setting this.data.arr with setData will also fire)
arr12 === this.data.arr[12];
},
"some.field.**": function (field) {
// Triggered when this.data.some.field itself or any sub-data fields under it are set using setData
// (Other than that, setting this.data.some with setData will also fire)
field === this.data.some.field;
},
"**": function () {
// every time setData fires
},
},
});
page.<view>{{name}}: {{age}}</view>
Component({
properties: {
'name': {
type: String,
value: 'smart'
}
}
data: { age: 18 },
});
created: Executed when the component instance has just been created.attached: Executed when the component instance enters the page node tree.ready: Executed after the component is laid out in the view layer.moved: Executed when the component instance is moved to another location in the node tree.detached: Executed when the component instance is removed from the page node tree.error: Executed whenever a component method throws an error.Sample code
Component({
lifetimes: {
attached: function () {
// Executed when the component instance enters the page node tree
},
},
});
show: Executed when the page the component is on is shown.hide: Executed when the page the component is on is hidden.resize: Executed when the size of the page where the component is located changes.Sample code
Component({
pageLifetimes: {
show: function () {
// Executed when the page where the component is located is displayed
},
},
});
There are two common communication methods between components.
TYML data binding: used to set data from the parent component to the specified property of the child component, only JSON compatible data can be set.<!-- When the custom component triggers the "myevent" event, the "onMyEvent" method is called -->
<component-tag-name bind:myevent="onMyEvent" />
Page({
onMyEvent: function (e) {
e.detail; // The detail object provided when the custom component triggers the event
},
});
<!-- in custom component -->
<button bind:tap="onTap">Clicking this button will trigger the "myevent" event</button>
Component({
properties: {},
methods: {
onTap: function () {
var myEventDetail = {}; // detail object, provided to the event listener function
var myEventOption = {}; // option to trigger event
this.triggerEvent("myevent", myEventDetail, myEventOption);
},
},
});
slot node can be included in a component's tyml to host the tyml structure provided by the component user.tyml supports one slot or multiple slots.slots in a component's tyml, use different names to distinguish them.slot property to insert nodes into different slots.<!-- Component template -->
<view class="wrapper">
<slot name="before"></slot>
<view>here are the internal details of the component</view>
<slot name="after"></slot>
</view>
<!-- The page template of the referenced component -->
<view>
<component-tag-name>
<!-- This part of the content will be placed in the position of the component <slot name="before"> -->
<view slot="before">here is the content inserted into the component slot name="before"</view>
<!-- This part of the content will be placed in the position of the component <slot name="after"> -->
<view slot="after">here is the content inserted into the component slot name="after"</view>
</component-tag-name>
</view>
tyss. Except in the following two cases: app.tyss or the page's tyss to specify styles directly. These selectors affect the page and all components. Normally this is not recommended practice.iconfont in a project, since the style file of iconfont is global, you should turn off style isolation when you need to use iconfont in custom components.Component({
options: {
styleIsolation: "isolated",
},
});
isolated: Enable style isolation (default).apply-shared: The style of the page tyss will affect the custom component, but the style specified in the custom component tyss will not affect the page.shared: The style of the page tyss will affect the custom component, and the style specified in the custom component tyss will also affect the page and other settings.Sample code
<!-- component custom-component.tyml -->
<text class="red-text">The color of this text is determined by the style definitions in `app.tyss` and the page `tyss`</text>
/* app.tyss */
.red-text {
color: red;
}
/* component custom-component.js */
Component({
options: {
addGlobalClass: true,
},
});
url should be an absolute path.ty.navigateTo API documentation<navigator open-type="navigateTo"/>
ty.redirectTo API documentation<navigator open-type="redirectTo"/>
ty.navigateBack API documentation<navigator open-type="navigateBack"/>
ty.switchTab API documentation<navigator open-type="switchTab"/>
ty.reLaunch API documentation<navigator open-type="reLaunch"/>
url, and the parameters can be obtained in the life cycle.Sample code
ty.navigateTo({
url: 'test?id=1',
events: {
// Add a listener for the specified event to get the data sent from the opened page to the current page
acceptDataFromOpenedPage: function(data) {
console.log(data)
},
someEvent: function(data) {
console.log(data)
}
...
},
success: function(res) {
// Send data to the opened page through eventChannel
res.eventChannel.emit('acceptDataFromOpenerPage', { data: 'test' })
}
})
//test.js
Page({
onLoad: function (option) {
console.log(option.query);
const eventChannel = this.getOpenerEventChannel();
eventChannel.emit("acceptDataFromOpenedPage", { data: "test" });
eventChannel.emit("someEvent", { data: "test" });
// Listen to the acceptDataFromOpenerPage event, and get the data sent from the previous page to the current page through eventChannel
eventChannel.on("acceptDataFromOpenerPage", function (data) {
console.log(data);
});
},
});
The API provided by the basic library, including basic/application-level events, interface animation related, map, audio and video, canvas, interface and other capabilities. View more.
TTT capability is a kind of Tuya's ability to give basic capabilities to businesses (developers), to achieve quick access to Tuya ecology, and to achieve interconnection. TTT related API is the capability provided for TTT.TTT capability is the minimum set of public capabilities that all App of Tuya series must integrate. These capabilities are provided to Miniapp, RN, H5, etc. through plug-ins, so that cross-end business can run in any Tuya series App (IoT device).TTT capability on the terminal is the constraint and guarantee for the interconnection and interoperability of software capabilities on the user terminal.Note: To use some API, such as navigateTo, showToast, showModal, you need to integrate the corresponding Kit plugin capability.
/assets.iconfont, utils, etc.The multi-language Smart MiniApp has been integrated into the framework, and there is no need to introduce additional packages or methods.
Multilingual key values need to be added in the Mini Program Developer Platform. After selecting the corresponding Mini Program, click Multilingual Management on the sidebar.
<text>{{I18n.t('TYTimer_day2')}}</text>
<text>{{i18n.t('TYTimer_day2')}}</text>
console.log(I18n.t("TYTimer_day2"));
console.log(i18n.t("TYTimer_day2"));
tyss/less, it is supported to switch themes through the selector theme='dark' | 'light'.css variables.:root {
--main-bg-color: rgb(255, 255, 255); /* light background */
--main-text-color: rgb(54, 54, 54); /* dark text */
}
:root[theme="dark"] {
--main-bg-color: rgb(47, 58, 68); /* dark background */
--main-text-color: rgb(197, 197, 197); /* light text */
}
Dialog, Loading, Tabs, Cell, etc.npm, the npm package name is @tuya-miniapp/miniapp-components-plususingComponents configuration field in the json file of the page, usingComponents must be the full path.tyml of the corresponding page.// index.json
"usingComponents": {
"mpdialog": "@tuya-miniapp/miniapp-components-plus/dialog/index"
}
<mpdialog title="test" show="{{true}}" bind:buttontap="tapDialogButton" buttons="{{[{text: 'Cancel'}, {text: 'Confirm'}]}}">
<view>test content</view>
</mpdialog>
form form component, which will input the user input in the component textarea, checkbox-group, radio-group, input, picker, switch, slider Submit. See more form usage.form in the outermost layer and add bind:submit and bind:reset attributes.Property Name | Type | Default Value | Required | Description |
bind:submit | eventhandle | - | No | Carry the data in the form to trigger the submit event, and you can get the value of the form item corresponding to the name in event.detail |
bind:reset | eventhandle | - | no | reset event is fired when the form is reset |
Sample code
<form bind:submit="handleSubmit" bind:reset="handleReset">
<switch name="switch"></switch>
<button form-type="submit" data-info="Submit button" type="primary" class="submit-btn">Submit</button>
<button form-type="reset" data-info="reset button" class="reset-btn">reset</button>
</form>
Page({
data: {
resultData: [
{
name: "switch",
value: "",
},
],
},
handleSubmit(ev) {
const value = ev.detail.value;
console.log(value);
},
handleReset(ev) {
const value = ev.detail.value;
console.log(value);
},
});
More sample code sample code experience effect.
We have provided several templates for developers to learn