- 投稿日:2020-07-02T18:48:32+09:00
Vue.Draggable の奇妙な動きを対症療法でなんとかする
初投稿です。よろしくお願いします。
1.環境
Vue.js:2.6.11
Vue.Draggable:2.23.2
Google Chrome2.問題
趣味でなんとなく Vue.js で Webアプリを作っています。
ドラッグ&ドロップで要素をぴょこぴょこ移動させる機能を作りたいな~と思ってたら、Vue.Draggable というなんとも便利なものが存在しているではありませんか。
さっそくインストールして実装。
なかなかいい感じになってきたな、と思ってたらふと妙な動きをしていることに気付きました。
まずは動画を見てください。
※Google Chrome の場合
下のエリアの要素を少し動かしただけなのに、左上のエリアがなにやら蠢いています。
よくみると、下のエリアの要素を動かしはじめた一瞬、その要素が左上のエリアにワープしています。なんじゃぁこれは、と公式のサイトを見てみたのですが、公式のサイトのデモアプリでも同じような動きをします。
あ~じゃあダメだな、と思いつつ諦めきれず英語のサイトや中国語のサイトをあさりましたが解決せず…3.対症療法
ぼ~っとしながら奇妙な動きをするドラッグ&ドロップの操作を繰り返してると、ふと対症療法が浮かんできました。
色々試して気が付いたのは、この現象はcloneイベントの直後に発生しているということです。
そこで、cloneイベントのイベントハンドラに以下の記述を追加しました。<draggable tag="ul" v-model="left" :group=state @clone="onClone"> <li v-for="l in left" :key="l.content"> <div>{{ l.content }}</div> </li> </draggable> <!-- あと右上エリアの分と下エリアの分--> data() { return { state: undefined, left: [ {content: "task1"}, {content: "task2"}, {content: "task3"}, {content: "task4"} ], //あと右上エリアの分と下エリアの分 } }, methods: { onClone: function () { this.state = null setTimeout(this.setGroup, 100) }, setGroup: function () { this.state = "move" } }cloneイベントが発生したらgroup 属性を null にして group 間の移動ができないようにします。
0.1秒くらい待って、group 属性に値をセットしてgroup 間の移動を可能にします。すると以下の動画のようになります。
奇妙な動きはなくなりました。
また、同一エリア内での要素の移動に関して、動かした要素の二行上の要素が一瞬動くという奇妙な動きをすることもあります。
それもこの対症療法で対応できる気がします。
- 投稿日:2020-07-02T13:47:23+09:00
Vue.jsでの複数checkboxの状態管理
vueのチェックボックス管理はクセがありますよね。
例えば複数のメッセージをそれぞれチェックボックスで表示非表示制御するコンポーネントを作るとします。<module :defaults="{1:{name:'ほげ', is_checked:true}, 2:{name:'はげ', is_checked:false}}"></module>module.vue<template> <div> <div v-for="(param, index) in defaults" :key="'key_'+index"> <div> <label> <input type="checkbox" :name="'checkbox['+index+']" v-model="conditions[index]"> <span>{{ param.name }}</span> </label> </div> <div v-if="conditions[index]">お前が{{ param.name }}を覗き込む時{{ param.name }}もまたお前を覗いているのだ</div> </div> </div> </template> <script> export default { props: ['defaults'], data() { return { conditions:{} } }, created: function() { Object.keys(this.defaults).forEach(index => { this.conditions[index] = this.defaults[index].is_checked; } } </script>以上のようにチェックボックス状態管理配列conditions[index]のbool型でチェックボックスのonoffとメッセージの表示v-ifを制御しようとしてもうまく動きません。
vueは複数チェックボックスのonoff管理をv-modelで指定する配列に該当のvalueが含まれるかどうかでやりますので
module.vue<template> <div> <div v-for="(param, index) in defaults" :key="'key_'+index"> <div> <label> <input type="checkbox" :name="'checkbox['+index+']" :value="index" v-model="conditions"> <span>{{ param.name }}</span> </label> </div> <div v-if="conditions.includes(index)">お前が{{ param.name }}を覗き込む時{{ param.name }}もまたお前を覗いているのだ</div> </div> </div> </template> <script> export default { props: ['defaults'], data() { return { conditions:[] } }, created: function() { Object.keys(this.defaults).forEach(index => { if(this.defaults[index].is_checked){ this.conditions.push(index); } } } </script>としてやると動くと思います。
- 投稿日:2020-07-02T13:05:35+09:00
Vue.js導入方法
- 投稿日:2020-07-02T11:57:01+09:00
Vue.jsのプロジェクトをIPFS上にホスティングし、ENS(Ethereum Name Service)でアクセス可能にする
Vuee.jsで作成されたプロジェクトをIPFS上にデプロイし、EthereumのName ServiceであるENSに紐付けしてアクセスできるようにしていきたいと思います。
使うもの
Vueのプロジェクト作成
まずはVueのプロジェクトを作成していきましょう。
ここではvue-cli
を使って簡単にプロジェクトを作成していきます。$ npm install -g @vue/cli次に、プロジェクトを作成します。
$ vue create my-project作成されたらプロジェクトのディレクトリに移動して、走らせます。
$ cd my-project $ yarn serveブラウザで
http://localhost:8080/
にアクセスして以下のようになっていればOKです。このままビルドしてデプロイすると画面が真っ白になるので、設定を変更していきましょう。
プロジェクトのルートにvue.config.js
を作成します。そしてパスの設定を相対パスに変更します。
vue.config.jsmodule.exports = { publicPath: './' };参考:https://cli.vuejs.org/config/#publicpath
Githubにプッシュする
後で説明するfleekではGithubを使ってIPFSへのデプロイを実行していきます。
そこで、github上にリポジトリを作成し、作成したプロジェクトをプッシュしておきましょう。IPFSにデプロイ
それでは次にIPFSにデプロイをしていきたいと思います。
今回はfleekというIPFSにgithub経由でデプロイできるサービスを使っていきましょう。ちなみにそれ以外にも pinata や temporal といったサービスもあるので興味がある方は参照してみてください。
まずはfleekでアカウントを作成してください。無料で利用開始できます。
Hosting
を選択します。
Add new site
を選択し、サイトを追加していきます。
Connect with Github
でgithubに接続していきます。今回は
ipfs-demo
というプロジェクトを作成しているので、そのリポジトリを選択します。
必要なチームやリポジトリが見つからない場合は、Configure the Fleek app on Github
から読み取るリポジトリを追加していきます。その後、デプロイ時の設定を行います。
今回はVue.jsのプロジェクトなのですが、
Framework
にVue.jsがないのでOther
を選択します。
また、Vueはyarnでpackageをインストールした後、yarn buildでビルドするようになっているため
Build command
はyarn && yarn build
とします。
publish directory
はデフォルトではdist
だと思いますのでdist
とします(自分で変更している場合はそれにあわせます)設定が完了したら
Deploy site
を押下していきます。ビルドが走り始めるので完了するまで待ちます。
完了したあと、
IPFS Hash Pending
となっていたところが、Verify on IPFS
に変わります。ここをクリックすることで、IPFS上にホスティングされていることを確認できます(数分待つこともあります)。今回デプロイしたVue.jsのサンプル
https://ipfs.fleek.co/ipfs/QmU4zv5VyLPqKRUpotsrdxcmvFSvMJmfCLxbSj4gkZEWp4なお、URL末尾の
QmU4zv5VyLPqKRUpotsrdxcmvFSvMJmfCLxbSj4gkZEWp4
がIPFS上のハッシュ値でユニークな値です。
このコンテンツはすでにIPFS上にあるため、他のIPFSのゲートウェイからでも参照できます。例.
Cloudflareが提供してるゲートウェイ:
https://cloudflare-ipfs.com/ipfs/QmU4zv5VyLPqKRUpotsrdxcmvFSvMJmfCLxbSj4gkZEWp4/ipfs自体が提供しているゲートウェイ:
https://gateway.ipfs.io/ipfs/QmU4zv5VyLPqKRUpotsrdxcmvFSvMJmfCLxbSj4gkZEWp4/どこからでも同じコンテンツを参照できることがわかります。これもIPFSの特徴ですね。
これでデプロイは完了です。
ドメイン設定
最後にENSへの紐付けをしていきたいと思います。
まずはドメインを購入する必要がありますので以下のサイトにアクセスしましょう。ここでほしいドメインを検索し購入することができます。
ほしいドメインを検索していきます。
購入手続きを進めていきます。ENS購入には2度トランザクションを投げる必要があります。
まずは、購入の意思表示をし、他の人が同時に購入しようとしていないか待ちます。その後、実際にドメイン代を支払って購入していきます。
トランザクションが取り込まれれば完了です。
ここからfleekに戻ります。
Setting
->Domain Management
->ENS
を選択します。
Add Ens
を押下します。先ほど購入したドメイン名をセットし
Verify
します。(この時ドメインを購入したウォレットで接続しておきましょう)アドレスの確認されるので続けて
Yes, Add ENS
していきます。その後、fleekをENSの
Controller
として設定します。
Set Fleek as controller
を選択します。ポップアップに同意します。
トランザクションをなげ、成功すれば完了です。
Metamaskなどを利用している場合は https://takase.eth にアクセスしていただくと、 https://gateway.ipfs.io/ipfs/QmU4zv5VyLPqKRUpotsrdxcmvFSvMJmfCLxbSj4gkZEWp4/ にリダイレクトされると思います。
Metamaskなどを利用していなくても
.eth.link
には普通にアクセスできますので、こちらもためしてみてください。https://takase.eth.link/
(※ 個人のethドメインなので、どこかで消すかも)以上です。
- 投稿日:2020-07-02T10:49:25+09:00
Nuxt.js × Composition API セットアップ
Prologue
Nuxt.jsとCompositionAPIを使うことが多いのですが、結局最低限必要な設定とは?と毎回なるので、設定周りをまとめました。
基本はDocument通りになるため、自身で設定する場合には都度公式を確認することをお勧めします。Nuxt.js の初期設定周りは別記事にまとめているので、そちらも参考にしてください。
Nuxt.js × TypeScript セットアップ環境
- macOS: v10.15.5
- node.js: v12.18.0
- terminal: iTerm
- エディタ: VS Code
- パッケージマネージャ:
yarn
- Composition API: v1.0.0-beta.1
Nuxt.js セットアップ
今回は
nuxt-sample
をプロジェクト名として作成します。yarn create nuxt-app nuxt-sample create-nuxt-app v3.1.0 ✨ Generating Nuxt.js project in nuxt-sample ? Project name: nuxt-sample ? Programming language: TypeScript ? Package manager: Yarn ? UI framework: Buefy ? Nuxt.js modules: Axios ? Linting tools: Prettier ? Testing framework: Jest ? Rendering mode: Single Page App ? Deployment target: Server (Node.js hosting) ? Development tools: (Press <space> to select, <a> to toggle all, <i> to invertインストールが終わったら作成したプロジェクトに移動して、起動し、成功しているか念のため確認します。
cd nuxt-sample yarn devComposition API のインストール
- Composition API をインストールします。
yarn add @vue/composition-api2. Vue の Component で使えるように
plugins
に追加します。plugins/CompositionApi.ts
import Vue from 'vue'; import VueCompositionApi from '@vue/composition-api'; Vue.use(VueCompositionApi)3.
nuxt.config.ts
に作成した plugins を追記します。plugins: [ '~/plugins/CompositionApi' ],以上で最低限のセットアップは完了しました。
create nuxt-app
で作成したデフォルトのプロジェクトを書き換えてみる今回
Buefy
を UI Framework で組みこんだので、そのプロジェクトを Composition API で書き換えてみます。ファイル数も少ないので、お時間ある方は是非試してみてください。
- pages/index.vue
Before:
<script> import Card from '~/components/Card' export default { name: 'HomePage', components: { Card } } </script>After: Composition API
<script lang="ts"> import { defineComponent } from "@vue/composition-api"; import Card from '@/components/Card.vue' export default defineComponent({ name: 'HomePage', components: { Card } }) </script>
- components/Card.vue
Before:
<script> export default { props: { title: { type: String, required: true }, icon: { type: String, required: true } } } </script>After: Composition API
<script lang="ts"> import { defineComponent } from "@vue/composition-api"; export default defineComponent({ props: { title: { type: String, required: true }, icon: { type: String, required: true } } }) </script>
- layouts/default.vue
Before:
<script> export default { data () { return { items: [ { title: 'Home', icon: 'home', to: { name: 'index' } }, { title: 'Inspire', icon: 'lightbulb', to: { name: 'inspire' } } ] } } } </script>After: Composition API
template 部分も一部書き換えたので、こちらは全コード載せます。<template> <div> <nav class="navbar header has-shadow is-primary" role="navigation" aria-label="main navigation"> <div class="navbar-brand"> <a class="navbar-item" href="/"> <img src="~assets/buefy.png" alt="Buefy" height="28" /> </a> <div class="navbar-burger"> <span /> <span /> <span /> </div> </div> </nav> <section class="main-content columns"> <aside class="column is-2 section"> <p class="menu-label is-hidden-touch">General</p> <ul class="menu-list"> <li v-for="(item, key) of state.items" :key="key"> <nuxt-link :to="item.to" exact-active-class="is-active"> <b-icon :icon="item.icon" /> {{ item.title }} </nuxt-link> </li> </ul> </aside> <div class="container column is-10"> <nuxt /> </div> </section> </div> </template> <script lang="ts"> import { defineComponent, reactive } from '@vue/composition-api' interface Menu { title: string icon: string to: { name: string } } export default defineComponent({ name: 'default', setup() { const items: Menu[] = [ { title: 'Home', icon: 'home', to: { name: 'index', }, }, { title: 'Inspire', icon: 'lightbulb', to: { name: 'inspire', }, }, ] const state = reactive({ items: items, }) return { state, } }, }) </script>以上です。
Epilogue
今回は props, data を同時に記載する箇所がなかったのであまり実感がないかもしれませんが、 Composition API は、props と data, method 等 を分けて書けるので、よりわかりやすく、かなり可読性が高まったな、と感じています。
また、v0.4.x くらいから使い始めていましたが、この記事の直前にv1.0.0-beta.1
も出ていて、 どんどん使いやすくなっている印象を受けています。これから Vue のプロジェクトに TypeScript を導入するのであれば、ぜひ検討してみてください^^
- 投稿日:2020-07-02T10:07:19+09:00
Vue.jsで作ったサイトをgh-pages, AWS Amplifyで公開できるようにした。詰まったところの備忘録
参考資料:
Vue.jsを用いてサイト作成、AWS Amplify を使って自動デプロイについて
https://www.techpit.jp/courses/enrolled/881634gh-pagesへの表示について
https://www.shookuro.com/entry/2019/02/02/174655気を付けたところ:
gh-pagesでは、ソース変更しただけではサイトへの変更が反映されない。ソース変更
→ビルド
npm run build
→コミット
→プッシュの流れでやる必要がある
(ビルドしたファイルもコミット&プッシュしなければならない)詰まった:
Amplifyの方では
一旦失敗。
ログを見てみると
Error: Artifact directory doesn't exist: dist
とあったので、ビルドの設定を見てみた。
ビルドのデフォルト設定
artifacts:
baseDirectory: dist
files:
- '**/*'
は、gh-pages向けに出力先をvue.config.jsでdocsに変更していたため、ここをdocsとすることで
無事ビルドが通るようになった。
- 投稿日:2020-07-02T09:30:06+09:00
Vue.js・Laravel・OpenBDで本の画像を表示!書籍管理アプリで表紙の画像が表示できるようになりました。 #BookMark
どうも、たかふみです。
Vue.jsを使って本の画像表示をやってみました。
結果、これがこうなりまして、本の詳細画面に遷移した時に書籍画像が表示されるようになっています。Vue.js・Laravelでの画像表示については⬇︎こちらのチュートリアルのお陰でできました!
段階的に書かれていて分かりやすかったです!■Vue + Vue Router + Vuex + Laravelで写真共有アプリを作ろう
https://www.hypertextcandy.com/vue-laravel-tutorial-introduction/画面
コード
■blade(該当部分のみ)
show.blade.php<div class="card-header">詳細</div> <book-image-component></book-image-component>■VueComponent
BookImageComponent.vue<template> <div v-if="photoUrl" class="photo-detail bookimage"> <figure class="photo-detail__pane photo-detail__image"> <img :src="photoUrl" alt=""> </figure> </div> </template> <script> export default { data () { return { photoUrl: null } }, methods: { // URLから特定のパラメータを取得 getParam(name, url) { if (!url) url = window.location.href; name = name.replace(/[\[\]]/g, "\\$&"); var regex = new RegExp("[?&]" + name + "(=([^&#]*)|&|#|$)"), results = regex.exec(url); if (!results) return null; if (!results[2]) return ''; return decodeURIComponent(results[2].replace(/\+/g, " ")); }, // isbnコードから画像URLを取得 async fetchPhoto () { const isbn =this.getParam('isbn'); const response = await axios.get('https://api.openbd.jp/v1/get?isbn='+isbn) if(response.data[0] == null){ this.photoUrl = null } else { this.photoUrl = response.data[0].summary.cover; } } }, watch: { $route: { async handler () { await this.fetchPhoto() }, immediate: true } } } </script>コード説明
詳細画面
手順
1.どうやって画像表示するか考える
2.書籍の画像を表示するためのVueコンポーネントを作る
3.確認1.どうやって画像表示するか考える
今回、画像表示をするためにOpenBDという書籍情報取得APIを使いました。
このAPIではISBNコード(書籍のIDみたいなもの)をリクエストに書籍情報を取得することができます。レスポンス内に画像URLがあるので、これを使って画面に書籍画像を表示します。
※OpenBDについては後ほど記載します。ISBNコードはURL内のパラメータを取得してリクエストすることにしました。
2.書籍の画像を表示するためのVueコンポーネントを作る
書籍画像以外の情報についてはLaravelの方で実装を行っていたので、画像の部分だけコンポーネント化しています。
BookImageComponent.vue<template> <div v-if="photoUrl" class="photo-detail bookimage"> <figure class="photo-detail__pane photo-detail__image"> <img :src="photoUrl" alt=""> </figure> </div> </template> <script> export default { data () { return { photoUrl: null } }, methods: { // URLから特定のパラメータを取得 getParam(name, url) { if (!url) url = window.location.href; name = name.replace(/[\[\]]/g, "\\$&"); var regex = new RegExp("[?&]" + name + "(=([^&#]*)|&|#|$)"), results = regex.exec(url); if (!results) return null; if (!results[2]) return ''; return decodeURIComponent(results[2].replace(/\+/g, " ")); }, // isbnコードから画像URLを取得 async fetchPhoto () { const isbn =this.getParam('isbn'); const response = await axios.get('https://api.openbd.jp/v1/get?isbn='+isbn) if(response.data[0] == null){ this.photoUrl = null } else { this.photoUrl = response.data[0].summary.cover; } } }, watch: { $route: { async handler () { await this.fetchPhoto() }, immediate: true } } } </script>■URLから特定のパラメータを取得
URLからISBNコードを取得する必要があったので、下記のサイトで紹介されていたメソッドを使いました。
■Javascript でURLのパラメータを取得する方法
http://www-creators.com/archives/4463URLから特定のパラメータを取得getParam(name, url) { if (!url) url = window.location.href; name = name.replace(/[\[\]]/g, "\\$&"); var regex = new RegExp("[?&]" + name + "(=([^&#]*)|&|#|$)"), results = regex.exec(url); if (!results) return null; if (!results[2]) return ''; return decodeURIComponent(results[2].replace(/\+/g, " ")); }■isbnコードから画像URLを取得
上のメソッドを使い、ISBNコードを変数isbnへ入れてから、openBDのAPIへリクエストを行います。
response.data[0].summary.cover
で画像urlがレスポンスされるのでthis.photUrl
へ入れます。openBDへリクエストasync fetchPhoto () { const isbn =this.getParam('isbn'); const response = await axios.get('https://api.openbd.jp/v1/get?isbn='+isbn) if(response.data[0] == null){ this.photoUrl = null } else { this.photoUrl = response.data[0].summary.cover; } }■photUrlをvindして画像を表示
上のメソッドで画像urlがphotUrlへ入るので、画面上に書籍画像が表示されます。
photUrlをvindして画像を表示<figure class="photo-detail__pane photo-detail__image"> <img :src="photoUrl" alt=""> </figure>3.確認
表示されていれば成功です。
OpenBDとは
書籍情報の取得ができるAPIです。
書籍APIにはAmazonや楽天のAPIもあるのですが、「会員登録が不要・レスポンスが高速・レスポンスに画像URLを含んでいる」ことからOpenBDに決めました。■openBD
https://openbd.jp/まとめ:チュートリアルの復習にもなって良かった。
画像が表示できたことで見たい本が探しやすくなりました。
今回の実装でこちらのサイトを参考にしました。チュートリアルの復習にもなったので良かったです。本記事の書籍管理アプリ「BookMark」は引き続き開発中です!
⬇︎こちらから実際の画面を確認できます。
https://bookmark-tm.herokuapp.com/それでは!
参考URL
■Laravel + Vue での画像表示について
・Vue + Vue Router + Vuex + Laravelで写真共有アプリを作ろう
https://www.hypertextcandy.com/vue-laravel-tutorial-introduction/■書籍APIについて
・書籍検索APIのリクエストパラメータ・取得値考察
https://qiita.com/kanary/items/5ec45bbc01efd4388fdb・国立国会図書館サーチが提供する書影API
https://iss.ndl.go.jp/information/api/api-lists/thumbnail_info/
- 投稿日:2020-07-02T08:17:25+09:00
【Vue.js】まとめ_1
Vue.jsについて必要な知識をまとめました。
自身の備忘録として記載します。Vue.js
リアクティブプログラミングといいます。
『再度アクティブになる』ということで、データが更新されると自動的にデータを利用している画面表示も更新されます。Node.jsとnpm
本格的なWebアプリ開発になると、クライアント側だけでなくサーバ側の開発も合わせて行う必要があるためNode.jsを使用します。
Node.jsを利用するとサーバー側だけじゃなく、クライアント側もJavaScriptだけ作成できるようになります。
npmはパッケージ管理ツールで、Node.jsのプログラムに組み込まれている。Vue.jsでメッセージを表示
<head> <script src="https://unpkg.com/vue"></script> <head> <div id="sample"> {{ message }} </div> <script> var app = new Vue({ el : '#app', data : { message: 'Hello Vue!' } }) </script>上記コードでは、Vue.jsを使用してHello Vue!と表示させています。
参考書籍
Vue.js & Nuxt.js超入門
https://www.amazon.co.jp/dp/4798056596?tag=maftracking247988-22&linkCode=ure&creative=6339https://www.amazon.co.jp/dp/4798056596?tag=maftracking247988-22&linkCode=ure&creative=6339