20210116のvue.jsに関する記事は7件です。

nuxtで書いたコードをGASで使えるよう変換

概要

  • nuxtで作成したファイル(vueコンポーネント形式)をGASで利用できる形(x-template形式)に変換する
  • これ自体がnuxtで動くプログラム。個人で使うなら自分のPCでローカルホストを立ち上げ、変換されたコードをコピペして使えば良い。 image.png

開発背景

  • GASでフロントサイドを書くにあたって、GASのエディタはお世辞にも使いやすいとは言えません(最近のアップデートでだいぶ使いやすくはなりましたが)
  • 多分GAS開発者の多くがしているように、claspで作成してGASにプッシュする方法がありますが、claspプッシュしてWebページをリロードして、、、というのは地味に面倒ですし、エラーが見つけにくいという欠点もあります。
  • そこで、私はnuxtでUIをある程度作ってから、GASのhtmlファイルにコピーする方法をとっています。
  • nuxtで作ったファイルをそのままコピーできれば良いのですが、nuxtはコンポーネントを.vue形式で作成するのに対して、GASでは.html形式にする必要があること、コンポーネントの書き方はnuxtは〜とexhast defaultに対してGASではx-templateを使った書き方であるなど、いくつかの修正する必要があります。
  • もともとはこれらの作業を手でやっていましたが、コンポーネントファイルが多くなってくると面倒なので、プログラム化しました。

設計

ユーザー操作

  • ブラウザでnuxtアプリのフォルダをアップすると、html形式にしてダウンロードできるようにします。
  • テキストの編集は全てjavascriptで実装しました。

nuxtとGASの違い

  • ファイル形式について、nuxtではコンポーネントファイルが.vue形式、一方でGASでは.html形式
  • コンポーネントの書き方について、nuxtではHTMLに相当する部分をで括りjavascriptをexport defaultで読み取れるようにしている。一方でGASのhtmlファイルでは、HTMLの部分を<script type="text/x-template">で括り、ローカルコンポーネントを変数に入れて親コンポーネントで読み取れるようにしている

nuxt → GASへの変換

componentsのファイル

  1. ファイル名をsomething.vueからsomething.htmlに
  2. <template>の部分を<script type="text/x-template" id="something">
  3. export default"を"const something =" に
  4. template = "#something", を追加

pagesのファイル

1〜4まではcomponentsと同じ

  1. import ChildComponent from "~/components/ChildComponent.vue"を削除

layoutsのファイル

  • 私の開発ではSPAで作成しており、layouts/index.htmlは以下のような構造
<!DOCTYPE html>
<html>
  <head>
    <base target="_top">
      <?!= include("config") ?>
  </head>
  <body>
  <?!= include("components/EditComponent") ?>
  <?!= include("components/ImportMailList") ?>
  <?!= include("components/MailListHead") ?>
  <?!= include("components/MailPreview") ?>
  <?!= include("components/VarConfig") ?>

  <?!= include("pages/mailer") ?>

  <div id="app"></div>

  <script>
    new Vue({
      vuetify: vuetify,
      render: h => h(mailer)
    }).$mount("#app")
  </script>

  </body>
</html>

工夫点

フォルダのアップロードとファイルの処理

  • フォルダのアップロードにはinputタグにwebkitdirectry属性を追加する
  • webkitdirectoryでフォルダをアップした後で、各ファイルを処理する方法は以下参照
<template>
  <input type="file" @change="upload($event)" webkitdirectory>
</template>

<script>
(vue methods)
async upload(event){
      //ファイル一覧の取得と各ファイルの処理
      const files = event.target.files
      for(const file of files){
        //ファイルパスの取得
        const path = file.webkitRelativePath;

                //ファイルの読み取り等はPromiseを用いて同期処理すること
                const text = await this.editFile(file)
      }
},
editFile(file){
  return new Promise((resolve,reject)=>{
    const reader = new FileReader()
    reader.readFileAsText()
    reader.onload = function(e){
      const text = e.target.result
      resolve(text)
    }
  })
}

</script>

nuxtのファイル一覧から必要なファイルの絞り込み

  • nuxtのフォルダをアップすると、2万強のファイルがアップされる。
  • そのうち、必要なvueファイルを絞り込むには以下のようにする
const path = file.webkitRelativePath;
//不要なファイルをフィルタリング
if(!path.includes(".vue"))continue;
if(path.includes(".nuxt"))continue;
if(path.includes("node_modules"))continue;
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Django+Vue.js の開発環境を docker-compose で構築する(2)

この記事は前回からの続きです

前回:Django+Vue.js の開発環境を docker-compose で構築する(1)

前回は、Vue のコンテナを立ち上げてプロジェクトを作成し、GitHub でのレポジトリ管理をフロントエンド(Vue)とバックエンド(Django)に分けました。

今回やりたいこと

今回は、nginx のリバースプロキシを設定し、Vue のスタート画面を見るところまでやっていきます。

手順

  1. Vue のプロジェクトをビルドする
  2. docker-compose.dev.yml を編集する
  3. app_nginx.conf を編集する

1. Vue のプロジェクトをビルドする

まずは Vue のプロジェクトをビルドします。まだなんにも作ってないけどね。

$ docker-compose -f docker-compose.dev.yml run vue npm run build

正しくビルドされれば、Vue のディレクトリに dist というディレクトリができます。

2. docker-compose.dev.yml を編集する

次に、コンテナの /frontend./src/frontend をマウントさせるように、docker-compose.dev.yml の nginx セクションを編集します。

docker-compose.dev.yml(抜粋)
nginx:
  image: nginx:1.17
  restart: unless-stopped
  container_name: nginx
  networks:
    - django_net
  ports:
    - "80:80"
  volumes:
    - ./nginx/conf:/etc/nginx/conf.d
    - ./nginx/uwsgi_params:/etc/nginx/uwsgi_params
    - ./static:/static
    - ./src/frontend:/frontend   # 追加
  depends_on:
    - python

3. app_nginx.conf を編集する

最後に、nginx を次のとおりに設定します。

./nginx/conf/app_nginx.conf
upstream django {
  ip_hash;
  server python:8001;  # uWSGI で Django と nginx とが通信するためのポート
  server vue:3000;     # Vue と nginx とが通信するためのポート  # 追加
}

server {
  listen      80;      # 待ち受けポート
  server_name 127.0.0.1;
  charset     utf-8;

  location /static {
    alias /static;
  }

  client_max_body_size 75M;

  location / {            # 追加
    root /frontend/dist;  # 追加
  }                       # 追加

  location /apiv1/ {                      # 追加
    uwsgi_pass  django;                   # 追加
    include     /etc/nginx/uwsgi_params;  # 追加
  }

  location /admin/ {                      # 追加
    uwsgi_pass  django;                   # 追加
    include     /etc/nginx/uwsgi_params;  # 追加
  }                                       # 追加
}                                         # 追加

server_tokens off;

要するに、
- / へのアクセスは、/frontend/dist にルーティング
- /static へのアクセスは、./static にルーティング
- /apiv1/admin へのアクセスは、uwsgi 経由で Django にルーティング
とします。

ちなみに、ngnix の待ち受けポートが 80 番になっているのは、私が Mac 上の VirtualBox で Ubuntu Server を動かしており、ホストの 8081 番とゲストの 80 番を接続しているからです。だから、Mac のブラウザで http://127.0.0.1:8081/ にアクセスすれば、開発中の画面が見られるってワケ。
関連:もう VirtualBox の設定で悩まない。そう、Vagrant ならね?

動作確認

以上を設定し、コンテナを再起動してトップページにアクセスすると、無事に Vue のスタート画面を見ることができました。

スクリーンショット 2021-01-16 21.51.36.png

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

Nuxt.js + Storybook導入で詰まった点の覚え書き

概要

既存のnuxt.jsにstorybookを導入しようとして、詰まった点をまとめます。
基本は公式ドキュメントの手順を参照

環境

storybook : 6.1.14
nuxt.js: 2.9.2

scssを読み込みたい

遭遇したのは2パターンでvueファイル上の<style lang="scss">内にあるscssと全体のscssファイルの読み込みである。

大体全体のscssが読み込まれていない場合,vueファイル内で参照している変数がうまく読み取れず以下のようなエラーが出る。

SassError: Undefined variable: "$変数名".

これを解決するためには.storybook/main.jsで以下のようにwebpackの設定をしてあげると解決する。

storybook/main.js
const path = require('path');
const rootPath = path.resolve(__dirname, '../');
module.exports = {
  webpackFinal: async (config, { configType }) => {
    config.module.rules.push({
      test: /\.scss$/,
      use: ['style-loader', 'css-loader',
        {
          loader: 'sass-loader',
          options: {
            // scssファイル読み込み
            prependData: `
              @import "~/assets/scss/<scssファイル1>";
              @import "~/assets/scss/<scssファイル2>";
            `
          }
        }
      ],
      include: rootPath
    });
    return config;
  },
  "stories": [
    "../stories/**/*.stories.mdx",
    "../stories/**/*.stories.@(js|jsx|ts|tsx)"
  ],
  "addons": [
    "@storybook/addon-links",
    "@storybook/addon-essentials"
  ]
}

webpackのドキュメントだとadditionalDataになってるけどバージョンの問題だろうか?

参照しているvueのpathが~/xxxx.vueになっており、ファイルが見つからない。

Module not found: Error: Can't resolve '~xxxx`

みたいなエラーが出てくる

これは.storybook/main.jsに以下のような設定を追加追加することで解決できる。

storybook/main.js
const path = require('path');
const rootPath = path.resolve(__dirname, '../');
module.exports = {
  webpackFinal: async (config, { configType }) => {

    config.module.rules.push({
      test: /\.scss$/,
      use: ['style-loader', 'css-loader',
        {
          loader: 'sass-loader',
          options: {
            prependData: `
              @import "~/assets/scss/<scssファイル1>";
              @import "~/assets/scss/mixins/<scssファイル2>";
            `
          }
        }
      ],
      include: rootPath
    });
    config.resolve.alias['~'] = rootPath;
    return config;
  },
  "stories": [
    "../stories/**/*.stories.mdx",
    "../stories/**/*.stories.@(js|jsx|ts|tsx)"
  ],
  "addons": [
    "@storybook/addon-links",
    "@storybook/addon-essentials"
  ]
}

@の場合は

config.resolve.alias['@'] = rootPath;

とすれば良い。

解決できなかった問題

Nuxtにはpluginとして任意のjsコードをインジェクトする機構が存在する。参考

これをstorybook上だと以下のようなエラーが出てinjectしてくれなかった。

_vm.<pluginでinjectされるはずの> is not a function

良い方法があれば教えてもらえるとうれしい。

scssの対応を除いて概ねすんなりと導入できた。
nuxtと言いつつ大体webpackの設定周りだった。webpackは触りたくないなぁ。。。

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

vuetifyで「[Vue warn]: The .native modifier for v-on is only valid on components but it was used on <div>.」

起きたこと

私の場合はカレンダー・コンポーネントを使った時に発生しました。

起動はしますが、ブラウザ上でwarningが出ます。

[Vue warn]: The .native modifier for v-on is only valid on components but it was used on <div>.

解決方法

その1 vuetifyのバージョンをあげる

このwarningについてはGitHubでissueがあがっていて、解決済です。(v-iconでも発生するようです)

[Bug Report] warning with VueJS 2.6.11 · Issue #9999 · vuetifyjs/vuetify
[Bug Report] Button wrapper missing for faSvg clickable v-icons · Issue #10623 · vuetifyjs/vuetify

修正のPRは↓で、v2.3.14でリリース済です。

fix(VIcon): render a button element around clickable component icons by KaelWD · Pull Request #12148 · vuetifyjs/vuetify

というわけで、v2.3.14に上げれば発生しなくなります。

その2 warningを無視するコードを入れる

様々な事情でバージョンをあげるのが難しい場合、無理やり無視する事も可能です。(warningなので動作に影響は無いようです)

該当のコードはこちら

Nuxtの場合は、pluginとして書いてあげるとわかりやすいです。

ignore-warning.ts
const ignoreWarnMessage = 'The .native modifier for v-on is only valid on components but it was used on <div>.';
Vue.config.warnHandler = function (msg, vm, trace) {
  // `trace` is the component hierarchy trace
  if (msg === ignoreWarnMessage) {
    msg = null;
    vm = null;
    trace = null;
  }

該当のwarningメッセージを握りつぶします。

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

初心者限定!!Vueで横幅(width)の変化を検知する方法

今回は、タイトルにも書いてる通りwindowの横幅の変化を検知したいと思います!!!

長ったらしい話はせずにもうコードを書いていきますね!

まず、初めにdataオブジェクトでcurrentWidthというプロパティを宣言し、横幅が変化するたびに呼び出す関数を設定していきます。

App.vue
<script>
export default {
  data() {
    return {
      currentWidth: window.innerWidth,
    }
  },
  methods: {
    calculateWindowWidth() {
      // 横幅を取得する関数
      this.windowWidth = window.innerWidth
    }
  }
}
</script>

初期値として、window.innerWidthを設定しておきます。

次に、DOM要素と紐づけられた後に行う関数mounted、DOM要素が消去される前の関数beforeDestroyを用いて、横幅の変更を検知します。

App.vue
<script>
export default {
  data() {
    return {
      currentWidth: window.innerWidth,
    }
  },
  mounted() {
    // 横幅の変更を検知
    window.addEventListener('resize', this.calculateWindowWidth)
  },
  beforeDestroy() {
    // 横幅の変更を検知
    window.addEventListener('resize', this.calculateWindowWidth)
  },
  methods: {
    calculateWindowWidth() {
      // 横幅を取得する関数
      this.currentWidth = window.innerWidth
    }
  }
}
</script>

いかがだったでしょうか?

僕は、最初にcomputedで行ってしまい横幅の変更を検知してくれませんでした。

最初はcomputed便利だな~って思ってたんですけど、最近使い方が難しいことに気づきました。

なんとなく出来たので良しとします。

以上、「初心者限定!!Vueで横幅(width)の変化を検知する方法」でした!

良かったら、LGTM、コメントお願いします。

また、何か間違っていることがあればご指摘頂けると幸いです。

他にも初心者さん向けに記事を投稿しているので、時間があれば他の記事も見て下さい!!

Thank you for reading

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

【Vue】親から孫へとPropsを受け渡す方法

はじめに

本記事へのアクセスありがとうございます。
Atomic designの実装においてPropsによるデータの受け渡しが多発したので、親コンポーネントから孫コンポーネントまでの一連のデータの流れを備忘録も兼ねて記事に残したいと思います。
では、さっそく見ていきましょう。

親から孫コンポーネントへ

親コンポーネント

<template>
  <div>
    <child :parent-to-child-prop="sendData" />
  </div>
</template>
<script>
export default {
  components: {
    Child: () => import('@/components/Child')
  },
  data() {
    return {
      sendData: '親から孫へ'
    }
  }
}
</script>

子コンポーネント

<template>
  <div>
    <grand-child :child-to-grand-child-prop="parentToChildProp"/>
  </div>
</template>
<script>
export default {
  props: {
    parentToChildProp: {
      type: String,
      default: ''
    }
  },
  components:{
    GrandChild: () =>import('@/components/GrandChild')
  }
}
</script>

孫コンポーネント

<template>
  <div>
    {{ childToGrandChildProp }}
  </div>
</template>
<script>
export default {
  props: {
    childToGrandChildProp: {
      type: String,
      default: ''
    }
  }
}
</script>

おわりに

propsを用いるときはtypeとdefaultは設定しておきましょう。
また、テンプレート内にcomponentを書くときはケバブケースでpropsで貰って使うデータはキャメルケースで書くようにしています。
誰かのお役に立てれば幸いです?‍♂️

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

Vue.js + TypeScript で@Componentをつけ忘れていたら、変更内容がうまく反映されずにはまった話

Vue.js + TypeScript で開発をしている時に、 Props を更新したり、template部分を変更しても、うまく反映され図にかなりはまってしまい、修正に時間がかかってしまった。

結果、 @Component をつけたら、全てが解決した。
なぜ、解決したかも踏まえた、勉強してしっかりまとめておこうと思う。

発生事象

Vue.js + TypeScript で、以下の形式で .vue ファイルを使用して開発を行っていた。

@Component({})
export default class MyComponent extends Vue {
...
}

そうすると、以下のような問題が発生した。

  • data で設定した場合は画面に反映されるが、 Prop で設定すると画面に反映されない。
  • template で設定した内容が反映されない。

解決内容

調べて見ると、共通点として、 @Component を指定しているもののみが上記の事象が反映していることに気づく。
@Component をつけてみると、全てがうまくいった。。。

公式ドキュメントを見ると、 @Component をつけることは必須とのことでした。。。
https://jp.vuejs.org/v2/guide/typescript.html

すごいシンプルなことだったけど、すごいはまって、1-2日使ってしまったので、メモがてら残しておきます。
時間があれば、この辺りの仕組みも少し勉強したい。。。

参考サイト

https://jp.vuejs.org/v2/guide/typescript.html

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