- 投稿日:2020-06-23T23:59:52+09:00
bootsrtapVueの<b-navbar>で超簡単レスポンシブ対応ヘッダー!!(サンプルコードあり)
はじめに
私、完全な初学者でVue.jsを使用して簡単なポートフォリオサイトを作成しようとしていたところレスポンシブ対応がとても面倒臭く感じました。何か簡単にできないかと調べていたところ、発見した記事を参考にして作成したbootstrap4のクラスを使用しましたが、ハンバーガーメニューを押しても反応しなかっため、途方に暮れていました。しかし、根気よく調べているとbootstrapVueの
<b-navbar>
を使用すると簡単に、しかもちゃんと反応するものを作成できたので紹介します!最後にヘッダーのvueファイルをサンプルコードとして記載しています。一部表現が間違っている部分があるかもしれません。ご了承ください。
対象者
vue-cliでプロジェクトを作成してvueファイルを使用している方
プロジェクトの作り方やbootstrapVueを使用できるようにすることは他の方の記事を参考にしてください。
<b-navbar>
とはここから先の説明は基本的にはbootstrapVueの公式ドキュメント(https://bootstrap-vue.org/docs/components/navbar) に載っているものを扱います。
<b-navbar>
コンポーネントは、ブランディング、ナビゲーション、その他の要素を簡潔なヘッダーに配置するラッパーです。簡単に拡張でき、<b-collapse>
コンポーネントのおかげで、レスポンシブな動作を簡単に統合することができます。以下、公式ページに載っているサンプルコード↓に沿って、ハンバーガーメニューに必要な最低限の要素について説明をしていきます。
sample<div> <b-navbar toggleable="lg" type="dark" variant="info"> <b-navbar-brand href="#">NavBar</b-navbar-brand> <b-navbar-toggle target="nav-collapse"></b-navbar-toggle> <b-collapse id="nav-collapse" is-nav> <b-navbar-nav> <b-nav-item href="#">Link</b-nav-item> <b-nav-item href="#" disabled>Disabled</b-nav-item> </b-navbar-nav> <!-- Right aligned nav items --> <b-navbar-nav class="ml-auto"> <b-nav-form> <b-form-input size="sm" class="mr-sm-2" placeholder="Search"></b-form-input> <b-button size="sm" class="my-2 my-sm-0" type="submit">Search</b-button> </b-nav-form> <b-nav-item-dropdown text="Lang" right> <b-dropdown-item href="#">EN</b-dropdown-item> <b-dropdown-item href="#">ES</b-dropdown-item> <b-dropdown-item href="#">RU</b-dropdown-item> <b-dropdown-item href="#">FA</b-dropdown-item> </b-nav-item-dropdown> <b-nav-item-dropdown right> <!-- Using 'button-content' slot --> <template v-slot:button-content> <em>User</em> </template> <b-dropdown-item href="#">Profile</b-dropdown-item> <b-dropdown-item href="#">Sign Out</b-dropdown-item> </b-nav-item-dropdown> </b-navbar-nav> </b-collapse> </b-navbar> </div>説明
<b-navbar>
これで全体を囲む
プロパティ
toggleable=“lg”
ブレイクポイント(どの大きさでハンバーガーメニューに切り替えるか)決める
type=“dark"
色を決める
variant=“info"
色を決める(おそらく背景)typeとvariantに設定する文字はbootstrapお馴染みの文字なので調べると出てきます。コードの
dark
,info
の部分をお好みで変更してください
toggleableに関しても指定する文字はbootstrapお馴染みのsmなどのサイズ指定の文字なので調べたら出てくると思います。お好みでlg
の部分をお好みで変更してください。
<b-navbar-brand>
サイト全体のロゴを表示するコンポーネント
<a>
タグみたいに<b-navbar-brand>文字</b-navbar-brand>
で囲って文字を表示プロパティ
href=“”
orto=“”
vue-routerを使っている場合は
href
ではなく<router-link>
のプロパティ同様で指定
<b-navbar-toggle target="nav-collapse"></b-navbar-toggle>
ハンバーがメニューを押したら出てくる要素の指定(target)
プロパティ
target
適当な文字列を指定
その文字列をidプロパティで保持するタグをハンバーガーに追加
<b-navbar-nav>
ヘッダーのどこに配置するかを決めるためのコンポーネント
この小要素が主要な表示するものになる例
//デフォルトで左よせ(多分) <b-navber-nav> </b-navbar-nav> //ml-auto bootstrap4のクラス(margin-left:auto;の意味)を使用して右よせ <b-navber-nav class=“ml-auto"> </b-navbar-nav>
<b-navbar-item>
<b-navbar-nav>
が子要素として持てるタグの1つ
リンクのために使用使用法は<a>
タグと一緒
<b-navbar-brand>
同様urlの指定はhref=“”
,router-link
の指定はto=“"
で行う以上が使用するものになります。
他にも
<b-navber-nav>
が子要素として持てるとして<b-nav-item-dropdown>
、<b-nav-text>
、<b-nav-form>
などありますが、詳しく知りたい方は上記に載せたbootstrapVue公式を参照してください。最後にヘッダーを作成するサンプルコードを載せておきます。
下の例では vue-router でルーティングしています。また、ヘッダーを上部で固定しています。
サンプルコード
myheader.vue<template> <div class="myheader"> <b-navbar toggleable="sm" type="dark" variant="info"> <b-navbar-brand to=“/“>HOME</b-navbar-brand> <b-navbar-toggle target="nav-collapse"></b-navbar-toggle> <b-collapse id="nav-collapse" is-nav> <b-navbar-nav> <b-nav-item to="/about">about</b-nav-item> <b-nav-item to="/game">game</b-nav-item> <b-nav-item to="/paint">paint</b-nav-item> <b-nav-item to="/scrap">scrap</b-nav-item> </b-navbar-nav> </b-collapse> </b-navbar> </div> </template> <style lang="scss" scoped> .myheader { position: fixed; width: 100%; z-index: 1; } </style>
- 投稿日:2020-06-23T23:22:25+09:00
Vue CLI と kintone CLI の共存を探る(TypeScript 編)
Vue CLI
でセットアップしたプロジェクトでkintone CLI
を利用したカスタマイズ環境を作る目論見です。
どうにかこうにか形になりました。
ざっくり書いていますので読みづらいかも知れません。こちらは TypeScript 編です。
JavaScript 編は以下をご覧ください。Vue CLI と kintone CLI の共存を探る(JavaScript 編)
目的
Vue CLI
で作られるプロジェクトの整然さとkintone CLI
で行えるカスタマイズの開発やデプロイの簡易性を両立させる。
TypeScript
での開発を可能とし、@kintone/rest-api-client
を利用する。
kintone UI Component
は諦める。(React
でしか動かないので)
場合によりVuetify
の利用を検討する。フォーマッティング・lint に関しては以下の方針。
Vetur
はフォーマットを実行させず、シンタックスハイライトなどの役割に専念。
eslint
は静的解析のみ担当。コードフォーマットはしない。
コードフォーマットはPrettier
が実行。前提
Vue CLI
およびkintone CLI
がグローバルインストールされている事。npm install -g @vue/cli npm install -g git://github.com/kintone/kintone-cli.gitプロジェクト作成手順
Vue.js プロジェクトをセットアップする
Vue CLI
でプロジェクトを開始する。vue create vue-cli-kintone-cli-ts以下の選択肢で進める。
? Check the features needed for your project:
- Babel
- TypeScript
- Vuex
- CSS Pre-processors
- Linter / Formatter
- Unit Testing
? Use class-style component synytax?
Yes
? Use Babel alongside TypeScript (required for modern mode, auto-detected polyfills, transpiling JSX)?
Yes
? Pick a CSS pre-processor (PostCSS, Autoprefixer and CSS Modules are supported by default):
Sass/SCSS (with dart-sass)
? Pick a linter / formatter config:
ESLint + Prettier
? Pick additional lint features:
Lint on save
? Pick a unit testing solution:
Jest
? Where do you prefer placing config for Babel, ESLint, etc.?
In dedicated config fileskintone CLI でアプリを作成する
作成されたプロジェクトを VS Code で開き、ターミナルを起動する。
kintone CLI
でアプリをセットアップする。kintone-cli create-template
? What type of app you want to create ?
Customization
? Do you want to set authentication credentials ?
Yes
? What is your kintone domain ?
(サブドメイン).cybozu.com
? What is your kintone username ?
(ユーザー名)
? What is your kintone password ?
(パスワード)
? Do you use proxy ?
No
? Do you want to use React ?
No
? Do you want to use TypeScript ?
Yes
? Do you want to use webpack ?
Yes
? What is the entry for webpack ?
main.ts
? What is the app name ?
app
? Do you want to use @cybozu/eslint-config for syntax checking ?
No
? What is the app ID ?
(アプリ ID)
? What is the scope of customization ?
ALL
app
ディレクトリの下にソースが作成される。開発サーバーをインストールする
この手順だとローカルプレビュー用の
local-web-server
がインストールされないため、手動で追加する。
現時点(2020 年 6 月)での最新版は4.2
だが、このバージョンでは正しく動作しない模様。
kintone-cli
でインストールされるものと同じバージョンの2.6.1
をインストールする。yarn add -D local-web-server@2.6.1
その他の関連ツールをインストールする
core-js
が二重に入っている。
いったんアンインストールして最新版を追加。yarn remove core-js yarn add core-js
@kintone/rest-api-client
,@kintone/dts-gen
をインストールする。yarn add @kintone/rest-api-client yarn add -D @kintone/dts-gen
ESLint・Prettier の設定
以下を参考にする。
続・VSCode 上で vue ファイルに対して ESLint と Prettier が快適に動作する設定
VS Code で ESLint × Prettier のベストかも知れないプラクティスyarn add -D eslint-config-prettier
プロジェクトルート直下の
.eslintrc.js
を修正module.exports = { extends: [ // --- 省略 "prettier", ], };プロジェクトルート直下に
.eslintignore
ファイルを作成。
dist
フォルダを追跡から除外する。.eslintignore**/dist標準のフォーマッティングを無効化し、
Prettier
が全て担当するようにする。
.vscode/settings.json
に設定を加える。.vscode/settings.json{ "javascript.format.enable": false, "typescript.format.enable": false, "vetur.format.enable": false, "editor.codeActionsOnSave": { "source.fixAll.eslint": true } }
.prettierrc
を作る。
設定はお好みで。.prettierrc{ "semi": false, "singleQuote": true }ディレクトリ構成
プロジェクトルート直下の
src
以下のファイルをapp/source
に移動。
app/tests/unit
フォルダを作成。
残ったsrc
とpublic
、tests
は不要なので削除。
app/source/main.ts
をとりあえず以下のようにするapp/source/main.tsimport Vue from "vue"; import App from "./App.vue"; import store from "./store"; Vue.config.productionTip = false; kintone.events.on("app.record.index.show", (event) => { console.log("Hello from kintone CLI"); const elem: Element = kintone.app.getHeaderSpaceElement() as Element; new Vue({ store, render: (h) => h(App), }).$mount(elem); return event; });tsconfig.json の設定
プロジェクトルート直下と
app
の下に存在する。
プロジェクトルート直下の設定に寄せる。
app
の下にある記述をプロジェクトルート直下のtsconfig.json
にマージする。
この際include
やpaths
、typeRoots
のパスを調整する。
最終的には以下の通りとなる。tsconfig.json{ "compilerOptions": { "target": "esnext", "module": "esnext", "strict": true, "jsx": "preserve", "importHelpers": true, "moduleResolution": "node", "experimentalDecorators": true, "esModuleInterop": true, "allowSyntheticDefaultImports": true, "sourceMap": true, "baseUrl": ".", "typeRoots": ["node_modules/@types", "**/source/*.d.ts"], "types": ["webpack-env", "jest"], "paths": { "@/*": ["~/*"] }, "lib": ["esnext", "dom", "dom.iterable", "scripthost"] }, "include": [ "**/source/**/*.ts", "**/source/**/*.tsx", "**/source/**/*.vue", "**/tests/**/*.ts", "**/tests/**/*.tsx" ], "exclude": ["node_modules"] }
app
下のtsconfig.json
は削除ないしリネーム。babel の設定
ビルドするために
@babel/plugin-proposal-decorators
のインストールが必要。yarn add -D @babel/plugin-proposal-decorators
プロジェクトルート直下に
babel.config.js
が、app
の下に.babelrc
が存在する。
プロジェクトルート直下のbabel.config.js
にapp/.babelrc
の内容をマージする。
以下のようになる。babel.config.jsmodule.exports = { plugins: [ [ "@babel/plugin-proposal-decorators", { legacy: true, }, ], [ "@babel/plugin-proposal-class-properties", { loose: true, }, ], "@babel/plugin-syntax-dynamic-import", ], presets: [ "@vue/cli-plugin-babel/preset", [ "@babel/preset-env", { useBuiltIns: "usage", corejs: { version: 3, proposals: true, }, }, ], ], };その後
app/.babelrc
は削除ないしリネーム。Webpack の設定
.vue
ファイルをビルドするためにvue-loader
,vue-template-compiler
,ts-loader
,url-loader
,file-loader
をインストールする。
またwebpack
の設定は開発ビルドとプロダクションビルドで設定を変えたいので、webpack-merge
もインストールする。
加えて、プロダクションビルドではミニファイも行うので、terser-webpack-plugin
もインストールする。yarn add -D vue-loader vue-template-compiler ts-loader url-loader file-loader webpack-merge terser-webpack-plugin
webpack
の設定はapp
以下のものを使用する。
app/webpack.config.js
をapp/webpack.common.js
にリネームし、内容を以下のようにする。app/webpack.common.jsconst path = require("path"); const VueLoaderPlugin = require("vue-loader/lib/plugin"); module.exports = { entry: path.resolve(__dirname, "./source/main.ts"), resolve: { extensions: [".ts", ".tsx", ".vue", ".js"], }, output: { path: path.resolve(__dirname, "./dist"), filename: `${path.basename(__dirname)}.min.js`, }, module: { rules: [ { test: /\.vue$/, use: { loader: "vue-loader", options: { loaders: { js: { loader: "babel-loader", }, }, }, }, }, { test: /.ts?$/, exclude: /node_modules/, use: { loader: "ts-loader", options: { transpileOnly: true, appendTsSuffixTo: ["\\.vue$"], happyPackMode: false, }, }, }, { test: /.css$/, use: ["style-loader", "css-loader"], }, { test: /\.(jpe?g|png|gif|svg|ico)(\?.+)?$/, use: { loader: "url-loader", options: { esModule: false, limit: 10000, fallback: { loader: "file-loader", options: { name: "img/[name].[ext]", }, }, }, }, }, ], }, performance: { maxEntrypointSize: 10000000, maxAssetSize: 10000000, }, plugins: [new VueLoaderPlugin()], };開発ビルドの設定
app/webpack.dev.js
は以下の通りにする。app/webpack.dev.jsconst merge = require("webpack-merge"); const common = require("./webpack.common.js"); module.exports = merge(common, { mode: "development", });プロダクションビルドの設定
app/webpack.prod.js
は以下の通りにする。app/webpack.prod.jsconst merge = require("webpack-merge"); const common = require("./webpack.common.js"); const TerserPlugin = require("terser-webpack-plugin"); module.exports = merge(common, { mode: "production", optimization: { minimize: true, minimizer: [ new TerserPlugin({ terserOptions: { compress: { drop_console: true } }, }), ], }, });新たに
app/webpack.config.js
を作り、以下のようにする。
このファイルでビルドターゲットを判定して、適切なファイルをロードするようにする。app/webpack.config.jsmodule.exports = (env, argv) => { const mode = argv.mode.includes("development") ? "dev" : "prod"; return require(`./webpack.${mode}.js`); };Jest の設定
特にない。
必要に応じてプロジェクトルート直下のjest.config.js
を編集すればよい。package.json の設定
コマンドの入力を簡略化するため
scripts
を以下のようにする。
webpack の設定ファイルもここでコントロールする。package.json"scripts": { "dev": "ws --port ****", "serve-app": "kintone-cli dev --app-name app --watch --localhost", "devel-app": "webpack --mode development --config app/webpack.config.js", "build-app": "webpack --mode production --config app/webpack.config.js", "deploy-app": "kintone-cli deploy --app-name app", "test:unit": "jest" },
ws --port ****
は任意のポート番号。
以下の記事で解説している。
kintone CLI をざっくり試す.gitignore の設定
これまでの流れで
app/auth.json
は含まれているはず。
app/dist
も弾くようにする。
その上で、今後仮にapp
が増えても大丈夫なようにする。以下の通り修正。
.gitignre*/auth.json */dist
.vscode/settings.json
は共有したいので、.vscode
の行は削除する。ここまでで開発準備は終了。
あとはひたすらに開発に注力する。開発フェーズ
開発・テスト
実際の開発は
app/source/
以下のファイルに対して行っていく事になる。開発モード(ローカルサーバ)で起動
yarn serve-appローカルサーバへの参照が kintone アプリに適用され、テストが行えるようになる。
単体テストは以下のように実行。
yarn test:unit
テストファイルは
app/tests/unit/
以下に**.spec.ts
のファイル名パターンで記述する。ビルド
yarn build-app
app
フォルダの下にdist
フォルダが作成されファイルがビルドされる。
ビルドしたファイルを手動で運用環境に適用したい場合に使う。
webpack.prod.js
ではTerserPlugin
によりミニファイとconsole
の除去が行われる。デプロイ
yarn deploy-appビルドとデプロイを同時に実行するコマンド。
ビルドが実行され、終了後に運用環境にデプロイされる。2 つめ以降のアプリのカスタマイズを作る場合
プロジェクトが複数のアプリカスタマイズで構成される場合、いくつかアプローチがある。
kintone-cli create-template を使う
kintone CLI
的には王道パターンではある。kintone-cli create-template --app-name (新しいアプリ名)と実行し、カスタマイズを新規で作成する。
作成されたフォルダに、既存のアプリカスタマイズのファイルをかぶせてやる。(要微修正)
この方法だと改めて依存モジュール類を再取得しに行く動作をするため、時間が掛かる上にせっかく整えた
package.json
がまた汚れてしまう。
(core-js
が二重になってしまうなど)
従って、決して良いやり方ではないと思われるが、以下の方法の方が簡単。既存のアプリをコピーする
既に作成済みのアプリカスタマイズの構成ファイルをコピーして整えていくパターン。
以下、作成済みのアプリカスタマイズをapp
、 新しいアプリカスタマイズをsecond-app
として説明する。フォルダ・ファイル構成
プロジェクトルート直下に新しいフォルダ
second-app
を作成する。
その下に、source
フォルダ、tests
フォルダを作成する。
second-app/source/
以下に必要に応じて下記フォルダを作る。
- assets
- components
- css
- js
- store
app/
の以下のファイルをsecond-app/
フォルダにコピーする。
- auth.json
- config.json
- webpack.common.js
- webpack.config.js
- webpack.dev.js
- webpack.prod.js
app/source/
の以下のファイルをsecond-app/source/
フォルダにコピーする。
- global.d.ts
- shims-vue.d.ts
- shims-tsx.d.ts
認証情報
新しいアプリカスタマイズの認証情報が異なる場合は
second-app/auth.json
を編集する。アプリカスタマイズ情報
second-app/config.json
を開き、以下の部分を編集する。second-app/config.json{ "appID": **, // カスタマイズを適用するアプリID "appName": "second-app", "type": "Customization", "scope": "ALL", "uploadConfig": { "desktop": { "js": ["second-app/dist/second-app.min.js"], "css": [] }, "mobile": { "js": ["second-app/dist/second-app.min.js"] } } }基本的には編集前に
app
となっていたものをsecond-app
に置き換えれば良い。package.json の修正
package.json
のscripts
にコマンドを追加する。作成済みの
serve-app
,devel-app
,build-app
,deploy-app
をコピーし、app
の部分をsecond-app
に変えてやる。
合わせると以下の通りになる。package.json"scripts": { "dev": "ws --port 8800", "serve-app": "kintone-cli dev --app-name app --watch --localhost", "devel-app": "webpack --mode development --config app/webpack.config.js", "build-app": "webpack --mode production --config app/webpack.config.js", "deploy-app": "kintone-cli deploy --app-name app", "serve-second-app": "kintone-cli dev --app-name second-app --watch --localhost", "devel-second-app": "webpack --mode development --config second-app/webpack.config.js", "build-second-app": "webpack --mode production --config second-app/webpack.config.js", "deploy-second-app": "kintone-cli deploy --app-name second-app", "test:unit": "jest" },あとは元のアプリカスタマイズを参考に
main.ts
、App.vue
、components/**.vue
等を作り込んでいく。それなりに作業が多くオペミスが起こりやすいので注意が必要。
Vuetify を利用する場合
Vue CLI
でインストールし、その成果をapp
以下に移してやると言う流れ。
※この流れでは IE11 で正しく動作しない。IE11 が要件に入らない場合のみ採用できる。vue add vuetifyインストールが始まる。
道中でプリセットの選択を求められる。
デフォルトで良い。
? Choose a preset:
Deafult (recommended)
public/index.html
が存在していないと最後にエラーが出るが、インストール自体は正常に行われているので問題ない。プロジェクトルート直下の
src
以下にファイルが作成される。
src/App.vue
をapp/source/App.vue
に上書き。
src/components/HelloWorld.vue
をapp/source/components/HelloWorld.vue
に上書き。
src/assets/Logo.svg
をapp/source/assets/
に移動。
src/plugins
フォルダをapp/source/
に移動。
src
フォルダは不要なので削除。
app/plugins/vuetify.ts
を以下のように修正。app/plugins/vuetify.tsimport "@mdi/font/css/materialdesignicons.css"; import Vue from "vue"; import Vuetify from "vuetify/lib"; Vue.use(Vuetify); export default new Vuetify({ icons: { iconfont: "mdi", }, });
app/source/main.ts
を以下のように修正する。app/source/main.tsimport Vue from "vue"; import App from "./App.vue"; import store from "./store"; import vuetify from "./plugins/vuetify"; Vue.config.productionTip = false; kintone.events.on("app.record.index.show", (event) => { console.log("Hello from kintone CLI"); const elem: Element = kintone.app.getHeaderSpaceElement() as Element; new Vue({ store, vuetify, render: (h) => h(App), }).$mount(elem); return event; });
app/webpack.coomon.js
に以下の記述を追加。app/source/webpack.common.jsconst VuetifyLoaderPlugin = require("vuetify-loader/lib/plugin"); module.exports = { // 省略 module: { rules: [ // 省略 // CSS に対するルールの次に記述する { test: /\.s(c|a)ss$/, use: [ 'vue-style-loader', 'css-loader', { loader: 'sass-loader', options: { implementation: require('sass'), sassOptions: { fiber: require('fibers'), indentedSyntax: true // optional } } } ] }, // 省略 // いちばん下に追加する { test: /\.(woff|woff2|eot|ttf)(\?.+)?$/, use: { loader: 'url-loader', options: { esModule: false, limit: 1000000 } } } ] } plugins: [ new VueLoaderPlugin(), // 既に記述済み new VuetifyLoaderPlugin(), ], };追加のライブラリをインストールする。
yarn add -D vue-style-loader fibers deepmerge @mdi/font
これで
Vuetify
が表示できるようになる。雑感
Vue CLI
とkintone CLI
を良い感じに共存させようと言う考えから始めたが、あとでライブラリを追加したり多くの設定ファイルに手を入れたりファイルを移動させたりと、結局のところ両者の良さを良い感じに活かすと言うよりはどうにかこうにか妥協点を見出したと言う形になったように思う。
とは言え、Vue.js
の環境をゼロから(Vue CLI
を使わずに)作成するのは今となってはもう面倒この上ないし、kintone CLI
のコマンド一発でデプロイできる便利さは開発工数の削減に効果があるのは間違いなく、無理っくり感が否めない構成とは言えテンプレート化できたのは十分なメリットをもたらすのではなかろうか。※今回の成果は近日中に GitHub にアップする予定です。
参考
VS Code に Prettier・ESLint・Stylelint を導入してファイル保存時にコードを自動整形させる方法
続・VSCode 上で vue ファイルに対して ESLint と Prettier が快適に動作する設定
VS Code で ESLint × Prettier のベストかも知れないプラクティス
kintone CLI をざっくり試す
- 投稿日:2020-06-23T23:22:12+09:00
Vue CLI と kintone CLI の共存を探る(JavaScript 編)
Vue CLI
でセットアップしたプロジェクトでkintone CLI
を利用したカスタマイズ環境を作る目論見です。
どうにかこうにか形になりました。
ざっくり書いていますので読みづらいかも知れません。こちらは JavaScript 編です。
TypeScript 編は以下をご覧ください。Vue CLI と kintone CLI の共存を探る(TypeScript 編)
目的
Vue CLI
で作られるプロジェクトの整然さとkintone CLI
で行えるカスタマイズの開発やデプロイの簡易性を両立させる。
@kintone/rest-api-client
を利用する。
kintone UI Component
は諦める。(React
でしか動かないので)
場合によりVuetify
の利用を検討する。フォーマッティング・lint に関しては以下の方針。
Vetur
はフォーマットを実行させず、シンタックスハイライトなどの役割に専念。
eslint
は静的解析のみ担当。コードフォーマットはしない。
コードフォーマットはPrettier
が実行。前提
Vue CLI
およびkintone CLI
がグローバルインストールされている事。npm install -g @vue/cli npm install -g git://github.com/kintone/kintone-cli.gitプロジェクト作成手順
Vue.js プロジェクトをセットアップする
Vue CLI
でプロジェクトを開始する。vue create vue-cli-kintone-cli-js以下の選択肢で進める。
? Check the features needed for your project:
- Babel
- Vuex
- CSS Pre-processors
- Linter / Formatter
- Unit Testing
? Pick a CSS pre-processor (PostCSS, Autoprefixer and CSS Modules are supported by default):
Sass/SCSS (with dart-sass)
? Pick a linter / formatter config:
ESLint + Prettier
? Pick additional lint features:
Lint on save
? Pick a unit testing solution:
Jest
? Where do you prefer placing config for Babel, ESLint, etc.?
In dedicated config fileskintone CLI でアプリを作成する
作成されたプロジェクトを VS Code で開き、ターミナルを起動する。
kintone CLI
でアプリをセットアップする。kintone-cli create-template
? What type of app you want to create ?
Customization
? Do you want to set authentication credentials ?
Yes
? What is your kintone domain ?
(サブドメイン).cybozu.com
? What is your kintone username ?
(ユーザー名)
? What is your kintone password ?
(パスワード)
? Do you use proxy ?
No
? Do you want to use React ?
No
? Do you want to use TypeScript ?
No
? Do you want to use webpack ?
Yes
? What is the entry for webpack ?
main.js
? What is the app name ?
app
? Do you want to use @cybozu/eslint-config for syntax checking ?
No
? What is the app ID ?
(アプリ ID)
? What is the scope of customization ?
ALL
app
ディレクトリの下にソースが作成される。開発サーバーをインストールする
この手順だとローカルプレビュー用の
local-web-server
がインストールされないため、手動で追加する。
現時点(2020 年 6 月)での最新版は4.2
だが、このバージョンでは正しく動作しない模様。
kintone-cli
でインストールされるものと同じバージョンの2.6.1
をインストールする。yarn add -D local-web-server@2.6.1
その他の関連ツールをインストールする
core-js
が二重に入っている。
いったんアンインストールして最新版を追加。yarn remove core-js yarn add core-js
@kintone/rest-api-client
をインストールする。yarn add @kintone/rest-api-clientESLint・Prettier の設定
以下を参考にする。
続・VSCode 上で vue ファイルに対して ESLint と Prettier が快適に動作する設定
VS Code で ESLint × Prettier のベストかも知れないプラクティスyarn add -D eslint-config-prettier
プロジェクトルート直下の
.eslintrc.js
を修正module.exports = { extends: [ // --- 省略 "prettier", ], // --- 省略 globals: { kintone: true, event: true, }, };プロジェクトルート直下に
.eslintignore
ファイルを作成。
dist
フォルダを追跡から除外する。.eslintignore**/dist標準のフォーマッティングを無効化し、
Prettier
が全て担当するようにする。
.vscode/settings.json
に設定を加える。.vscode/settings.json{ "javascript.format.enable": false, "typescript.format.enable": false, "vetur.format.enable": false, "editor.codeActionsOnSave": { "source.fixAll.eslint": true } }
.prettierrc
を作る。
設定はお好みで。.prettierrc{ "semi": false, "singleQuote": true }ディレクトリ構成
プロジェクトルート直下の
src
以下のファイルをapp/source
に移動。
app/tests/unit
フォルダを作成。
残ったsrc
とpublic
、tests
は不要なので削除。
app/source/main.js
をとりあえず以下のようにするapp/source/main.jsimport Vue from "vue"; import App from "./App.vue"; import store from "./store"; Vue.config.productionTip = false; kintone.events.on("app.record.index.show", (event) => { console.log("Hello from kintone CLI"); const elem = kintone.app.getHeaderSpaceElement(); new Vue({ store, render: (h) => h(App), }).$mount(elem); return event; });babel の設定
プロジェクトルート直下に
babel.config.js
が、app
の下に.babelrc
が存在する。
プロジェクトルート直下のbabel.config.js
にapp/.babelrc
の内容をマージする。
以下のようになる。babel.config.js{ "plugins": [ "@babel/plugin-proposal-class-properties", "@babel/plugin-syntax-dynamic-import" ], "presets": [ "@vue/cli-plugin-babel/preset", [ "@babel/preset-env", { "useBuiltIns": "usage", "corejs": { "version": 3, "proposals": true } } ] ] }その後
app/.babelrc
は削除ないしリネーム。webpack の設定
.vue
ファイルをビルドするためにvue-loader
,vue-template-compiler
,url-loader
,file-loader
をインストールする。
またwebpack
の設定は開発ビルドとプロダクションビルドで設定を変えたいので、webpack-merge
もインストールする。
加えて、プロダクションビルドではミニファイも行うので、terser-webpack-plugin
もインストールする。yarn add -D vue-loader vue-template-compiler url-loader file-loader webpack-merge terser-webpack-plugin
webpack
の設定はapp
以下のものを使用する。
app/webpack.config.js
をapp/webpack.common.js
にリネームし、内容を以下のようにする。app/webpack.common.jsconst path = require("path"); const VueLoaderPlugin = require("vue-loader/lib/plugin"); module.exports = { entry: path.resolve(__dirname, "./source/main.js"), resolve: { extensions: [".ts", ".tsx", ".vue", ".js"], }, output: { path: path.resolve(__dirname, "./dist"), filename: `${path.basename(__dirname)}.min.js`, }, module: { rules: [ { test: /\.vue$/, use: { loader: "vue-loader", options: { loaders: { js: { loader: "babel-loader", }, }, }, }, }, { test: /.js?$/, exclude: /node_modules/, use: { loader: "babel-loader", }, }, { test: /.css$/, use: ["style-loader", "css-loader"], }, { test: /\.(jpe?g|png|gif|svg|ico)(\?.+)?$/, use: { loader: "url-loader", options: { esModule: false, limit: 10000, fallback: { loader: "file-loader", options: { name: "img/[name].[ext]", }, }, }, }, }, ], }, performance: { maxEntrypointSize: 10000000, maxAssetSize: 10000000, }, plugins: [new VueLoaderPlugin()], };開発ビルドの設定
app/webpack.dev.js
は以下の通りにする。app/webpack.dev.jsconst merge = require("webpack-merge"); const common = require("./webpack.common.js"); module.exports = merge(common, { mode: "development", });プロダクションビルドの設定
app/webpack.prod.js
は以下の通りにする。app/webpack.prod.jsconst merge = require("webpack-merge"); const common = require("./webpack.common.js"); const TerserPlugin = require("terser-webpack-plugin"); module.exports = merge(common, { mode: "production", optimization: { minimize: true, minimizer: [ new TerserPlugin({ terserOptions: { compress: { drop_console: true } }, }), ], }, });新たに
app/webpack.config.js
を作り、以下のようにする。
このファイルでビルドターゲットを判定して、適切なファイルをロードするようにする。app/webpack.config.jsmodule.exports = (env, argv) => { const mode = argv.mode.includes("development") ? "dev" : "prod"; return require(`./webpack.${mode}.js`); };Jest の設定
特にない。
必要に応じてプロジェクトルート直下のjest.config.js
を編集すればよい。package.json の設定
コマンドの入力を簡略化するため
scripts
を以下のようにする。
webpack の設定ファイルもここでコントロールする。package.json"scripts": { "dev": "ws --port ****", "serve-app": "kintone-cli dev --app-name app --watch --localhost", "devel-app": "webpack --mode development --config app/webpack.config.js", "build-app": "webpack --mode production --config app/webpack.config.js", "deploy-app": "kintone-cli deploy --app-name app", "test:unit": "jest" },
ws --port ****
は任意のポート番号。
以下の記事で解説している。
kintone CLI をざっくり試す.gitignore の設定
これまでの流れで
app/auth.json
は含まれているはず。
app/dist
も弾くようにする。
その上で、今後仮にapp
が増えても大丈夫なようにする。以下の通り修正。
.gitignre*/auth.json */dist
.vscode/settings.json
は共有したいので、.vscode
の行は削除する。ここまでで開発準備は終了。
あとはひたすらに開発に注力する。開発フェーズ
開発・テスト
実際の開発は
app/source/
以下のファイルに対して行っていく事になる。開発モード(ローカルサーバ)で起動
yarn serve-appローカルサーバへの参照が kintone アプリに適用され、テストが行えるようになる。
単体テストは以下のように実行。
yarn test:unit
テストファイルは
app/tests/unit/
以下に**.spec.js
のファイル名パターンで記述する。ビルド
yarn build-app
app
フォルダの下にdist
フォルダが作成されファイルがビルドされる。
ビルドしたファイルを手動で運用環境に適用したい場合に使う。
webpack.prod.js
ではTerserPlugin
によりミニファイとconsole
の除去が行われる。デプロイ
yarn deploy-appビルドとデプロイを同時に実行するコマンド。
ビルドが実行され、終了後に運用環境にデプロイされる。2 つめ以降のアプリのカスタマイズを作る場合
プロジェクトが複数のアプリカスタマイズで構成される場合、いくつかアプローチがある。
kintone-cli create-template を使う
kintone CLI
的には王道パターンではある。kintone-cli create-template --app-name (新しいアプリ名)と実行し、カスタマイズを新規で作成する。
作成されたフォルダに、既存のアプリカスタマイズのファイルをかぶせてやる。(要微修正)
この方法だと改めて依存モジュール類を再取得しに行く動作をするため、時間が掛かる上にせっかく整えた
package.json
がまた汚れてしまう。
(core-js
が二重になってしまうなど)
従って、決して良いやり方ではないと思われるが、以下の方法の方が簡単。既存のアプリをコピーする
既に作成済みのアプリカスタマイズの構成ファイルをコピーして整えていくパターン。
以下、作成済みのアプリカスタマイズをapp
、 新しいアプリカスタマイズをsecond-app
として説明する。フォルダ・ファイル構成
プロジェクトルート直下に新しいフォルダ
second-app
を作成する。
その下に、source
フォルダ、tests
フォルダを作成する。
second-app/source/
以下に必要に応じて下記フォルダを作る。
- assets
- components
- css
- js
- store
app/
の以下のファイルをsecond-app/
フォルダにコピーする。
- auth.json
- config.json
- webpack.common.js
- webpack.config.js
- webpack.dev.js
- webpack.prod.js
認証情報
新しいアプリカスタマイズの認証情報が異なる場合は
second-app/auth.json
を編集する。アプリカスタマイズ情報
second-app/config.json
を開き、以下の部分を編集する。second-app/config.json{ "appID": **, // カスタマイズを適用するアプリID "appName": "second-app", "type": "Customization", "scope": "ALL", "uploadConfig": { "desktop": { "js": ["second-app/dist/second-app.min.js"], "css": [] }, "mobile": { "js": ["second-app/dist/second-app.min.js"] } } }基本的には編集前に
app
となっていたものをsecond-app
に置き換えれば良い。package.json の修正
package.json
のscripts
にコマンドを追加する。作成済みの
serve-app
,devel-app
,build-app
,deploy-app
をコピーし、app
の部分をsecond-app
に変えてやる。
合わせると以下の通りになる。package.json"scripts": { "dev": "ws --port 8800", "serve-app": "kintone-cli dev --app-name app --watch --localhost", "devel-app": "webpack --mode development --config app/webpack.config.js", "build-app": "webpack --mode production --config app/webpack.config.js", "deploy-app": "kintone-cli deploy --app-name app", "serve-second-app": "kintone-cli dev --app-name second-app --watch --localhost", "devel-second-app": "webpack --mode development --config second-app/webpack.config.js", "build-second-app": "webpack --mode production --config second-app/webpack.config.js", "deploy-second-app": "kintone-cli deploy --app-name second-app", "test:unit": "jest" },あとは元のアプリカスタマイズを参考に
main.js
、App.vue
、components/**.vue
等を作り込んでいく。それなりに作業が多くオペミスが起こりやすいので注意が必要。
Vuetify を利用する場合
Vue CLI
でインストールし、その成果をapp
以下に移してやると言う流れ。
※この流れでは IE11 で正しく動作しない。IE11 が要件に入らない場合のみ採用できる。vue add vuetifyインストールが始まる。
道中でプリセットの選択を求められる。
デフォルトで良い。
? Choose a preset:
Deafult (recommended)
public/index.html
が存在していないと最後にエラーが出るが、インストール自体は正常に行われているので問題ない。プロジェクトルート直下の
src
以下にファイルが作成される。
src/App.vue
をapp/source/App.vue
に上書き。
src/components/HelloWorld.vue
をapp/source/components/HelloWorld.vue
に上書き。
src/assets/Logo.svg
をapp/source/assets/
に移動。
src/plugins
フォルダをapp/source/
に移動。
src
フォルダは不要なので削除。
app/plugins/vuetify.js
を以下のように修正。app/plugins/vuetify.jsimport "@mdi/font/css/materialdesignicons.css"; import Vue from "vue"; import Vuetify from "vuetify/lib"; Vue.use(Vuetify); export default new Vuetify({ icons: { iconfont: "mdi", }, });
app/source/main.js
を以下のように修正する。app/source/main.jsimport Vue from "vue"; import App from "./App.vue"; import store from "./store"; import vuetify from "./plugins/vuetify"; Vue.config.productionTip = false; kintone.events.on("app.record.index.show", (event) => { console.log("Hello from kintone CLI"); const elem = kintone.app.getHeaderSpaceElement(); new Vue({ store, vuetify, render: (h) => h(App), }).$mount(elem); return event; });
app/webpack.coomon.js
に以下の記述を追加。app/source/webpack.common.jsconst VuetifyLoaderPlugin = require("vuetify-loader/lib/plugin"); module.exports = { // 省略 module: { rules: [ // 省略 // CSS に対するルールの次に記述する { test: /\.s(c|a)ss$/, use: [ 'vue-style-loader', 'css-loader', { loader: 'sass-loader', options: { implementation: require('sass'), sassOptions: { fiber: require('fibers'), indentedSyntax: true // optional } } } ] }, // 省略 // いちばん下に追加する { test: /\.(woff|woff2|eot|ttf)(\?.+)?$/, use: { loader: 'url-loader', options: { esModule: false, limit: 1000000 } } } ] } plugins: [ new VueLoaderPlugin(), // 既に記述済み new VuetifyLoaderPlugin(), ], };追加のライブラリをインストールする。
yarn add -D vue-style-loader fibers deepmerge @mdi/font
これで
Vuetify
が表示できるようになる。雑感
Vue CLI
とkintone CLI
を良い感じに共存させようと言う考えから始めたが、あとでライブラリを追加したり多くの設定ファイルに手を入れたりファイルを移動させたりと、結局のところ両者の良さを良い感じに活かすと言うよりはどうにかこうにか妥協点を見出したと言う形になったように思う。
とは言え、Vue.js
の環境をゼロから(Vue CLI
を使わずに)作成するのは今となってはもう面倒この上ないし、kintone CLI
のコマンド一発でデプロイできる便利さは開発工数の削減に効果があるのは間違いなく、無理っくり感が否めない構成とは言えテンプレート化できたのは十分なメリットをもたらすのではなかろうか。※今回の成果は近日中に GitHub にアップする予定です。
参考
VS Code に Prettier・ESLint・Stylelint を導入してファイル保存時にコードを自動整形させる方法
続・VSCode 上で vue ファイルに対して ESLint と Prettier が快適に動作する設定
VS Code で ESLint × Prettier のベストかも知れないプラクティス
kintone CLI をざっくり試す
- 投稿日:2020-06-23T21:12:39+09:00
Vuejs 子コンポーネントのplaceholder属性の初期値を親コンポーネント側で入力した値にするには
上の画像のようなTodolistを作成中です。編集ボタンを押すと内容が編集できるといった仕組みになっています。
上の画像が編集画面です。初期値ですでに入力されていた内容と設定されていた日付が表示されてます。
親コンポーネント(TodoList.vue)<div> <b-container fluid class="bv-example-row"> <b-row> <b-card border-variant="secondary" footer-border-variant="secondary" align="center" v-for="todo in todos" :key="todo.id" :content="todo.content" :timelimit="todo.timelimit" > <template v-slot:header> <b-button variant="outlineinfo" @click="testOpenModal(todo)"> 編集 </b-button> <b-button variant="outline-danger"> 削除 </b-button> <b-button variant="outline-success"> 完了 </b-button> </template> <b-card-text>{{ todo.content }}</b-card-text> <template v-slot:footer> 期限:{{ todo.timelimit }} </template> </b-card> </b-row> <transition name="modal"> <show-modal :id="todoId" :timelimit="todoTimelimit" :content="todoContent" v-if="showContent" @close="modalClose" /> </transition> </b-container> </div> <script> import ShowModal from './ShowModal' export default { name: 'todo-list', components: { ShowModal, }, data () { return { showModal: false, editUserContent: '', showContent: false, todoItem: '' } }, computed: { todos () { return this.$store.state.todos } }, methods: { testOpenModal (todo) { this.showContent = true this.todoId = todo.id this.todoTimelimit = todo.timelimit this.todoContent = todo.content }, modalClose () { this.showContent = false } } } </script>上記のような配列で回して表示しているTodoListです。show-modalが子コンポーネントでモーダルウィンドウを表示させるコンポーネントです。
<b-button variant="outlineinfo" @click="testOpenModal(todo)"> 編集 </b-button>上のコードでモーダル画面を発火させる文です。引数にtodoを渡しています。
todoの中には内容と日付などが入っています。methods: { testOpenModal (todo) { // モーダルをウィンドウを表示させる this.showContent = true // todoIdにtodoのなかのidを代入 this.todoId = todo.id this.todoTimelimit = todo.timelimit this.todoContent = todo.content },上のコードでモーダルを表示させ
this.xxxx = todo.xx
でtodoのなかの値を代入しています。<show-modal :id="todoId" :timelimit="todoTimelimit" :content="todoContent" v-if="showContent" @close="modalClose" />v-bindで先ほど代入してあげた値をshow-modal側に渡しています。
<template> <div> <div class="modal-mask"> <div class="modal-wrapper" @click.self="$emit('close')"> <div class="modal-container"> <div class="modal-header"> {{ id }}:編集 {{ timelimit }} </div> // v-model="content"でも初期値が入るし:value="content"でも入る <div class="modal-form"> <b-input-group class="mb-2"> <b-form-input type="text" placeholder="やりたいことを入力してください" :value="content" @input="onInput" > </b-form-input> <b-form-datepicker class="mb-2" placeholder="何日までに行いますか?" :value="timelimit" > </b-form-datepicker> </b-input-group> </div> <div class="modal-footer"> <button @click="editTodo">OK</button> <button @click="$emit('close')">Close</button> </div> </div> </div> </div> </div> </template> <script> export default { name: 'show-modal', props: ['id', 'timelimit', 'content'], deta () { return { closeModal: false, timelimit: '', editContent: '', } }, methods: { editTodo() { this.$store.commit ('editTodo',{ editContent: this.editContent }) }, onInput(e) { this.content = e.target.value this.$emit('content', this.content) } }, computed: { todos () { return this.$store.state.todos } } } </script>
- 投稿日:2020-06-23T18:35:00+09:00
vuexでcomponentなform、親子相互bind
git
https://github.com/kujiy/vuex-study/tree/a2049726e7e6a2c62c1a1ba1d0cef7940473c6b9やりたいこと
親子相互にbindしたい。
どのinput boxに入れても全部リアクティブに動く状態。
vuexのcomputedでやる場合はget/setが必要
vuex の modulesを使っています
main.js
import Vue from 'vue' import Vuex from 'vuex' import App from './App.vue' Vue.use(Vuex) // import store from './store.js' import store from './store_module.js' Vue.config.productionTip = false new Vue({ render: h => h(App), store, }).$mount('#app')store.js
他の勉強もしてたのでゴミだらけimport Vue from 'vue' import Vuex from 'vuex' Vue.use(Vuex) const store = new Vuex.Store({ modules: { moduleA: { namespaced: true, state: { count: 0, mymsgDict: "mAAAAAAAAAAAAAAAAAAA ymsgDict init", mymsg: " AAAAAAAAAAAAAAAAAAAAAAA mymsg init" }, mutations: { increment(state) { state.count++ }, setMsgDict(state, payload) { state.mymsgDict = payload.message; }, setMsg(state, payload) { state.mymsg = payload; }, updateMessage(state, message) { state.message = message; } } }, moduleB: { namespaced: true, state: { count: 0, }, mutations: { increment(state) { state.count++ }, } } } }) export default storeapp.vue
copmonentでhelloworldを呼んでる<template> <div id="app"> Page app: <form> <input v-model="compTitleVuex" > <input v-model="compTitleVuex" > <HelloWorld/> </form> </div> </template> <script> import HelloWorld from './components/HelloWorld.vue' export default { name: 'App', components: { HelloWorld }, computed: { compTitleVuex: { get() { return this.$store.state.moduleA.mymsg }, set(value) { console.log(value); this.$store.commit('moduleA/setMsg', value) } } } } </script>呼び出されるcomponent側
HelloWorld.vue ひどい名前・・<template> <div class="hello"> <hr> Inside component <input v-model="compTitleVuex"> </div> </template> <script> export default { name: 'insideComponent', computed: { compTitleVuex: { get() { return this.$store.state.moduleA.mymsg }, set(value) { console.log(value); this.$store.commit('moduleA/setMsg', value) } } } } </script>以下 mapStateは動かなかった
書き方違うか、対応してないか。
export default { name: 'HelloWorld', computed: { // mix this into the outer object with the object spread operator ...mapState({ message: state => state.moduleA.message; }) }}
- 投稿日:2020-06-23T17:05:16+09:00
【Nuxt.js】Nuxt文法編:@click
前置き
「すごく勉強になる!?」
とコメントいただけた
人気の文法編です?
今回は@click!❓どんな時に使うか
クリックでJSを実行したい時に使います?
使用率は高いのでぜひマスターしてください?TODOリストをクリックで削除したり
https://note.com/aliz/n/nda7438249ca8
クリックでページ遷移したり
https://note.com/aliz/n/nd9f344e4686f
modalをクリックで開閉したり…!
https://note.com/aliz/n/nd6e771724cd7@click
@click
v-on:click
どちらでも同じ意味です。
@はv-on:の省略です?v-on:hoge
hogeイベントが起きた時v-on:
DOMイベントの発火時に
JavaScriptを実行?v-on:click
クリックイベントが起きた時に
JavaScriptを実行?実行式を直接記載
@click="実行式"
実行式を直接書きます✍️
ただ通常は次のmethodsを呼び出すのが一般的です!
それが何故かを理解するために、把握する程度でOK!ここでdataのcounterを使う場合は
thisが不要です!
methods内で呼び出す場合は
必要になります?index.vue<template> <div class="page"> <p>{{ counter }}</p> <button @click="counter += 1"> click! </button> </div> </template> <script> export default { data () { return { counter: 0, } }, } </script>?+=
演算子です。
変数の値(counter: 0)と
式の値(1)を加算して
その和を変数(counter)に代入します♠️
counterの0に1を足して
counter自体が1になります。
そしてまた1を足すとcounterが2, 次は3…
と続いていきます?メソッドイベントハンドラ
@click="methods名"
実行式が長くなることが多いため
methods名を呼び出せます?♀️?パターン1?
index.vue<template> <div class="page"> <p>{{ counter }}</p> <button @click="countUp"> click! </button> </div> </template> <script> export default { data () { return { counter: 0, } }, methods: { countUp () { this.counter += 1 }, }, } </script>結果
先ほどと同じです?♀️?パターン2?
index.vue<template> <div class="page"> <button @click="alertMessage"> alertMessage </button> <button @click="alertEvent"> alertEvent </button> </div> </template> <script> export default { data () { return { name: 'Nuxt.js' } }, methods: { alertMessage () { alert (`Hello ${this.name}!`) }, alertEvent (event) { alert (event.target.tagName) }, }, } </script>?
テキスト${変数名}
methodsのalertMessageで使用。
テンプレートリテラルです。
通常は文字列を''で囲み
+で変数を連結しますが…
いちいち''で囲むのは面倒?
'テキスト' + 変数名 + 'テキスト'テンプレートリテラルを使えば
いちいち文字を''で区切らず
``(バッククォート)で全体を囲み
変数の部分だけ${変数名}にすれば
簡単に連結できます??event.target.tagName
methodsのalertEventで使用。
event.target
クリックイベントが起きている物
[object HTMLButtonElement]
event.target.tagName
buttonタグの名前
buttonが表示されます?
大文字で返されます。
https://developer.mozilla.org/ja/docs/Web/API/Element/tagNameインラインメソッドハンドラ
@click="methods名(引数に代入する物)"
インラインでJavaScript実行式を書けます!
文字列'hi'を表示させてます?index.vue<template> <div class="page"> <button @click="say('hi')"> Say hi </button> </div> </template> <script> export default { methods: { say (message) { alert (message) }, }, } </script>?say(変数)
文字列ではなく変数でも⭕️
say(name)にした場合は
dataのnameが呼び出され
表示は文字列'myName!'になります?
data () {
return {
name: 'myName!'
}
},?ちなみにsayが変数、'hi'が変数名です!
インラインステートメントハンドラ
@click="methods名($event)"
$event変数でDOMイベントの参照ができます!❓DOMイベントとは
DOM:文字の色を変えたり、
プログラムからhtmlなどを操作できる仕組みのこと
DOMイベント:操作するためのイベント【イベントの種類】
いくつか記載しましたが
他にもまだまだ沢山あります!
気になる方は調べてみてください?イベントハンドラJavaScriptイベントハンドラ/ --| mouseイベント(DOMイベント)/ -----| @click(type) -----| @mousedown(type) -----| @mouseup(type) --| keyboardベント/ -----| @click -----| @mousedown -----| @mouseup --| inputイベント/ -----| @input -----| @change【解説/index.vue】
・textChange (event)
イベントを受け取る際は$が不要です?
・event.target.value
今回のMouseEventが起きている
target(button)のvalue(りんご、みかん)index.vue<template> <div class="page"> <p>{{ text }} が好き</p> <button value="りんご" @click="textChange($event)" > りんご </button> <button value="みかん" @click="textChange($event)" > みかん </button> </div> </template> <script> export default { data () { return { text: 'りんご or みかん', } }, methods: { textChange (event) { console.log(event) this.text = event.target.value }, }, } </script>?$eventは省略可能
@click="methods名"だけでもOKです!?@click="textChange($event.target.value)"
もちろんここで直接値を渡してもOKです!
consoleの表示が変わるので見てみてください?
methodsの変更もお忘れなく〜?
textChange (event) {
console.log(event)
this.text = event
},?console.log(event)
今回はMouseEventが表示されています?
中身を見るとtype: "click"が出てきますよ?イベント修飾子
@click.修飾子="methods名"
様々な修飾子(event modifiers)が使えます!・stop
ネストされた子要素のmethodsが
親要素に伝搬するのを防ぎます【index.vue】
親要素、子要素共に同じmethodsを使用してます。
stopなし:親と子の2回のalertが表示される
stopあり:子の1回のみalertが表示されるindex.vue<template> <div @click="handler"> <button @click.stop="handler"> イベント実行ボタン </button> </div> </template> <script> export default { methods: { handler (element) { alert(element) }, }, } </script>他にも色々あります!
・prevent
Event.preventDefault()と同じです。
@submit.preventでよく使います。 https://note.com/aliz/n/n5b9bd618399e・capture
・self
・once
・passive
- 投稿日:2020-06-23T16:39:55+09:00
Vuejsでリアルタイム検索
初めに
割と検索に苦手意識を持ってきたので実装を避けてきたのですが思ったより案外簡単にできたのでおいておきます。
環境
- Vuejs
- Bootstrap4
- Axios
HTML
<input type="text" placeholder="検索..." v-model="keyword"> <p v-for="user in filterUsers"> {{ user.name }} </p>Vuejs
export default { data() { return { keyword: '', } }, created() { this.getItems() }, computed: { filterData() { var users = []; for (var i in this.users) { var user = this.users[i] // 配列とkeywordを比較して一致したら... if(user.name.indexOf(this.keyword) !== -1) { //配列にpushする。 users.push(user) } } return users; } }, methods: { getItems: function () { axios.get('/api/users').then(res => { this.users = res.data }) } } }終わり
これで完成となっています。
ね?簡単でしょ?
リアルタイム検索なので前方、後方、部分、完全一致関係なく検索してくれます。
便利な世の中になった。
- 投稿日:2020-06-23T16:06:30+09:00
Docker+Rails+Vueの環境を迷わず作成するステップ
最近勉強したDockerを使って、railsとVueの環境構築をしてみました。
いろいろ検索してやってみたものの、多くのエラーと向き合う日々を迎えることに...(それでもだいぶ理解は深まった?)この記事では
- とにかく開発環境だけ欲しい
- 自分の忘備録
を主な対象として、最速でDokcer+Rails+Vueの環境を作成するステップをご紹介します?!
(多分エラーは出ないはず。。。)STEP1. 4つのファイルを作成しよう
まずは作業するフォルダ(ディレクトリ)に
- Dockerfile
- docker-compose.yml
- Gemfile
- Gemfile.lock
の4つのファイルを作成します。内容はそれぞれ以下のようにします!
DockerfileFROM ruby:2.5.3 RUN curl -sL https://deb.nodesource.com/setup_10.x | bash - && apt-get update && \ apt-get install -y nodejs --no-install-recommends && rm -rf /var/lib/apt/lists/* RUN apt-get update -qq && apt-get install -y build-essential libpq-dev RUN apt-get update && apt-get install -y curl apt-transport-https wget && \ curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add - && \ echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list && \ apt-get update && apt-get install -y yarn RUN curl -sL https://deb.nodesource.com/setup_10.x | bash - RUN apt-get install -y nodejs npm && npm install n -g && n 10.17.0 RUN yarn add node-sass RUN mkdir /app WORKDIR /app COPY Gemfile /app/Gemfile COPY Gemfile.lock /app/Gemfile.lock RUN bundle install COPY . /appdocker-compose.ymlversion: '3' services: web: build: . command: bundle exec rails s -p 3000 -b '0.0.0.0' volumes: - .:/app ports: - 3000:3000 depends_on: - db tty: true stdin_open: true db: image: mysql:5.7 volumes: - db-volume:/var/lib/mysql environment: MYSQL_ROOT_PASSWORD: password volumes: db-volume:Gemfilesource 'https://rubygems.org' gem 'rails', '5.2.3'作業しているディレクトリで
touch Gemfile.lock
を実行すると、からのGemfile.lockが作成されます。?バージョンやdbのパスワードなどはよしなにご変更ください〜。
STEP2. rails newをする
今回はdockerコンテナ上でrailsアプリを作成するので、コマンドラインにそのまま
rails new
を打つのは正しくありません。
(僕のPCはローカルにrailsを入れていないため、rails new
を打っても「そのコマンド知りませんけど?」って怒られます。)dockerコンテナ上でコマンドを実行したい場合は
docker-compose run
コマンドをつかえばOKです?。下記コマンドを実行します。
docker-compose run web rails new . --force --database=mysql --webpack=vue --skip-coffee
このコマンドにより、
- dbはMySQLを明示的に指名
- Vueを後入れしなくて済む(後入れでエラーが結構出た記憶)
- coffee使わないので、coffee関連のファイルを作成しない
という付加価値をつけた状態で、rails new しています。
?あと2ステップ!
STEP3. database.ymlを作成する
STEP2の読み込みが完了したら、config/database.ymlが作成されているはず。
このファイル内にある「default」の内容を少し書き換えます。config/databese.ymldefault: &default adapter: mysql2 encoding: utf8 pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %> username: root password: password ←docker-compose.ymlで指定したdbのパスワード host: db ←docker-compose.ymlのservicesで指定したdbの名前STEP4. docker-compose up --build
ここまでできたら、
docker-compose up --build
を実行します!少し時間がかかりますが、読み込みが終わったあとにローカルホストにアクセスしてみると、「Yay! You’re on Rails!」の画面が表示されましたか?
もしそうなら成功です!だがしかしBut。。。?
僕の場合は、「ERROR -- : Unknown database 'app_development' (ActiveRecord::NoDatabaseError)」が表示されました。僕と同じという方は、
docker-compose exec web rails db:create
をしてあげればOK!
docker-compose down
をした後に、再度
docker-compose up --build
をすれば立ち上がるはずだぞ!お疲れ様でした?最後に
コロナ禍でWebエンジニア転職を頑張っていますが、railsポートフォリオだけだとお祈りしかされません。
AWSの冗長構成でインフラ構築しててもお祈りです。そこでRails+VueのRESTfulAPIを使ったアプリ(いわゆるSPA)を追加で作ったところ最終面接までは行けるようになりましたが、それでもやっぱり大変です。
もしWebエンジニア転職が大変だぁという方が読んでくれていたら、これだけは言いたいです。
諦めずに頑張ろうね!!!!以上、お粗末様でした。
- 投稿日:2020-06-23T11:09:34+09:00
TypeScript+Vue.jsの環境でnullableなpropsを指定する
TypeScript+Vue.jsの環境でVue.jsのコンポーネントでpropsを使っているときに、nullableなtype指定をどうやってやるかを説明します。
結論
Typescriptの方の型指定だけnullableであることを明示します。
title.vue<template> <h1>{{ title }}</h1> </template> <script lang="ts"> import { createComponent, SetupContext } from '@vue/composition-api' export default createComponent({ props: { title: { type: String as () => string | null, default: null } } }) </script>そもそもなのですが、Vue.jsのpropsはすべてnullableなので、nullableにするときに
[String, null]
というようにnullをpropsのtypeに書く必要はありません。よって、TypeScript側にだけnullableだということを教えればよいです。