はじめに
VueNativeが話題です。公開してから数日でgithubスター数3000を超えました。
Introducing Vue Native!https://t.co/vIjdcELvkV pic.twitter.com/2mfmOHNbuw
— Sanket Sahu (@sanketsahu) 2018年6月12日
HelloWorldの記事もいいね数多め。:さっそくVue NativeでHello Worldしてみた - Qiita
ということでVue Nativeを触ってみます。
ゴールはTodoアプリですが、この記事では一旦コンソール出力までを実装します。
作り方
今回はReactNativeアプリをクローンしてみます。以下の記事をVueNativeでやってみたです
- 【React Native入門】Java Scriptでアプリ作ろう【Reactやったことない人者向け】1
- 【React Native入門】Java Scriptでアプリ作ろう【Reactやったことない人向け】2
VueNativeは中身的にはReactNativeの技術の上に乗っているので、エラー処理なんかはReactNativeの知識が求められそう。一度目を通しても良いかもしれません。
まずはプロジェクト作成
Vue Native Cli
を使ってアプリを作ります。
これを使うために更にcreate-react-native-app
が必要になるので、global installします。
yarn global add create-react-native-app
yarn global add vue-native-cli
vue-native init todoapp
cd todoapp/
アプリ起動
yarn start
i
でiosエミュレーターが起動します。
補足
これはさっき導入したcreate-react-native-app
によって提供されている開発環境でexpoとfacebookがコラボして作られたツールです。
そもそも、Vue Nativeは内部的にReact Nativeをラップして実装しているようで、vue-native-cli
もcreate-react-native-app
をラップして実装しているのでしょう。
こちらのcreate-react-native-app
は、xcodeやAndroid Studioを経由せず、Expoを使ってアプリが実行されます。
xcodeやAndroid Studioのビルド環境が絡むと(特にAndroid)、地雷踏んだときにめっちゃ時間かかります。Expoを使ってみた感じ、アプリケーションの実装を考えるだけで済むため、開発者に有意義なツールです。
とはいえカスタマイズするとなると脱Expoをしないといけないので、導入時のタイミングにはありかもしれないです。
ちなみに、QRコードを使って手元のスマホアプリから確認するときは同じネットワーク(WiFi)に接続してくださいね。(この192.168.160.30
はローカルIPアドレスなので)
色を変えてみよう
App.vue
を以下の内容で編集してみます。
<template>
<view class="container">
<text class="welcome">{{message}}</text>
</view>
</template>
<script>
export default {
data: function() {
return {
message: "Vue Nativeへようこそ"
}
}
}
</script>
<style>
.container {
background-color: #333;
align-items: center;
justify-content: center;
flex: 1;
}
.welcome {
color: white;
font-size: 20px;
margin: 20px;
}
</style>
コンポーネント作成
Todoの入力フォームと、そのTodoをリストに追加するボタンを追加していきます。
src/TodoInput.vue
を作ります。
<template>
<view class="container">
<text-input class="text-input" />
<touchable-opacity class="button">
<text class="button-text">追加</text>
</touchable-opacity>
</view>
</template>
<script>
export default {}
</script>
<style>
.container {
flex-direction: row;
padding: 20px;
}
.text-input {
background-color: white;
margin-right: 5px;
flex: 3;
}
.button {
flex: 1;
background-color: #008080;
margin-left: 5px;
align-items: center;
justify-content: center;
padding-top: 10px;
padding-bottom: 10px;
}
.button-text {
color: white;
font-weight: normal;
}
</style>
ちなみにReactNativeで書くとこうなります。
import React, { Component } from 'react';
import {
View,
Text,
TouchableOpacity,
TextInput,
StyleSheet,
} from 'react-native';
const styles = StyleSheet.create({
container: {
flexDirection: 'row',
padding: 20,
},
textInput: {
flex: 3,
backgroundColor: '#FFF',
marginRight: 5,
},
button: {
flex: 1,
backgroundColor: '#008080',
marginLeft: 5,
alignItems: 'center',
justifyContent: 'center',
paddingTop: 10,
paddingBottom: 10,
},
buttonText: {
color: '#FFF',
fontWeight: '500',
}
});
export default class TodoInput extends Component {
render() {
return (
<View style={styles.container}>
<TextInput style={styles.textInput}/>
<TouchableOpacity style={styles.button}>
<Text style={styles.buttonText}>追加</Text>
</TouchableOpacity>
</View>
);
}
}
コンポーネントについて
VueNativeはReactNativeのコンポーネントを使って実装します。
react-vueをforkして実装していることから、ReactNativeのコンポーネント名をキャメルケース(CamelCace)からケバブケース(kebab-case)に置き換えて使うイメージで大丈夫です。
ここでは<TouchableOpacity>
を<touchable-opacity>
と書きます。
スタイル
ReactNativeでは、StyleSheetを使い、CSSをjsのオブジェクトとして定義しています(CSS in JS)。つまり、純粋なCSSでは書けません。
Vue NativeではCSSで書けます。いいですね。
ReactNativeではこうで
buttonText: {
color: '#FFF',
fontWeight: '500',
}
VueNativeではこう書けます
.button-text {
color: white;
font-weight: normal;
}
. . .
ちなみに対応していないCSSもあるみたいです。
font-size: large;
適用されません。
VueのCSSから、ReactNativeのstyleにマッピングがうまくできてない感じがします。
(react-vue
でマッピングができてない?)
buildエラーになるパターンと、そうならないパターンに遭遇しましたが、条件を追求できていないので分かり次第追記します。
コンポーネントの読み込み
App.vue
にTodoInput.vue
を組み込んでみましょう。
<template>
<view class="container">
<view class="main">
<text-input />
</view>
</view>
</template>
<script>
import TextInput from './src/TodoInput';
export default {
components: {
TextInput
}
}
</script>
<style>
.container {
background-color: #333;
flex: 1;
padding-top: 40px;
align-items: center;
}
.main {
flex: 1;
max-width: 400px;
align-items: center;
}
</style>
- scriptタグで
TextInput
をインポート - scriptタグで
components
としてTextInput
を定義 - ケバブケースでコンポーネントを記述:
<text-input />
するとこんな感じで画面に表示されるようになります。
コンソール出力
テキストを入力して追加ボタンを押すとconsoleに出力できるようにしてみましょう。
App.vue
は以下の編集をします。
- <text-input />
+ <text-input
+ :on-add='_onPress'
+ />
export default {
components: {
TextInput
- }
- }
+ },
+ methods: {
+ _onPress : (text) => {
+ console.log(text);
+ },
+ }
+ }
- App.vueで関数を定義
- その関数
_onPress
を、on-add
(onAdd)としてTextInputに渡す
つぎに、TodoInput.vue
の編集です。
- <text-input class="text-input" />
- <touchable-opacity class="button">
+ <text-input class="text-input" v-model="newText" />
+ <touchable-opacity class="button" :on-press="addTodo">
<script>
export default {
+ props: {
+ onAdd: Function
+ },
+ methods: {
+ addTodo: function() {
+ this.onAdd(this.newText)
+ },
+ }
}
</script>
テキストを入力して追加ボタンを押してみてください。
ターミナルにconsole.logの内容が出力されます。
xcodeを使った場合だとchromeのコンソールに出力されますが、こちら(expo)はターミナルに出力される感じです。
一旦はここまでです。
ソースはgithubにあげてますので、わからなければこちらからどうぞ!