Help us understand the problem. What is going on with this article?

Vue NativeでTodoアプリを作ろう その1

More than 1 year has passed since last update.

はじめに

VueNativeが話題です。公開してから数日でgithubスター数3000を超えました。

HelloWorldの記事もいいね数多め。:さっそくVue NativeでHello Worldしてみた - Qiita

ということでVue Nativeを触ってみます。
ゴールはTodoアプリですが、この記事では一旦コンソール出力までを実装します。

作り方

今回はReactNativeアプリをクローンしてみます。以下の記事をVueNativeでやってみたです

VueNativeは中身的にはReactNativeの技術の上に乗っているので、エラー処理なんかはReactNativeの知識が求められそう。一度目を通しても良いかもしれません。

まずはプロジェクト作成

Installation — Vue Native

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

するとQRコードとともにこんな結果がでてきます。
image.png

iでiosエミュレーターが起動します。

clipboard.png

補足

これはさっき導入したcreate-react-native-appによって提供されている開発環境でexpoとfacebookがコラボして作られたツールです。
そもそも、Vue Nativeは内部的にReact Nativeをラップして実装しているようで、vue-native-clicreate-react-native-appをラップして実装しているのでしょう。

こちらのcreate-react-native-appは、xcodeAndroid Studioを経由せず、Expoを使ってアプリが実行されます。
xcodeAndroid Studioのビルド環境が絡むと(特にAndroid)、地雷踏んだときにめっちゃ時間かかります。Expoを使ってみた感じ、アプリケーションの実装を考えるだけで済むため、開発者に有意義なツールです。
とはいえカスタマイズするとなると脱Expoをしないといけないので、導入時のタイミングにはありかもしれないです。

ちなみに、QRコードを使って手元のスマホアプリから確認するときは同じネットワーク(WiFi)に接続してくださいね。(この192.168.160.30はローカルIPアドレスなので)

色を変えてみよう

App.vueを以下の内容で編集してみます。

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>

clipboard.png

コンポーネント作成

Todoの入力フォームと、そのTodoをリストに追加するボタンを追加していきます。
src/TodoInput.vueを作ります。

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で書くとこうなります。

TodoInput@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)に置き換えて使うイメージで大丈夫です。

Introducing Vue Native – GeekyAnts Blog

ここでは<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.vueTodoInput.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>
  1. scriptタグでTextInputをインポート
  2. scriptタグでcomponentsとしてTextInputを定義
  3. ケバブケースでコンポーネントを記述: <text-input />

するとこんな感じで画面に表示されるようになります。

clipboard.png

コンソール出力

テキストを入力して追加ボタンを押すと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>

テキストを入力して追加ボタンを押してみてください。

すると
clipboard.png

ターミナルにconsole.logの内容が出力されます。
xcodeを使った場合だとchromeのコンソールに出力されますが、こちら(expo)はターミナルに出力される感じです。

一旦はここまでです。

ソースはgithubにあげてますので、わからなければこちらからどうぞ!

nitaking
ReactNativeエンジニアからのフルスタックエンジニア
https://lapras.com/public/CWAAMPM
aircloset
「新しい当たり前を作る」を作ることをミッションに、airClosetを開発・運営しています。
http://corp.air-closet.com/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away