Native CrossPlatform Mobile Application Development with Native ScriptVue
Native Cross-Platform Mobile Application Development with ������������������� Native. Script-Vue https: //bit. ly/nativescript_vue �������
������� Mobile App 1. Native (����������� ) a. Android: Java, Kotlin b. i. OS: Swift 2. Native Cross Platform (������������� ) a. b. c. d. Java. Script: Native. Script, React Native, Weex Dot. Net: Xamarin Dart: Flutter C/C++: Qt 3. Hybrid Cross Platform (��� Web. View) a. Apache Cordova b. Appcelerator c. Adobe AIR
1. ����� Native. Script
���������� ● Node. js ○ ○ ● https: //nodejs. org/ 10. 15. 3 LTS Java Standard Edition ○ ○ https: //www. oracle. com/technetwork/javase/downloads/index. html Java SE 8 u 211 / Java SE 8 u 212 (JDK) ● Android Studio (SDK) ○ https: //developer. android. com/studio
����� 1. ������� Native. Script a. npm i -g nativescript 2. ���� Android Studio ����� SDK a. Configure > SDK Manager 3. ������� environment a. JAVA_HOME=C: Program FilesJavajdk 1. 8. 0_172 b. ANDROID_HOME=C: Androidandroid-sdk 4. ��������� a. tns doctor 5. ������ Android ��� USB Driver
������� Environment Computer > Properties > Advanced system settings > Advanced > Environment Varaibles. . .
������� Environment
�������� Android 1. ���� USB Debugging ����� a. Settings > About phone > ��� Build Number 7 ����� b. Settings > Developer options > ���� USB Debugging 2. ������� USB Driver ��� PC a. ���� USB Data �������� PC b. �� driver ����� c. ��������� Allow 3. ������ adb a. adb devices
tns doctor
Driver adb ����� ● https: //adb. clockworkmod. com/ ● https: //developer. android. com/studio/run/oem-usb#Drivers ● Samsung https: //developer. samsung. com/galaxy/others/android-usb-driver-for-windows ● Huawei https: //consumer. huawei. com/en/support/faqs/detail/? id=6630
������ ● ����� app ����� tns create ○ ○ ● tns create Hello. World 1 tns create Hello. World 2 --vue run app ����� tns run android ���� tns preview ○ ○ tns preview tns run android --bundle
2. ������� Native. Script
Vue. js ���� app. js /app/app. js import Vue from "nativescript-vue"; import Home from ". /components/Home"; new Vue({ template: ` render: h => h('Frame', [h(Home)]) <Frame> <Home /> </Frame>`, components: { Home } }). $start(); }). $start()
Native. Script Playground ● ���������������������������������� � ● ��������� app �� android/ios �������� ○ ○ Play https: //play. google. com/store/apps/details? id=org. nativescript. play Preview https: //play. google. com/store/apps/details? id=org. nativescript. preview ● ������� https: //play. nativescript. org/? template=play-vue ���� scan qr ������������
����� 2 ������ Native. Script Playground ● ���� 30 ���� ● ������� Native. Script Play ��� Native. Script Preview ���� ● ���� https: //play. nativescript. org/
ECMAScript ● ● ● ������ Java. Script arrow function promise async/await for of
Arrow Function ● ● set. Timeout(function() { console. log('ok') }, 1000) rows. map(function(row) { return row. code }) ● ● set. Timeout(() => { console. log('ok') }, 1000) rows. map((row) => { return row. code }) rows. map(row => row. code)
Promise ● ● ���� callback ��������● ����� error ������ catch ������� ● call. A(). then(call. B). then(call. C). catch(call. D). then(call. E). catch(call. F) call. A(). then(call. B, call. C). then(call. D, call. E). catch(call. F). then(call. G)
async/await ● function get. Data(url) { return fetch(url). then(res => res. json()). then(json => json. status) } ● async function get. Data(url) { let res = await fetch(url) let json = await res. json() return json. status }
for of ● for (let i = 0; i < list. length; i++) { let item = list[i] // } ● for (let item of list) { }
������������ ● http: //prototypingtools. co/ ● Online ○ ● Mocking. Bot https: //mockingbot. in Desktop App ○ Adobe XD https: //www. adobe. com/products/xd. html ● Prototype on Paper ○ ○ Prott https: //play. google. com/store/apps/details? id=com. prottapp. android Marvel https: //play. google. com/store/apps/details? id=com. marvelapp
������� components/Home. Page. vue <template> <Page>. . . </Page> </template> <script> // javascript </script> <style> /* css */ </style>
����������� <Frame> <Page> <Action. Bar title="Home" class="action-bar" /> <Scroll. View> <!-- Page content --> </Scroll. View> </Page> </Frame>
Stack. Layout ● https: //nativescript-vue. org/en/docs/elements/layouts/stack-layout/ ● Stack. Layout ○ ○ orientation ■ vertical ������� (default) ■ horizontal ������ child: horizontal. Alignment ■ left, center, right, top, bottom <Stack. Layout orientation="horizontal" background. Color="#3 c 495 e"> <Label text="first" width="70" background. Color="#43 b 883"/> <Label text="second" width="70" background. Color="#289062"/> <Label text="third" width="70" background. Color="#1 c 6 b 48"/></Stack. Layout>
Dock. Layout ● https: //nativescript-vue. org/en/docs/elements/layouts/dock-layout/ ● Dock. Layout ○ ○ stretch. Last. Child = true, false ���� child ������� child: dock = left, right, top, bottom <Dock. Layout stretch. Last. Child="false" background. Color="#3 c 495 e"> <Label text="left" dock="left" width="40" background. Color="#43 b 883"/> <Label text="top" dock="top" height="40" background. Color="#289062"/> <Label text="right" dock="right" width="40" background. Color="#43 b 883"/> <Label text="bottom" dock="bottom" height="40" background. Color="#289062"/> </Dock. Layout>
Grid. Layout ● https: //nativescript-vue. org/en/docs/elements/layouts/grid-layout/ ● rows, cols ������� ○ ○ ������ = ����� * = ���� auto = ������� * = ��������� ● cols="3*, 5*" ������� 3: 5 ● child: row, col ����� child �� grid ● child: row. Span, col. Span ����� row, column ����� span
Grid. Layout <Grid. Layout columns="40, auto, *" rows="40, auto, *" background. Color="#3 c 495 e"> <Label text="0, 0" row="0" col="0" background. Color="#43 b 883"/> <Label text="0, 1" row="0" col="1" col. Span="2" background. Color="#1 c 6 b 48"/> <Label text="1, 0" row="1" col="0" row. Span="2" background. Color="#289062"/> <Label text="1, 1" row="1" col="1" background. Color="#43 b 883"/> <Label text="1, 2" row="1" col="2" background. Color="#289062"/> <Label text="2, 1" row="2" col="1" background. Color="#1 c 6 b 48"/> <Label text="2, 2" row="2" col="2" background. Color="#43 b 883"/> </Grid. Layout>
Wrap. Layout <Wrap. Layout background. Color="#3 c 495 e"> <Label text="first" width="30%" height="30%" background. Color="#43 b 883"/> <Label text="second" width="30%" height="30%" background. Color="#1 c 6 b 48"/> <Label text="third" width="30%" height="30%" background. Color="#289062"/> <Label text="fourth" width="30%" height="30%" background. Color="#289062"/> </Wrap. Layout>
������� Action Bar Action. Bar ���������������� ● Action. Bar ● Action. Item ● Navigation. Button title Navigation. Button Action. Item
Action. Bar ● https: //nativescript-vue. org/en/docs/elements/action-bar/ ● Props ○ ○ title = ������� android. icon = ����� res: //icon android. icon. Visibility = true, false flat = true, false
Action. Item ● https: //nativescript-vue. org/en/docs/elements/action-bar/action-item/ ● Props ○ ○ ios. system. Icon ����� https: //developer. apple. com/library/ios/documentation/UIKit/Reference/UIBar. Button. Item_Class /#//apple_ref/c/tdef/UIBar. Button. System. Item android. system. Icon ����� https: //developer. android. com/guide/topics/resources/drawableresource ios. position = left, right android. position ■ action. Bar ������ action bar ■ popup �����. . . ■ action. Bar. If. Room ����� action bar ����������. . .
Navigation. Button ● https: //nativescript-vue. org/en/docs/elements/action-bar/navigation-button/ ● Props ○ ○ text = ������ (����� i. OS) android. system. Icon = icon (����� Android)
vue. js: data ��������� component <script> <template> export default { <Page> data() { return { <Stack. Layout> <Label text="Username: " /> user: "My. User 1", <Text. Field : text="user" /> pass: "My. Pass 1", <Label text="Password: " /> } <Text. Field : text="pass" /> }, </Stack. Layout> created() { set. Interval(() => { this. user = this. user + "*" }, 5000) }, } </script> </Page> </template>
vue. js: v-model ������ 2 ������ <script> <template> export default { <Page> data() { return { text: "Hello world", } <Stack. Layout> <Label text="Text 1: " /> <Text. Field : text="text" /> <Label text="Text 2: " /> }, <Text. Field v-model="text" /> } <Label : text="text" /> </script> </Stack. Layout> </Page> </template>
vue. js: computed ������ <script> <template> export default { <Page> data() { return { text: "Hello world", } <Stack. Layout> <Label text="Text: " /> <Text. Field v-model="text" /> <Label : text="'len=' + text. length" /> }, <Label : text="'len=' + text. Len" /> computed: { text. Len() { return this. text. length }, }, } </script> </Stack. Layout> </Page> </template>
Vue. js: methods export default { data() { return { text: "Hello world", busy: false, } methods: { do. Save() { this. busy = true set. Timeout(() => { this. busy = false }, 1000) }, } <Page> <Stack. Layout> <Label text="Text: " /> <Text. Field v-model="text" }, <template> : editable="!busy" /> <Button text="SAVE" @tap="do. Save" /> <Activity. Indicator : busy="busy" /> </Stack. Layout> </Page> </template>
Vue. js: lifecycle events ● ● ● ● before. Create created before. Mount mounted before. Update updated before. Destroy destroyed
List. View ● ● https: //nativescriptvue. org/en/docs/elements/components/list -view/ Props ○ ○ ○ ● @item. Tap="on. Item. Tap"> <v-template> <Label : text="item. text" /> </v-template> <v-template if="$odd"> <Label : text="item. text" color="red" /> </v-template> </List. View> Events ○ ● for ■ item in list. Of. Items ■ (item, index) in list. Of. Items items separator. Color <List. View for="item in list. Of. Items" item. Tap Methods ○ refresh on. Item. Tap(event) { console. log(event. index) console. log(event. item) }
��������� List. View (1/2) <template> <Page> <Stack. Layout orientation="horizontal"> <List. View for="item in students" @item. Tap="on. Student. Tap"> <v-template> <Stack. Layout orientation="horizontal"> <Text. Field v-model="name" /> <Label : text="item. name" /> <Button text="Add" @tap="add. Student"/> <Button text="Remove" </Stack. Layout> @tap="on. Student. Remove($index)"/> </Stack. Layout> </v-template> </List. View> </Stack. Layout> </Page> </template>
��������� List. View (2/2) <script> methods: { export default { add. Student() { data() { this. students. add({ name: this. name }) return { }, name: '', on. Student. Tap(evt) { students: [ console. log(evt. item, evt. index) { name: 'Name 1' }, ], on. Student. Remove(idx) { } this. students. splice(idx, 1) }, } } </script>
��������� ● https: //nativescript-vue. org/en/docs/routing/manual-routing/ ● $navigate. To(Component, options) ○ this. $navigate. To(About. Page) ● $navigate. Back(options, backstack. Entry = null) ○ this. $navigate. Back() ● $show. Modal(Component) ○ ○ this. $show. Model(Student. Detail. Page) this. $modal. close() ����
������������ Student. List. Page. vue ������� Student. Detail. Page. vue <Stack. Layout orientation="horizontal"> <Label : text="item. name" /> <Button text="Detail" @tap="view(item)" /> </Stack. Layout> <script> export default { props: { student: { type: Object, default() { return {} }, }, }, // props } </script> view(student) { this. $navigate. To(Student. Detail. Page, { props: { student: student, } }) },
Action. Dialog action("Choose one!", "Or cancel. . . ", ["cheese", "wine"]). then(result => { console. log(result); }); let result = await action("Choose one!", "Or cancel. . . ", ["cheese", "wine"]); console. log(result);
Alert. Dialog await alert('Hello!') console. log("Alert dialog closed") await alert({ title: "Alert", message: "Hello!", ok. Button. Text: "OK" }) console. log("Alert dialog closed")
Confirm. Dialog let result = await confirm("Are you ready? ") console. log(result); let result = await confirm({ title: "Confirm", message: "Are you ready? ", ok. Button. Text: "OK", cancel. Button. Text: "Cancel" }) console. log(result)
Login. Dialog let result = await login("Please login", "Username", "Password") console. log(result, result. user. Name, result. password) let result = await login({ title: "Login", message: "Please login", ok. Button. Text: "OK", cancel. Button. Text: "Cancel", user. Name: "Username", password: "Password" }) console. log(result, result. user. Name, result. password)
Prompt. Dialog let result = await prompt('How are your? ', 'Amazing!') console. log(result, result. text) let result = await prompt({ title: "Prompt", message: "How are your? ", ok. Button. Text: "OK", cancel. Button. Text: "Cancel", default. Text: "Amazing!", }) console. log(result, result. text)
Plugin ● https: //market. nativescript. org/ ● ���� plugin ○ ○ tns plugin add PLUGIN_NAME ��������������� plugin
Plugin ����� ● ● ● ● ● nativescript-localstorage �������� key-value nativescript-camera �������� nativescript-geolocation ������ GPS nativescript-vibrate ������� nativescript-flashlight ������ nativescript-barcodescanner ������������ nativescript-google-maps-sdk ��� Google Maps nativescript-audio ����������� nativescript-background-http ��������
������� nativescript-localstorage ● https: //market. nativescript. org/plugins/nativescript-localstorage ● ����� ○ tns plugin add nativescript-localstorage ● ����� ○ ○ ○ ○ require( "nativescript-localstorage" ); local. Storage. set. Item('key 1', 'value 1'); // key ��� value ���� string ���� local. Storage. set. Item('key 2', JSON. stringify({ code: '001', name: 'name 1' })) let key 1 = local. Storage. get. Item('key 1') || 'v 1' let key 2 = JSON. parse(local. Storage. get. Item('key 2') || 'null') local. Storage. remove. Item('key 1') local. Storage. clear() local. Storage. key(local. Storage. length - 1)
������� nativescript-camera (1/2) ● https: //market. nativescript. org/plugins/nativescript-camera ● ����� ○ ○ tns plugin add nativescript-camera i. OS ����� app/App_Resources/i. OS/Info. plist ������ ■ <key>NSCamera. Usage. Description</key> ■ <string>enter your camera permission request text here</string> ■ <key>NSPhoto. Library. Usage. Description</key> ■ <string>enter your photo library permission request text here</string>
������� nativescript-camera (2/2) ● ����� ○ ○ import * as camera from "nativescript-camera"; var options = { width: 300, height: 300, keep. Aspect. Ratio: true, save. To. Gallery: true }; import { Image } from "tns-core-modules/ui/image"; try { await camera. request. Permissions(); let image. Asset = await camera. take. Picture(options); this. $refs. img. src = image. Asset; } catch (e) { console. log('cannot use camera') }
������� nativescript-geolocation ● https: //market. nativescript. org/plugins/nativescript-geolocation ● ����� ○ tns plugin add nativescript-geolocation ● ����� ○ ○ ○ import * as geolocation from "nativescript-geolocation"; import { Accuracy } from "tns-core-modules/ui/enums"; let loc = await geolocation. get. Current. Location({ desired. Accuracy: Accuracy. high, maximum. Age: 5000, timeout: 20000 }) console. log(loc. latitude, loc. longitude, loc. altitude, loc. horizontal. Accuracy, loc. vertical. Accuracy, loc. speed, loc. timestamp) let watch = geolocation. watch. Location(success. Callback, error. Callback, options); geolocation. clear. Watch(watch);
Fetch API ● ● http: //docs. nativescript. org/cookbook/fetch ���������� import ���� Promise ������ GET ○ let r = await fetch('https: //httpbin. org/get') let json = await r. json() console. log(json)
Fetch API: ������ POST ● let r = await fetch('https: //httpbin. org/post', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON. stringify({ var 1: 'value 1', }) }) let json = await r. json() console. log(json)
���� server ����� node. js const express = require('express') const body. Parser = require('body-parser') const app = express() app. post('/login', body. Parser. json(), (req, res) => { if (req. body. email !== 'a@b. com' || req. body. pass !== '1234') { return res. send({ ok: 0, error: 'email or password incorrect' }) } res. send({ ok: 1 }) }) app. listen(3000, function () { console. log('Example app listening on port 3000!') })
������������ My. SQL ���� Knex. js const opt = { client: 'mysql', connection: { host: 'localhost', port: 3306, user: 'root', password: '1234', database: 'db 1', support. Big. Number: true, timezone: '+7: 00', date. Strings: true, charset: 'utf 8 mb 4_unicode_ci', } } const knex = require('knex')(opt)
������ query ���� Knex let rows = await knex('student as s'). join('department as d', 's. dep_code', 'd. dep_code'). where('s. dep_code', '=', dep_code). order. By('s. std_code', 'asc'). select('s. std_code', 's. name', 's. dep_code', 'd. name as dep_name')
������ Upload ������ const express = require('express'); const file. Upload = require('express-fileupload'); const app = express(); app. use(file. Upload()); app. post('/upload', function(req, res) { if (!req. files. sample. File) { return res. send({ ok: 0, error: 'No files were uploaded. ' }); } req. files. sample. File. mv('/somewhere/on/your/server/filename. jpg', function(err) { if (err) { return res. send({ ok: 0, error: err. message }); } res. send({ ok: 1 }); });
������ INSERT/UPDATE/DELETE ● ● INSERT let id = await knex('student'). insert({ std_code: '610001', name: 'Name 1', create_date: knex. fn. now(), }) ● ● UPDATE await knex('student'). where('code', '=', '610001'). update({ name: 'New. Name 1', }) DELETE await knex('student'). where('code', '=', '610001'). delete()
���� api ���� php <? php header("Content-Type: text/json"); $json = file_get_contents('php: //input'); $obj = json_decode($json, TRUE); if ($obj['email'] == '' || $obj['pass'] == '') { $res = array('ok' => 0, 'error' => 'email or pass incorrect'); echo json_encode($res); exit; } $res = array('ok' => 1); echo json_encode($res); exit;
������������ ● ����������� app/App_Resources/Android ○ ○ drawable ����� values ������ � ● ���� App Icon ������� Android. Manifest. xml ○ ○ ○ <application android: icon="@drawable/icon"> mdpi = 48 x 48 xxhdpi = 144 x 144 ● ��� launch screen ������� drawable-nodpi/splash_screen. xml ● �������� folder ����� reset ����� ○ ○ tns platform remove android tns prepare android
������� Icon Launcher
����������. apk ������ Play Store ● �����. keystore ������ ○ keytool -genkey -v -keystore <my-release-key>. keystore -alias <alias_name> -keyalg RSA keysize 2048 -validity 10000 ● ������� nativescript. id ������ package. json ���� ○ ○ tns platform remove android tns prepare android ● build ���� apk ○ ○ tns build android --release --key-store-path <path-to-your-keystore> --key-store-password <your-key-store-password> --key-store-alias <your-alias-name> --key-store-alias-password <your-alias-password> ����. apk ����� <app_name>/platforms/android/app/build/outputs/apk/<app_name>release. apk
- Slides: 86