Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Vue.js simple Chat Handson (in Hamamatsu.js 2019.11)

jacoyutorius
November 06, 2019

Vue.js simple Chat Handson (in Hamamatsu.js 2019.11)

Hamamatsu.js #8 at 2019.11.9 (https://connpass.com/event/148554/)

jacoyutorius

November 06, 2019
Tweet

More Decks by jacoyutorius

Other Decks in Technology

Transcript

  1. Vue.js handson
    Hamamatsu.js #2019.11
    @jacoyutorius
    Hamamatsu.js Amplify + Vue.js Handson @jacoyutorius 1

    View Slide

  2. Yuto Ogi
    @jacoyutorius
    Web developer, AIRS
    • ࠷ۙ͸αʔόʔϨεΞʔΩςΫνϟ͕
    ޷͖
    • AlexaͷεΩϧΛ࡞ͬͨΓWebΞϓϦ
    έʔγϣϯΛ࡞ͬͨΓ
    • ࣗ࡞ΩʔϘʔυপʹϋϚ͍ͬͯͯͦΖ
    ͦΖ3ػ໨Λ࡞Δ༧ఆ
    Hamamatsu.js Amplify + Vue.js Handson @jacoyutorius 2

    View Slide

  3. ※ AWSؔ࿈ͷϦιʔε͸ͪ͜ΒͰఏڙ͠·͕͢ɺϋϯζΦϯޙ਺೔Ҏ಺ʹͦΕΒ͸࡟আ͠·͢ɻ
    Hamamatsu.js Amplify + Vue.js Handson @jacoyutorius 3

    View Slide

  4. Hamamatsu.js Amplify + Vue.js Handson @jacoyutorius 4

    View Slide

  5. on docker
    docker-compose.yml
    version: "3.7"
    services:
    dev:
    image: node:12.13-alpine
    container_name: vue-dev
    ports:
    - "8080:8080"
    volumes:
    - .:/app
    tty: true
    stdin_open: true
    Hamamatsu.js Amplify + Vue.js Handson @jacoyutorius 5

    View Slide

  6. on docker
    $ docker-compose up -d
    Creating network "hmjs-chat_default" with the default driver
    Pulling dev (node:12.13-alpine)...
    ~
    Creating vue-dev ... done
    $ docker exec -it vue-dev sh
    Hamamatsu.js Amplify + Vue.js Handson @jacoyutorius 6

    View Slide

  7. on docker
    # yarn global add @vue/cli
    Hamamatsu.js Amplify + Vue.js Handson @jacoyutorius 7

    View Slide

  8. Stages
    1. create Vue project
    2. install Bootstrap
    3. Chat mockup
    4. integrate Chat API
    Hamamatsu.js Amplify + Vue.js Handson @jacoyutorius 8

    View Slide

  9. before handson
    • Node.js
    • install @vue/cli
    • Vue.js devtools (Chrome plugin)
    Hamamatsu.js Amplify + Vue.js Handson @jacoyutorius 9

    View Slide

  10. versions
    $ node -v
    v10.14.1
    $ npm -v
    6.11.3
    Hamamatsu.js Amplify + Vue.js Handson @jacoyutorius 10

    View Slide

  11. Hamamatsu.js Amplify + Vue.js Handson @jacoyutorius 11

    View Slide

  12. 1. create vue project
    Hamamatsu.js Amplify + Vue.js Handson @jacoyutorius 12

    View Slide

  13. $ vue create vue-chat-app
    Vue CLI v3.2.1
    ┌────────────────────────────┐
    │ Update available: 3.11.0 │
    └────────────────────────────┘
    ? Please pick a preset: default (babel, eslint)

    Done in 16.32s.

    Running completion hooks...
    #
    Generating README.md...
    $
    Successfully created project vue-chat-app.
    $ cd vue-chat-app
    $ subl . / atom . / code .
    Hamamatsu.js Amplify + Vue.js Handson @jacoyutorius 13

    View Slide

  14. $ tree -L 1
    .
    ├── README.md
    ├── babel.config.js
    ├── node_modules
    ├── package.json
    ├── public
    ├── src
    └── yarn.lock
    3 directories, 4 files
    Hamamatsu.js Amplify + Vue.js Handson @jacoyutorius 14

    View Slide

  15. $ yarn serve
    $ open http://localhost:8080
    Hamamatsu.js Amplify + Vue.js Handson @jacoyutorius 15

    View Slide

  16. Hamamatsu.js Amplify + Vue.js Handson @jacoyutorius 16

    View Slide

  17. 1. create vue project
    done
    • VueΞϓϦέʔγϣϯͷॳظԽ
    Hamamatsu.js Amplify + Vue.js Handson @jacoyutorius 17

    View Slide

  18. eslintͷઃఆΛগ͚ͩ͠؇͘͢Δ
    no-conoleͷϧʔϧΛ௥ه͓ͯ͘͠ͱޙʑָɻ
    eslintConfig": {
    "rules": {
    "no-console": "off" // ௥ه
    },
    Hamamatsu.js Amplify + Vue.js Handson @jacoyutorius 18

    View Slide

  19. 2. install Bootstrap
    Hamamatsu.js Amplify + Vue.js Handson @jacoyutorius 19

    View Slide

  20. $ yarn add bootstrap-vue bootstrap core-js
    > [email protected] postinstall /Users/yuto-ogi/Work/aws_amplify/vue-chat-app/node_modules/bootstrap-vue
    > opencollective || exit 0
    ;XXXXXXXXXXXX333333333XXXXXXXXXXXXX;
    :2XXXXXXXXXXSisssssiSXXXXXXXXXXX2:
    .;S3XXXXXXXXX, .,,,,..,SXXXXXXXX3S;,
    .:SX2222XXXXXX, :XXXXS. r3XXXX2222X2;.
    .riiiiii5XXXXX, .;;;;, :2XXXX5iiiiiir.
    ;iiiiiiSXXXX, ,rrrr;,.;XXXSiiiiii;
    ;iiiiiiS2XX, ;3333X; .2XSiiiiii;
    :siiiiii2X, .::::,..r2iiiiiis:
    ,siiiiii2isrrrrrsi22iiiiiis,
    ,riiiiii23333333X2iiiiiir,
    .riiiiii5XXXXXX5iiiiiir.
    .;iiiiiiSXXXXSiiiiii;.
    ;iiiiiiSXXSiiiiii;
    :siiiiiiiiiiiis:
    ,siiiiiiiiiis,
    ,riiiiiiiir,
    .riiiiiir.
    .;iiii;.
    ;ii;
    ;;
    Thanks for installing bootstrap-vue
    !
    Please consider donating to our open collective
    to help us maintain this package.
    Hamamatsu.js Amplify + Vue.js Handson @jacoyutorius 20

    View Slide

  21. 2. install Bootstrap
    src/main.js
    import Vue from 'vue'
    import App from './App.vue'
    import BootstrapVue from 'bootstrap-vue'
    import 'bootstrap/dist/css/bootstrap.css'
    import 'bootstrap-vue/dist/bootstrap-vue.css'
    Vue.use(BootstrapVue)
    Vue.config.productionTip = false
    new Vue({
    render: h => h(App),
    }).$mount('#app')
    Hamamatsu.js Amplify + Vue.js Handson @jacoyutorius 21

    View Slide

  22. 2. install Bootstrap
    src/App.vue



    For more information visit our website
    More Info

    horizontal
    :label-cols="4"
    description="Let us know your name."
    label="Enter your name"
    >


    Hello {{ name }}


    Hamamatsu.js Amplify + Vue.js Handson @jacoyutorius 22

    View Slide

  23. 2. install Bootstrap
    src/App.vue
    export default {
    name: "app",
    data() {
    return {
    name: ""
    };
    },
    computed: {
    showGreeting() {
    return this.name.length > 4;
    }
    }
    }
    Hamamatsu.js Amplify + Vue.js Handson @jacoyutorius 23

    View Slide

  24. Hamamatsu.js Amplify + Vue.js Handson @jacoyutorius 24

    View Slide

  25. Hamamatsu.js Amplify + Vue.js Handson @jacoyutorius 25

    View Slide

  26. 2. install Bootstrap
    • Vue.js devtools ͰίϯϙʔωϯτͷϓϩύςΟΛ֬ೝ͢Δ
    Hamamatsu.js Amplify + Vue.js Handson @jacoyutorius 26

    View Slide

  27. 3. mockup
    Hamamatsu.js Amplify + Vue.js Handson @jacoyutorius 27

    View Slide

  28. 3. mockup
    src/App.vue



    Vue Chat


    Post




    Hamamatsu.js Amplify + Vue.js Handson @jacoyutorius 28

    View Slide

  29. 3. mockup
    src/App.vue









    id="message"
    v-model="form.message"
    placeholder="Enter something..."
    rows="3"
    max-rows="6"
    >



    Submit
    Cancel



    Hamamatsu.js Amplify + Vue.js Handson @jacoyutorius 29

    View Slide

  30. 3. mockup
    src/App.vue






    Cras sit amet nibh libero, in gravida nulla. Nulla vel metus scelerisque ante sollicitudin.
    Cras purus odio, vestibulum in vulputate at, tempus viverra turpis. Fusce condimentum nunc
    ac nisi vulputate fringilla. Donec lacinia congue felis in faucibus.






    Hamamatsu.js Amplify + Vue.js Handson @jacoyutorius 30

    View Slide

  31. 3. mockup
    src/App.vue
    export default {
    name: "app",
    data() {
    return {
    form: {
    user: "",
    message: ""
    },
    chats: [],
    modalShow: false
    };
    },
    computed: {},
    methods: {
    onPostMessage() {
    console.log("submit");
    this.modalShow = false;
    },
    onCancel() {
    console.log("cancel");
    this.modalShow = false;
    }
    }
    };
    Hamamatsu.js Amplify + Vue.js Handson @jacoyutorius 31

    View Slide

  32. 3. mockup
    src/App.vue
    .card {
    margin: 1em 0;
    }
    Hamamatsu.js Amplify + Vue.js Handson @jacoyutorius 32

    View Slide

  33. Hamamatsu.js Amplify + Vue.js Handson @jacoyutorius 33

    View Slide

  34. Hamamatsu.js Amplify + Vue.js Handson @jacoyutorius 34

    View Slide

  35. 3. mockup
    point
    • ϞʔμϧμΠΞϩάͷ "Submit" ΛΫϦοΫ͢Δͱ console.log
    ͕ग़ྗ͞ΕΔ
    • ϞʔμϧμΠΞϩάͷ "Cancel" ·ͨ͸ ӈ্ͷ "x" ·ͨ͸μΠΞ
    ϩά֎ͷΤϦΞΛΫϦοΫ͢ΔͱϞʔμϧμΠΞϩά͕ด͡Δ
    Hamamatsu.js Amplify + Vue.js Handson @jacoyutorius 35

    View Slide

  36. 3 - 1. click event
    "Submit" ϘλϯΛΫϦοΫ͢Δͱνϟοτϝοηʔδ͕ొ࿥͞Ε
    Δɻ
    Hamamatsu.js Amplify + Vue.js Handson @jacoyutorius 36

    View Slide

  37. 3 - 1. click event
    λά෦෼ΛҎԼͷΑ͏ʹॻ͖׵͑Δɻ
    src/App.vue
    v-for="(chat, i) in chats"
    v-bind:key="i"
    v-bind:footer="chat.user + ' - ' + chat.created_at"
    footer-tag="footer"
    >




    {{ chat.message }}


    Hamamatsu.js Amplify + Vue.js Handson @jacoyutorius 37

    View Slide

  38. 3 - 1. click event
    onPostMessageϝιουΛҎԼͷΑ͏ʹॻ͖׵͑Δɻ
    src/App.vue
    methods: {
    onPostMessage() {
    this.chats.push({
    user: this.form.user,
    message: this.form.message,
    created_at: new Date().toLocaleString()
    });
    this.modalShow = false;
    this.form.user = "";
    this.form.message = "";
    },
    Hamamatsu.js Amplify + Vue.js Handson @jacoyutorius 38

    View Slide

  39. 3 - 2. valida+on
    Ϣʔβʔ໊ɾϝοηʔδ͕ೖྗ͞Ε͍ͯͳ͍৔߹ɺΤϥʔϝοηʔδΛදࣔ͢Δɻ
    Hamamatsu.js Amplify + Vue.js Handson @jacoyutorius 39

    View Slide

  40. 3 - 2. valida+on
    src/App.vue
    λάͷԼʹΤϥʔϝοηʔδΛදࣔ͢ΔྖҬΛઃஔ


    v-for="(error, j) in errors"
    v-bind:key="j"
    class="alert alert-danger"
    role="alert"
    >{{ error }}


    Hamamatsu.js Amplify + Vue.js Handson @jacoyutorius 40

    View Slide

  41. 3 - 2. valida+on
    src/App.vue
    data() {
    return {
    ~ (ུ) ~
    errors: [] // ௥Ճ͢Δ
    };
    },
    Hamamatsu.js Amplify + Vue.js Handson @jacoyutorius 41

    View Slide

  42. 3 - 2. valida+on
    src/App.vue
    computed: {
    formIsInValid() {
    return this.errors.length > 0;
    }
    }
    Hamamatsu.js Amplify + Vue.js Handson @jacoyutorius 42

    View Slide

  43. 3 - 2. valida+on
    src/App.vue
    methods: {
    onPostMessage() {
    this.checkMessageParams();
    if (this.formIsInValid) {
    return;
    }
    ~ (ུ) ~
    },
    checkMessageParams() {
    this.errors = [];
    if (this.form.user === "") {
    this.errors.push('"User" is required.');
    }
    if (this.form.message === "") {
    this.errors.push('"Message" is required.');
    }
    }
    Hamamatsu.js Amplify + Vue.js Handson @jacoyutorius 43

    View Slide

  44. 4. integrate Chat API
    Hamamatsu.js Amplify + Vue.js Handson @jacoyutorius 44

    View Slide

  45. 4 - 1. copy AWS se/ng
    AWSͷઃఆϑΝΠϧΛ૊ΈࠐΉ
    Hamamatsu.js Amplify + Vue.js Handson @jacoyutorius 45

    View Slide

  46. 4 - 1. copy AWS se/ng
    src/aws-exports.js
    const awsmobile = {
    "aws_project_region": "ap-northeast-1",
    "aws_appsync_graphqlEndpoint": "https://izjtvc7nijhrrihcnxu2umyuzy.appsync-api.ap-northeast-1.amazonaws.com/graphql",
    "aws_appsync_region": "ap-northeast-1",
    "aws_appsync_authenticationType": "API_KEY",
    "aws_appsync_apiKey": "" //౰೔͓఻͑͠·͢
    };
    export default awsmobile;
    Hamamatsu.js Amplify + Vue.js Handson @jacoyutorius 46

    View Slide

  47. 4 - 1. create AWS se/ng
    src/graphql ͱͦͷ഑ԼͷϑΝΠϧΛ࡞Δ
    Hamamatsu.js Amplify + Vue.js Handson @jacoyutorius 47

    View Slide

  48. create amplify AWS files
    $ tree src
    src
    ├── App.vue
    ├── assets
    │ └── logo.png
    ├── aws-exports.js
    ├── components
    │ └── HelloWorld.vue
    ├── graphql
    │ ├── mutations.js
    │ ├── queries.js
    │ ├── schema.json
    │ └── subscriptions.js
    └── main.js
    3 directories, 9 files
    Hamamatsu.js Amplify + Vue.js Handson @jacoyutorius 48

    View Slide

  49. 4 - 2. install aws-amplify
    aws-amplify ΛΠϯετʔϧ͢Δ
    Hamamatsu.js Amplify + Vue.js Handson @jacoyutorius 49

    View Slide

  50. 4 - 2. install aws-amplify
    $ yarn add aws-amplify aws-amplify-vue
    Hamamatsu.js Amplify + Vue.js Handson @jacoyutorius 50

    View Slide

  51. 4 - 2. install aws-amplify
    src/main.js
    import Amplify, * as AmplifyModules from 'aws-amplify'
    import { AmplifyPlugin } from 'aws-amplify-vue'
    import awsconfig from './aws-exports'
    Amplify.configure(awsconfig)
    Vue.use(AmplifyPlugin, AmplifyModules)
    Hamamatsu.js Amplify + Vue.js Handson @jacoyutorius 51

    View Slide

  52. 4 - 3. Query
    ը໘ಡΈࠐΈ࣌ʹొ࿥͞Ε͍ͯΔνϟοτϝοηʔδΛऔಘͯ͠ը໘ʹදࣔ͢Δɻ
    Hamamatsu.js Amplify + Vue.js Handson @jacoyutorius 52

    View Slide

  53. 4 - 3. Query
    src/App.vue
    import {
    API,
    graphqlOperation
    } from "aws-amplify";
    import { listHmjsChats } from "@/graphql/queries";
    ~ ུ ~
    async created() {
    const listChats = await API.graphql(graphqlOperation(listHmjsChats));
    this.chats = listChats.data.listHmjsChats.items;
    }
    Hamamatsu.js Amplify + Vue.js Handson @jacoyutorius 53

    View Slide

  54. 4 - 4. Post
    ϝοηʔδΛAPIʹPOST͢Δɻ
    Hamamatsu.js Amplify + Vue.js Handson @jacoyutorius 54

    View Slide

  55. 4 - 4. Post
    src/App.vue
    import { createHmjsChat } from "@/graphql/mutations";
    computed: {
    ~ ུ ~
    chatParams() {
    return {
    ...this.form,
    created_at: new Date().toLocaleString()
    };
    }
    },
    Hamamatsu.js Amplify + Vue.js Handson @jacoyutorius 55

    View Slide

  56. 4 - 4. Post
    src/App.vue
    onPostMessage() {
    this.checkMessageParams();
    if (this.formIsInValid) {
    return;
    }
    this.postMessage();
    this.modalShow = false;
    },
    Hamamatsu.js Amplify + Vue.js Handson @jacoyutorius 56

    View Slide

  57. 4 - 4. Post
    src/App.vue
    async postMessage() {
    await API.graphql(
    graphqlOperation(createHmjsChat, {
    input: this.chatParams
    })
    ).catch(error => {
    console.error(error);
    });
    },
    Hamamatsu.js Amplify + Vue.js Handson @jacoyutorius 57

    View Slide

  58. 4 - 5. Subscribe
    σʔλϕʔε΁ͷߋ৽Λߪಡ͢Δɻ
    Hamamatsu.js Amplify + Vue.js Handson @jacoyutorius 58

    View Slide

  59. 4 - 5. Subscribe
    src/App.vue
    import { onCreateHmjsChat } from "@/graphql/subscriptions";
    created() {
    API.graphql(
    graphqlOperation(onCreateHmjsChat)
    ).subscribe({
    next: chat => {
    this.chats.push(chat.value.data.onCreateHmjsChat);
    }
    });
    },
    Hamamatsu.js Amplify + Vue.js Handson @jacoyutorius 59

    View Slide

  60. ͓ർΕ͞·Ͱͨ͠ɻ
    Hamamatsu.js Amplify + Vue.js Handson @jacoyutorius 60

    View Slide

  61. source
    jacoyutorius/vue-chat-app
    Hamamatsu.js Amplify + Vue.js Handson @jacoyutorius 61

    View Slide