20210315のvue.jsに関する記事は9件です。

Vuetify v-data-tableのslotの探検

デフォルトの表示

単純にデータを渡して、v-data-tableで表するとこのような表示になります
image.png

Slotの働き調査

item.<name> slotを使うことで表示を変更できます。試しに"AAA"を指定すると
manufactureの列がAAAになりました。

<template>
  <div>
    <v-data-table :headers="headers" :items="desserts">
      <template v-slot:item.manufacture>
        AAA
      </template>
    </v-data-table>
  </div>
</template>

image.png

特定の列の表示方法を変更する

試しに、メーカ名の前にiconを付加してみます。データの値は、props.item.manufactureに格納されています。
propsの部分は、v-slot:item.manufacture="XXX" の"XXX" 部分と同じ文字にします。

<template>
  <div>
    <v-data-table :headers="headers" :items="desserts">
      <template v-slot:item.manufacture="props">
        <v-icon>mdi-home</v-icon>{{props.item.manufacture}}
      </template>
    </v-data-table>
  </div>
</template>

予想通りの結果が得られました。
image.png

データをEditできるようにする

Editできるようにする列のslotにv-edit-dialogを指定するとデータを編集できるようになります。
v-edit-dialogのinput slotに入力に使用するコンポーネントを指定する必要があります。
この例ではv-text-fieldを使い、type="Number"(数値入力用)を指定しいます。
v-model.number="props.item.quantity" の様に.numberを付けておくと、入力値が数値して扱われるので、001のような入力をしても1に変換されるようになります。

<template>
  <div>
    <v-data-table :headers="headers" :items="desserts">
      <template v-slot:item.quantity="props">
        <v-edit-dialog
          :return-value.sync="props.item.quantity"
        >
          {{ props.item.quantity }}
          <template v-slot:input>
            <v-text-field
              v-model.number="props.item.quantity"
              label="Edit"
              single-line
              type="Number"
            ></v-text-field>
          </template>
        </v-edit-dialog>
      </template>
    </v-data-table>
  </div>
</template>

image.png

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Nuxtでlocalhost:3000がなんかおかしい

久しぶりの案件で、

npm run dev

でlocalhost:3000をいつものように立ち上げようとしたら
あれ?ずっとローディングがぐるぐる・・・

エラーとか、WARNとか潰していったけど解決せず・・・
違うブラウザでみたら見れた

ということはキャッシュかなとおもって消したら、表示はされたけともう一回みるとだめ・・・

原因

1つ前の案件でPWAをしてたことが原因。
それのサービスワーカーが保存されていて悪さしていたみたい。
全然気づかなくてハマりましたとさ。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【JavaScript】axiosでCSVを受け取りブラウザでファイルダウンロードに移行させる方法。

前提

サーバーサイドはLaravel、フロントはVue.jsです。
今回はJavaScriptの話がメインなのでPHPやLaravelが分からない方でも支障なく読んでいただけると思います。

やりたかったこと

ユーザー目線:ブラウザに表示されているダウンロードボタンをクリックすると、CSVファイルをダウンロードできる。

僕目線:LaravelでCSVを吐き出すAPIを用意し、axiosを使ってAPIを叩きCSVをダウンロードできるようにする。

起こった問題

ブラウザの検索タブでエンドポイントに直接アクセスするとうまくダウンロードできるが、axiosを使ってエンドポイントにアクセスするとダウンロードできない。(CSVの内容はデータとして返ってくるが、ブラウザがダウンロード画面に移行しない。)

失敗した方法

CSVを返すAPIを単純に叩いてダウンロードできると思ったのですが、うまくいきませんでした。
※関係ない部分は色々省略してます。

sample.js
downloadCsv() {
    axios
      .get("/api/download/csv", {
      })
      .catch((error) => {
        console.log(error.messagae);
      });
  },

CSVのデータはちゃんと返ってきますが、ブラウザがダウンロードに移行しません。(ユーザー目線だと何も起こらない。)

うまくいった方法

コードを下記のようにかえるとうまくダウンロードできました。

sample.js
import saveAs from "file-saver";
// 省略
downloadCsv() {
  axios
    .get("/api/download/csv", {
      responseType: "blob",
    })
    .then((res) => {
      let mineType = res.headers["content-type"];
      const name = res.headers["content-disposition"];
      const blob = new Blob([res.data], { type: mineType });
      saveAs(blob, name);
    })
    .catch((error) => {
      console.log(error.messagae);
    });
};

追記部分を解説していきます。

リクエスト時の処理

sample.js
.get("/api/download/csv", {
  responseType: "blob",
})

データをBLOBとして受け取ります。
BLOBとはBinary Large OBjectの略で、IT用語辞典では以下のように解説されています。

BLOBとは、データベースのフィールド定義などで用いられるデータ型の一つで、テキスト(文字列)や整数のように既存のデータ型としては用意されていない任意のバイナリデータを格納するためのもの。

つまり、BlOBはテキストファイルだけではなく画像やPDFなどいろいろな形式のファイルを扱うことができる訳です。

そしてJavaScriptでは受け取ったデータをBOLBにするとこで、ファイルにすることが可能になります。

CSVはテキストデータなのでBLOBにする必要はないのでは?と思ったのですが、データをファイルにするために必要なようです。

レスポンスを受け取った後の処理

sample.js
.then((res) => {
  let mineType = res.headers["content-type"];
  const name = res.headers["content-disposition"];
  const blob = new Blob([res.data], { type: mineType });
  saveAs(blob, name);
})

res.headers["content-type"]にはLaravel側で設定した'text/csv'が格納されています。今回は必ず'text/csv'が返るようになっていますが、ダウンロード用のメソッドを色々な形式に対応できるようにするためにこのように書く必要がありますね。

res.headers["content-disposition"]にはLaravel側で設定したファイル名が格納されています。

new Blob([res.data], { type: mineType });
JavaScriptのBlobオブジェクトのインスタンスを生成しています。
BlobオブジェクトはBLOBをJavaScriptで扱うためのオブジェクトです。
第一引数にファイルの内容の配列、第二引数にファイルの種類を指定して使います。

saveAs(blob, "file");
'file-server'というライブラリを使ってファイルを保存しています。
詳しくは割愛しますが、ブラウザ間で異なるファイル保存の処理を1行で書けます。

文字化けを修正

無事CSVをダウンロードすることができましたが、ファイルの内容が文字化けしていました。
はっきりとした原因は分かりませんでしたが、Laravel側でSJIS形式に変換していた部分をUTF-8に変換するように変更すると文字化けしなくなりました。

sample.php
// mb_convert_encoding($content, 'SJIS', 'auto');
mb_convert_encoding($content, 'UTF-8', 'auto');

HTMLのmetaタグでUTF-8に指定しているのが原因なのか?
とりあえず、これで内容も分かるCSVファイルをダウンロードできるようになりました。めでたしめでたし。

最後に

aixosを使ってファイルをダウンロードするにはひと手間いることが分かりました。
BLOBについては恥ずかしながら全然知らなかったです。

今回はLaravel側でCSVを作成しましたが、データをJSON形式で送るようにしてVue側でCSVを作成することもできそうです。

他にもこんな方法があるとか、ここ間違ってるよとかあればご指摘等よろしくお願いします!
ではでは。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Vue.js コンポーネント

コンポーネント

templateのなかにHTML書く

Vue.js
Vue.component('button-preference', {
  data() {
    return { count: 0 };
  },
  methods: {
    countUp() {
      this.count += 1;
    },
  },
  template: `
    <button v-on:click="countUp">
      {{ count }} いいね!
    </button>
  `,
});

new Vue({
  el: '#example',
});

グローバル登録

Vue.js

Vue.component('button-preference', {
  template: `
    <button>いいね!</button>
  `
});

Vue.component('button-empathy', {
  template: `
    <button>そだねー</button>
  `,
});

Vue.component('buttons-sns', {
  template: `
    <div>
      <button-preference></button-preference>
      <button-empathy></button-empathy>
    </div>
  `,
});

new Vue({
  el: '#example',
});

#ローカル登録

ローカル登録するにはまず、コンポーネントをオブジェクトとして定義します。

プロパティ名はクォーテーションで囲ってください。

componentsプロパティーを使う

Vue.js
const buttonPreference = {
  template: `
    <button>いいね!</button>
  `,
};

const buttonEmpathy = {
  template: `
    <button>そだねー</button>
  `,
};

//上の二つのコンポーネントをしたで使う

const buttonsSns = {
  components: {
    'button-preference': buttonPreference,
    'button-empathy': buttonEmpathy,
  },
  template: `
    <div>
      <button-preference></button-preference>
      <button-empathy></button-empathy>
    </div>
  `,
};

上記のbuttonsSnsコンポーネントをVueインスタンスで使う↓

vue.js
new Vue({
  el: '#example',
  components: {
    'buttons-sns': buttonsSns,
  },
});
一部省略
<!DOCTYPE html>

  <body>
    <div id="example">
      <buttons-sns></buttons-sns>
    </div>

  </body>
</html>

親から子にデータを渡す

new Vue{{...}} == 親
butoon-sns == 子

vue.js
new Vue({
  el: '#example',
  components: {
    'buttons-sns': buttonsSns,
  },
});

propsを使ってデータ渡す
このデータには、dataオプションのデータと同じようにアクセスできます。
つまり、 this.oooでアクセス??? (定かではない)

vue.js
const buttonPreference = {
  props: ['initialCount'],
  template: `
    <button>
      {{ initialCount }} いいね!
    </button>
  `,
};

new Vue({
  el: '#example',
  components: {
    'button-preference': buttonPreference,
  },
});
 <body>
    <div id="example">
      <button-preference initial-count="0"></button-preference>
    </div>
    <script src="main.js"></script>
  </body>
</html>

補足:名前のつけ方

javascriptではキャメルケース(initialCount )
テンプレート(HTML)ではケバブケース (initial-count)

props

props: ['count', 'counts', 'value'],

と複数指定可能

props: {
  count: {
    type: Number,
    required: true,
  },
  counts: {
    type: Array,
    required: true,
  },
},

↑とpropsのルール指定可能
公式 https://jp.vuejs.org/v2/guide/components-props.html#%E3%83%97%E3%83%AD%E3%83%91%E3%83%86%E3%82%A3%E3%81%AE%E3%83%90%E3%83%AA%E3%83%87%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3

EXAMPLE

vue.js
const buttonPreference = {
  props: {
    initialCount: {
      type: Number,
      required: true,
    },
  },
  template: `
    <button>
      {{ initialCount }} いいね!
    </button>
  `,
};

new Vue({
  el: '#example',
  components: {
    'button-preference': buttonPreference,
  },
});
<div id="example">
      <button-preference initial-count="0"></button-preference>
</div>

initial-count='0'でエラー(文字列だから)

解決方法

<div id="example">
  <button-preference v-bind:initial-count="0"></button-preference>
</div>

v-bindを使う

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Vue.js】Vue.js(Nuxt.js)とContentfullでブログ機能を実装

はじめに

弊社プロダクトでNuxt×Contentfullを使用したブログ機能を実装したので、ここに記しておきます〜:raised_hand:
弊社で2年ほど運営しているオウンドメディアがあったのですが、
CVRも低く、SEOも下がり気味だったので、マーケとの協議の結果、
「本プロダクトに記事をがっちゃんこして、運営体制見直さね?」となったわけです!
ブログ用のAPIと管理画面作るの面倒だし、Contentfullイケてそうだなあ〜と思って実装に入りました!!

環境

  • MacOS
  • yarn 1.21.1
  • node 12.0.0
  • vue 2.6.1

Contentfullの設定

まずはContentfullの設定をしていきましょう!

①Contentfullに新規登録・ログイン

Contentfullトップページからログインボタンを押してログイン画面へ。
スクリーンショット 2021-03-14 17.40.14.png
アカウントを持っていない人はサインアップしてください。
(持っている人はそのままログインでOK)
スクリーンショット 2021-03-14 17.40.54.png
必要情報を入力して新規アカウント作成!
英語なので少し読みづらいですね〜
スクリーンショット 2021-03-14 17.41.39.png

②スペースの作成

新規登録・ログインができたらスペースを作成します。
スペースはプロジェクト単位で作成すると良いと思います!
初期設定では「The example project」というスペースが作成されているので、必要なければ削除してしまいましょう!
スクリーンショット 2021-03-14 17.44.24.png
スクリーンショット 2021-03-14 17.45.03.png
料金プランが選べるので、選択します。
プランによってDB容量やアカウントの管理権限設定が異なるようですが、まずはじめは無料で良いのかなと思います。
無料プランでは保存できる記事とアセット(画像など)の合計が5000個までなので、100記事くらいのメディアであれば無料で十分ですね。
ちなみに無料プランは各アカウントにつき1つしか作れないそうなので、無料プランを選択したい人は「The example project」を削除しておきましょう!

スクリーンショット 2021-03-14 18.10.54.png

スペース名を入力して作成します。
スクリーンショット 2021-03-14 18.17.41.png

確認画面が出たらOK!
スクリーンショット 2021-03-14 18.18.58.png

③コンテンツモデルの作成

スペースができたらコンテンツの中身の設定をしていきましょう。
サイドバーから先ほど作ったスペースを選択します。
スクリーンショット 2021-03-14 18.20.31.png
ヘッダーに出てきた「Content Model」を選択し、コンテンツモデルを作成。
スクリーンショット 2021-03-14 18.21.22.png
スクリーンショット 2021-03-14 18.22.03.png

任意の名前と詳細を入力します。
今回は記事コンテンツを作るため、「Post」という名前にしました。
スクリーンショット 2021-03-14 18.23.08.png

④フィールドの追加

コンテンツモデル内にフィールドを追加していきます。
記事の入力項目ですね!
スクリーンショット 2021-03-14 18.23.36.png

テキストや数字など様々選択できます。
「slug」を追加しました。urlになる文字列ですね。
スクリーンショット 2021-03-14 18.24.21.png
スクリーンショット 2021-03-14 18.29.07.png

今回は「slug」「title」「description」「thumbnail」「content」の5つを追加しました。

  • 「slug」…urlになる文字列
  • 「title」…記事のタイトル
  • 「description」…記事の概要
  • 「thumbnail」…サムネイル画像
  • 「content」…コンテンツの内容

スクリーンショット 2021-03-14 18.48.36.png

各フィールドごとに細かい設定も可能です。
「settings」から設定できます。

スクリーンショット 2021-03-14 18.51.40.png

今回は入力必須のバリデーションを設定します。
他にも文字制限やユニーク制限もありますね。
スクリーンショット 2021-03-14 19.01.11.png

これで一旦、Contentfull側の設定は完了です:ok_hand:

Nuxt.jsの設定

dotenvの追加

アプリケーションにdotenvの追加

ターミナル
npm install --save @nuxtjs/dotenv
もしくは
yarn add @nuxtjs/dotenv

ルート直下に.envを作成

ターミナル
touch .env

ContentfullでSPACE_IDとACCESS_TOKENを確認する。
スクリーンショット 2021-03-15 15.04.36.png
スクリーンショット 2021-03-15 15.05.49.png

確認したSPACE_IDとACCESS_TOKEとPOST_TYPE_IDを.env内に記載する。

.env
#CONTENTFUL
CTF_SPACE_ID=xxxxxx
CTF_ACCESS_TOKEN=xxxxxxxxxxxxxxxxxxxxxxx

nuxt.config.jsでdotenvを読み込み

nuxt.config.js
require("dotenv").config()

Contentfullプラグインの追加

Contentfullプラグインを追加します。

ターミナル
npm install contentful
もしくは
yarn add contentful

pluginsフォルダにcontentful.jsを作成。

plugins/contentful.js
const contentful = require('contentful')
module.exports = contentful.createClient({
  space: process.env.CTF_SPACE_ID,
  accessToken: process.env.CTF_ACCESS_TOKEN
})

nuxt.config.jsに諸々設定

nuxt.config.js
require("dotenv").config()
const client = require("./plugins/contentful")

// ~中略~

module.exports = {
  env: {
    // CONTENTFULの API_KEY を使う
    CTF_SPACE_ID: process.env.CTF_SPACE_ID,
    CTF_ACCESS_TOKEN: process.env.CTF_ACCESS_TOKEN
  },
}
plugins: [
    { src: '@/plugins/contentful' }
  ]

// ~中略~

  generate: {
    routes() {
      return client
        .getEntries({ content_type: 'column' })
        .then(entries => {
          return entries.items.map(entry => {
            return {
              route: "/posts/"+entry.fields.slug,
              payload: entry
            }
          })
        })
    }

プラグインや環境変数の読み込みをします。
またgenerateでslugをURLにする記載をしています。

記事一覧ページ

pages配下にpostsフォルダーを作成し、その中にindex.vueを作成する。
これが記事一覧ページになります。

コードは参考までに、、、

posts/index.vue
<template>
  <section class="posts-lists-page">
    <h1 class="title-h1 title-bottom">コラム一覧</h1>
    <div class="posts">
      <nuxt-link
        v-for="(post, index) in posts"
        :to="'posts/'+post.fields.slug"
        :key="index"
        class="post">
        <div class="post-thumb">
          <img
            :src="post.fields.thumbnail.fields.file.url"
            class="post-thumb__img">
        </div>
        <div class="post-text">
          <p class="post-text__date">{{ formatDate(post.sys.createdAt) }}</p>
          <h2 class="post-text__title">{{ post.fields.title }}</h2>
        </div>
      </nuxt-link>
    </div>
  </section>
</template>

<script>
import content from '~/plugins/contentful'
export default {
  head() {
    return {
      title: this.title,
      meta: [
        { hid: 'description', name: 'description', content: this.description },
        {
          hid: 'og:url',
          name: 'og:url',
          content: `https://furien.jp${this.$route.path}`
        },
        { hid: 'og:title', name: 'og:title', content: this.title },
        {
          hid: 'og:description',
          name: 'og:description',
          content: this.description
        },
        { hid: 'twitter:title', name: 'twitter:title', content: this.title },
        {
          hid: 'twitter:description',
          name: 'twitter:description',
          content: this.description
        }
      ]
    }
  },
  data() {
    const title = 'コラム一覧'
    return {
      title: title,
      description: `${title}|役立つ記事を沢山配信しています。`
    }
  },
  methods: {
    formatDate(iso) {
      const date = new Date(iso)
      const yyyy = new String(date.getFullYear())
      const mm = new String(date.getMonth() + 1).padStart(2, '0')
      const dd = new String(date.getDate()).padStart(2, '0')
      return `${yyyy}.${mm}.${dd}`
    }
  },
  asyncData({ params }) {
    return content
      .getEntries({
        content_type: 'column',
        order: '-sys.createdAt'
      })
      .then(entries => {
        return { posts: entries.items }
      })
      .catch(e => console.log(e))
  }
}
</script>

<style lang="scss" scope>
.posts-lists-page {
  .posts {
    margin: 0 auto;
    padding: 10px;
    display: flex;
    flex-direction: row;
    flex-wrap: wrap;

    .post {
      width: calc(100% / 2 - 20px);
      margin: 10px;
      background: #fff;
      text-decoration: none;
      color: #111;
      border: 1px solid rgba(162, 162, 162, 0.5);

      @include sp-small {
        width: 100%;
      }

      &-thumb {
        width: 100%;
        padding-bottom: 75%;
        position: relative;
        overflow: hidden;

        &__img {
          position: absolute;
          top: 50%;
          left: 50%;
          transform: translate(-50%, -50%);
          max-width: 100%;
        }
      }

      &-text {
        padding: 1rem;

        &__date {
          font-size: 1.2rem;
          color: gray;
        }

        &__title {
          width: fit-content;
          font-size: 2rem;
          font-weight: bold;

          @include sp-small {
            font-size: 1.5rem;
          }
        }
      }
    }
  }
}
</style>

スタイルや表示する内容は適宜変更してくださいね〜
こんな感じになりますね!

スクリーンショット 2021-03-15 15.46.25.png

記事詳細ページ

postsフォルダー内に_slugフォルダーを作成し、その中にindex.vueを作成する。
これが記事詳細ページになります。

posts/_slug/index.vue
<template>
  <article class="article-page">
    <div class="article">
      <BreadCrumbs :title="post.fields.title" />
      <h1 class="article__title">{{ post.fields.title }}</h1>
      <p class="article__date">{{ formatDate(post.sys.createdAt) }}</p>
      <div
        class="article__content"
        v-html="toHtmlString(post.fields.content)"/>
    </div>
  </article>
</template>

<script>
import { BLOCKS } from '@contentful/rich-text-types'
import { documentToHtmlString } from '@contentful/rich-text-html-renderer'
import content from '~/plugins/contentful'

export default {
  head() {
    const ogImage = this.post.fields.thumbnail.fields.file.url
    return {
      title: this.post.fields.title,
      meta: [
        {
          hid: 'description',
          name: 'description',
          content: this.post.fields.description
        },
        {
          hid: 'og:url',
          name: 'og:url',
          content: `https://furien.jp${this.$route.path}`
        },
        { hid: 'og:title', name: 'og:title', content: this.post.fields.title },
        {
          hid: 'og:description',
          name: 'og:description',
          content: this.post.fields.description
        },
        {
          hid: 'og:image:secure_url',
          name: 'og:image:secure_url',
          content: ogImage
        },
        {
          hid: 'twitter:title',
          name: 'twitter:title',
          content: this.post.fields.title
        },
        {
          hid: 'twitter:description',
          name: 'twitter:description',
          content: this.post.fields.description
        },
        { hid: 'twitter:image', name: 'twitter:image', content: ogImage }
      ]
    }
  },
  methods: {
    formatDate(iso) {
      const date = new Date(iso)
      const yyyy = new String(date.getFullYear())
      const mm = new String(date.getMonth() + 1).padStart(2, '0')
      const dd = new String(date.getDate()).padStart(2, '0')
      return `${yyyy}.${mm}.${dd}`
    },
    toHtmlString(obj) {
      const options = {
        renderNode: {
          [BLOCKS.EMBEDDED_ASSET]: ({
            data: {
              target: { fields }
            }
          }) => `<img src="${fields.file.url}"/>`
        }
      }
      return documentToHtmlString(obj, options)
    }
  },
  asyncData({ params, error, payload }) {
    if (payload) return { post: payload }
    return content
      .getEntries({
        content_type: 'column',
        'fields.slug': params.slug
      })
      .then(entries => {
        return { post: entries.items[0] }
      })
      .catch(e => console.log(e))
  }
}
</script>

<style lang="scss" scope>
.article-page {
  .article {
    margin: 0 auto;
    padding: 1rem;
    color: #222;

    &__title {
      margin: 5% 0;
      font-size: 3rem;
      font-weight: bold;

      @include sp-small {
        font-size: 2rem;
      }
    }

    &__date {
      font-size: 1.4rem;
      color: $dark-gray;
    }

    &__content {
      //〜中略〜
    }
  }
}
</style>

ここでのポイントはコンテンツをリッチテキストにしている点と画像の処理方法ですね!
コンテンツをリッチテキストにしたのは移行の際に、マーケがコピペで記事を移行できるようにするためです:point_up:
いろんなやり方があると思いますので、試してみてください!

こんな感じになります!
スクリーンショット 2021-03-15 16.01.11.png

サーバー(heroku)の環境変数

あとは本番環境にも.envに設定した環境変数を設置してあげればOKです!!

完成!!:clap:

これで完成です!!!
細かい設定、表示内容やスタイルなどは各々カスタマイズしていただければOKです!
Contentfull公式も結構丁寧に解説してくれてるので、一読してみてくださいね〜

おわりに

最近わりと大きなプロジェクトのPMを任されていて、なかなかコードをかけない日々を送っています:joy:
時間を見つけてコード書けるように精進していきます〜:joy:

参考

ContentfulとNuxtの連携の仕方①
https://izm51.com/posts/nuxt-contentful-netlify-blog-making-1/
ContentfulとNuxtの連携の仕方②
https://izm51.com/posts/nuxt-contentful-netlify-blog-making-2/
ContentfulのRichtextで画像を表示する方法
https://github.com/contentful/rich-text/issues/61
画像表示
https://tech.hajimari.inc/entry/2019/06/05/171553

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【JavaScript】別ファイルに関数をまとめてexportsを利用して呼び出す。

開発環境

React.js

概要

JavaScriptで関数を共通化して別ファイルにまとめたときに、HTMLのscriptタグを使い呼び出すのは面倒だと思いました。JavaScriptのexportsを使い呼び出すことができることを知りましたので記事にしておきます。

import.jsとexport.jsファイルを作成

import.jsからexport.jsの関数を呼び出していきます。

export.js
exports.criminalIsKogoro = function () {
  console.log("犯人は毛利小五郎");
}

exports.detectiveCriminal = function (name) {
  console.log("犯人は" + name);
}

const criminalIsAgasa = function () {
  console.log("犯人は阿笠だ");
}

比較するためにcriminalIsAgasaだけはexportsしないようにしておきます。

import.js
import exportFunction from 'export.jsのパスを記述'
// または
// var exportFunction = require('export.jsのパスを記述');

exportFunction.criminalIsKogoro; // "犯人は毛利小五郎"
exportFunction.detectiveCriminal("元太"); //"犯人は元太"
exportFunction.criminalIsAgasa; // error. exportFunction.criminalIsAgasa is not a function

このようにexportsをしておかないと外部のファイルから読み込むことができないことが分かりました。

参考

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【React.js】別ファイルに関数をまとめてexportsを利用して呼び出す。

開発環境

React.js

概要

React.jsで関数を共通化して別ファイルにまとめたときに、HTMLのscriptタグを使い呼び出すのは面倒だと思いました。JavaScriptのexportsを使い呼び出すことができることを知りましたので、備忘録として記事に残しておきます。

import.jsとexport.jsファイルを作成

import.jsからexport.jsの関数を呼び出していきます。

export.js
exports.criminalIsKogoro = function () {
  console.log("犯人は毛利小五郎");
}

exports.detectiveCriminal = function (name) {
  console.log("犯人は" + name);
}

const criminalIsAgasa = function () {
  console.log("犯人は阿笠だ");
}

比較するためにcriminalIsAgasaだけはexportsしないようにしておきます。

import.js
import exportFunction from 'export.jsのパスを記述'
// または
// var exportFunction = require('export.jsのパスを記述');

exportFunction.criminalIsKogoro; // "犯人は毛利小五郎"
exportFunction.detectiveCriminal("元太"); //"犯人は元太"
exportFunction.criminalIsAgasa; // error. exportFunction.criminalIsAgasa is not a function

このようにexportsをしておかないと外部のファイルから読み込むことができないことが分かりました。

参考

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Vue.js始めてみました⑥(v-for)

この度Vue.jsを学び始めました。
その勉強内容をまとめます

v-for

HTML要素を繰り返し表示する時にv-forを使います。

Vue.js
//配列から順番に値を1つづつ取り出し表示する
<タグ v-for="変数 in 配列>

//指定した回数表示を繰り返す
<タグ v-for="変数 in 最大値>

//配列から値と番号を1つずつ取り出し表示する
タグ v-for="(変数,番号) in 配列">

使い方

Vue.js
//配列から1つずつ取り出す使い方

<div id="app">
  <ul>
    <li v-for="item in Array">{{ item }}</li>
  </ul>
</div>

<script>
  new Vue({
    el: '#app',
    data: {
      Array:['いちご','メロン','バナナ','りんご']
    }
  })
</script>

上記のではArrayという配列にdataで配列データを用意しておき、それをv-forで順番に取り出し{{ item }}に入れて出力しています。

以下のようにすると配列データを番号付きで出力することもできます。

Vue.js
//配列から1つずつ取り出し、番号付きで表紙する

<div id="app">
  <ul>
    <li v-for="(item,index) in Array">{{ index }}:{{ item }}</li>
  </ul>
</div>

<script>
  new Vue({
    el: '#app',
    data: {
      Array:['いちご','メロン','バナナ','りんご']
    }
  })
</script>

以上です。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

実務でよく使うVueのv-bind:classの使い方4つ

v-bind:classはVueで使えるv-bindディレクティブの一つです。
公式で紹介されてるものより、個人的には使い勝手がいいなと思う方法など、自分がよく使う4パターンを紹介します。

1.真偽値に対して複数クラス

例:アクティブの時はテキストを青くして背景をグレーにしたい

sample.vue
<div :class="{'text-blue bg-grey': isActive}"></div>

2.複数の真偽値

例:アクティブの時はテキストを青くして、選ばれている時は背景をグレーにしたい

sample.vue
<div :class="{ 'text-blue' : isActive , 'bg-grey' : isSelected }"></div>

3.式(演算子)を使う

比較演算子や論理演算子を使って真偽値をかえします。

sample.vue
<div :class="{'text-blue':  apple == sale }"></div>
<div :class="{'text-blue': apple > 3}"></div>
<div :class="{'text-blue': apple && banana}"></div>
<div :class="{'text-blue': apple || banana}"></div>

4.三項演算子(条件分岐)

例:アクティブの時はテキストを青くしてそうじゃなかったらテキストを黒くしたい

sample.vue
<div :class="isActive?'text-blue':'text-black'"></div>
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む