pathName が /login の時 class="active" にします
<li :class="pathName === '/login' ? 'active' : ''">
親コンポーネント Parent.Vue
<Childcomponent>
山田太郎
</Childcomponent>
子コンポーネント Childcomponent.Vue
<h1>
<slot>default name</slot>
</h1>
結果
山田太郎
親コンポーネント Parent.Vue
<template>
<SampleslotChild>
<template #last>山田</template>
<template #first>太郎</template>
</SampleslotChild>
<SampleslotChild>
<template v-slot:last>テスト</template>
<template v-slot:first>ジロウ</template>
</SampleslotChild>
</template>
<script lang="ts" setup>
import SampleslotChild from "./SampleslotChild.vue"
</script>
#last と v-slot:last は同じです、好きな方で記述しましょう
子コンポーネント Childcomponent.Vue
<template>
<h1>
<slot name="last">default-last-name</slot>
</h1>
<h2>
<slot name="first">default-first-name</slot>
</h2>
</template>
結果
山田
太郎
テスト
ジロウ
親コンポーネントから子コンポーネントのデータを参照するスロットプロップス(slotProps)を受け取ることができます string型の position を受け取ってみます
親コンポーネント Parent.Vue
<template>
<SampleslotChild>
<template v-slot:position="slotProps">{{ slotProps }}</template>
</SampleslotChild>
</template>
<script lang="ts" setup>
import SampleslotChild from "./SampleslotChild.vue"
</script>
子コンポーネント Childcomponent.Vue
<template>
<h3>
<slot name="position" v-bind:position="position">{{position}}</slot>
</h3>
</template>
<script lang="ts" setup>
import {ref} from 'vue'
const position = ref("スタッフ")
setTimeout(() => {
position.value = '更新されたスタッフ'
}, 1000)
</script>
結果
{ "position": "スタッフ" }
↓ (1秒後に次のような表示となります)
{ "position": "更新されたスタッフ" }
オブジェクトを受け取る場合は次のように記述します
親コンポーネント Parent.Vue
<template>
<h1>一括で受け取る場合</h1>
<SampleslotChild>
<template v-slot:user="slotProps">slotPropsのname:{{ slotProps.user.name }}</template>
</SampleslotChild>
<h1>分割代入で受け取る場合</h1>
<SampleslotChild>
<template v-slot:user="{user:{name,age}}">slotPropsのname:{{ name }}</template>
</SampleslotChild>
</template>
<script lang="ts" setup>
import SampleslotChild from "./SampleslotChild.vue"
</script>
子コンポーネント Childcomponent.Vue
<template>
<h4>
<slot name="user" v-bind:user="user">{{ user.name }} ({{ user.age }})</slot>
</h4>
</template>
<script lang="ts" setup>
import {reactive} from 'vue'
interface User {
name: string
age: number
}
const user = reactive<User>({
name: 'スタッフ 太郎',
age: 20
})
setTimeout(() => {
user.name = '更新 次郎'
user.age = 21
}, 1000)
</script>
npx nuxi init my-app
cd my-app
yarn install
yarn add vuetify@next mdi
yarn add -D sass
npx で実行するのは nuxi です。
tsconfig.json に "jsx": "preserve" を追加します
{
// https://v3.nuxtjs.org/concepts/typescript
"extends": "./.nuxt/tsconfig.json",
"compilerOptions": {
"jsx": "preserve"
}
}
pages/hoge.vue
<template>
<div>
<h1>hoge</h1>
<p>hogeページです</p>
</div>
</template>
↓ tsx を使うと以下のように記述することができます
<script lang="tsx">
export default defineComponent({
render() {
return (
<div>
<h1>hoge</h1>
<p>hogeページです</p>
</div>
)
}
})
</script>
React開発者を Vue3 に取り込むことができます。
参考 : https://tech.andpad.co.jp/entry/2021/07/01/170000
composable/useCounter.ts
import type { Ref } from 'vue'
export const inc = (counter: Ref<number>) => () => counter.value++
export const dec = (counter: Ref<number>) => () => counter.value--
export const useSharedCounter = () => {
// ページ遷移で消えてもいい場合はこちら
const counter = ref(0)
// ページ遷移でも値を保持したい場合はこちら。ただし第一引数の key はユニークであること
const counter = useState('counter', () => (0))
return {
counter: readonly(counter),
dec: dec(counter),
inc: inc(counter),
}
}
/pages/sample.vue
<template>
<div>
<h1>カウンター: {{ counter }}</h1>
<button @click="dec" style="width: 28px; height: 28px; border: 1px solid red;"> - </button>
<button @click="inc" style="width: 28px; height: 28px; border: 1px solid red;"> + </button>
</div>
</template>
<script setup lang="ts">
const { counter, inc, dec } = useSharedCounter()
</script>
npx create-nuxt-app my-app
vuetify を選択しておきます
yarn add --dev @nuxt/typescript-build @nuxt/types
yarn add --dev nuxt-property-decorator
yarn add --dev vue-mixin-decorator
// Vue2 の 場合は version3 を入れます
yarn add vee-validate@3
https://github.com/justrhysism/vue-mixin-decorator
nuxt.config.js に こちらが追加されています
buildModules: [
// https://go.nuxtjs.dev/typescript
'@nuxt/typescript-build',
// https://go.nuxtjs.dev/vuetify
'@nuxtjs/vuetify',
],
vuetify を追加する
"types": ["@nuxt/types", "@nuxtjs/axios", "@types/node", "vuetify"]
nuxt.config.js
// hot reload
webpack: (config) => {
config.watchOptions = {
aggregateTimeout: 100,
poll: 300,
ignored: ["/node_modules/", "/.nuxt/", "/dist/"],
}
} ,
nuxt.config.ts
dark: false にします
vuetify: {
customVariables: ['~/assets/variables.scss'],
theme: {
dark: false,
続きはこちらを行うと理解が深まります
https://tech.mof-mof.co.jp/blog/nuxt-vuetify/
nuxt/content
https://bit.ly/3DuvM2p
v-bind は 「:」
v-onは「@」
v-slotは「#」
(マスタッシュ記法)
<p>{{message}}</p>
↓ こちらと同じです
(v-textディレクティブ)
<p v-text="message"></p>
callback function を利用します。 thisを利用する場合はアロー関数で記述してthisを固定しましょう。
submit() {
this.$emit('submit', () => this.closeDialog())
},
async submit(closeDialog) {
await this.foo1();
await this.foo2();
closeDialog()
}
<div id="app"></div>
<!-- 外部からVue.jsのメソッドを実行する -->
<script>
document.querySelector('#app').__vue__.testMethod();
</script>
index.html
<div id="app"
my-option='{ "styles": { "td":"width" } }'
>
main.js
const myOption = JSON.parse(this.$el.getAttribute('my-option'));
index.html に 渡したい引数をセット
<div id="app" arg1="hoge" arg2="fuga"></div>></div>
new Vue({
render: h => h(App),
).$mount('#app')
↓ このように書き換えます
new Vue({
render: function(createElement) {
const arg1 = this.$el.getAttribute('arg1')
alert( arg1 );
return createElement(App,
{
props: {
arg1: arg1
}
})
}
}).$mount('#app')
export default {
name: 'App',
components: {
MyComponent ,
},
props: {
arg1: {
type: String,
required: true,
} ,
},
created: function () {
alert( 'App.vue : ' + this.arg1 );
},
}
touch vue.config.js
例: sample-app.js のような命名になります。
module.exports = {
configureWebpack: {
output: {
filename: 'sample-[name].js',
chunkFilename: 'sample-[name].js'
}
},
css: {
extract: {
filename: 'sample-[name].css',
chunkFilename: 'sample-[name].css'
},
},
}
npm run build
必ず value という名前で作成しましょう
export default {
props: {
value: {
type: String,
required: true
}
}
}
export default {
computed: {
inputValue: {
get() {
return this.value;
},
set(value) {
this.$emit('input', value);
}
}
} ,
}
$emitの書式は
$emit( '任意のイベント名' )
です。
<input type="text" v-model="inputValue" />
以上です。
<my-component v-model="item.content.value"></my-component>
引用: https://b1tblog.com/2019/10/17/vue-vscode-addons/
・補足1. v-model とは何か? (答: 次の書式のシンタックスシュガーです)
<input type="text" v-model="value">
↓ 同じ
<input type="text" :value="value" @input="e => value = e.target.value">
・「htmlタグのvalue」 に 変数 value の値をセットします。
・inputイベントに無名関数をセットしてその中で 変数valueに「htmlタグのvalue」をセットします。
なお、自動で付与されるイベントはhtmlタグによって異なります。
テキストと複数行テキストは、value プロパティと input イベントを使用します
チェックボックスとラジオボタンは、checked プロパティと change イベントを使用します
選択フィールドは、value プロパティと change イベントを使用します
・補足2. v-model="xxxxx" で指定する xxxxx はどこで宣言するのか?
data または computed(get() ,set() 両方指定)で宣言します。
同名で両方存在するときは data が使用されるので、同じ名前をつけるのはやめておきましょう(ややこしい)
data で変数 hoge を定義しておく
data(){
return {
hoge: 1 ,
}
},
computed で変数 hoge を定義しておく
ゲッター(アクセサ)、セッター(ミューテータ) 、両方定義しておきましょう。
computed: {
hoge: {
get() {
return this.$store.state.myState.hoge;
},
set(value) {
const key = 'hoge';
this.$store.commit('myState',[key,value]);
}
}
},
https://v3.ja.vuejs.org/guide/migration/v-model.html#はじめに
2.x では、コンポーネントで v-model を使うことは、value プロパティを渡して input イベントを発火することと同じでした。
<ChildComponent v-model="pageTitle" />
<!-- これは下記の省略形です -->
<ChildComponent :value="pageTitle" @input="pageTitle = $event" />
インストール
yarn add vuedraggable
cssがめんどくさい場合は bootstrapも入れておきましょう
yarn add bootstrap-vue
コレクションの操作がめんどくさい場合は lodashも入れておきましょう
yarn add lodash
yarn add @types/lodash
xhr を使用するときは axios も入れておきましょう
yarn add axios
main.js に 以下も追加します
import Axios from 'axios'
Vue.use(Axios)
mkdir src/types
vi src/types/vuedraggable.d.ts
src/types/vuedraggable.d.ts
declare module 'vuedraggable'
コピーをさせたいリストを次のように変更します
<draggable
group="items"
>
↓
<draggable
:group="{ name: 'items', pull: 'clone', put: false }"
>
<template v-if="data == 'aaa' ">
<img src="cool-img" alt="awesome">
<h1>AAA</h1>
<p>Cool Text AAA</p>
</template>
<template v-else-if="data == 'bbb' ">
<img src="cool-img" alt="awesome">
<h1>BBB</h1>
<p>Cool Text BBB</p>
</template>
npm install --global @vue/cli
一度ターミナルを再起動してから
バージョンの確認
vue -V
@vue/cli 4.5.11
vue create my-project-name
Typescript を利用するために Manually select features を選択します。
cd my-project-name
npm run serve
dist フォルダにビルド結果が出力されます
npm run build
vue 2 の場合は
vue.config.js
module.exports = {
publicPath: './'
}
vue 3 の場合は
vue.config.js
module.exports = {
baseUrl: './'
}
クラスコンポーネントのがおすすめですが、こちらを参考に決定するといいでしょう。↓
https://zenn.dev/kata_n/articles/233ee8e03c5cb1
https://qiita.com/aLiz/items/5f7cab2b86116b496586
https://meetup-jp.toast.com/1843
基本形
<script lang="ts">
import { Component, Vue } from 'vue-property-decorator';
import { Component, Vue } from 'nuxt-property-decorator' // nuxtの場合
@Component
export default class extends Vue {
}
</script>
あとは、こちらを参考に。
https://qiita.com/ryo2132/items/4d43209ea89ad1297426#created-mounted-updated-destroyed-etc
これはオブジェクトが undefined なのに、オブジェクトのメンバ変数にアクセスしようとした時によくおこります。
次のようにあらかじめ存在チェックを入れて回避しましょう。
{{ props.row.client.tel }}
↓ ( v-if を使って props.row.client の存在を確認する )
<span v-if="props.row.client">{{ props.row.client.tel }}</span>
(例: projects の中身が3つ以上ある場合 )
<li v-if="props.row.projects.length > 2">
↓ エラーが出る場合はこのように書き換えます
<li v-if="props.row.projects && props.row.projects.length > 2">
npm install -g yarn
プロジェクト名を mysite としています。
yarn create nuxt-app mysite
cd mysite
yarn dev
http://localhost:3000/
でサイトにアクセスできるようになります。
pages ディレクトリの中に works ディレクトリを作成して 1001.vue を次の内容で保存します。
<template>
<div>
アイウエオ
</div>
</template>
http://localhost:3000/works/1001
でアクセスできるようになります。
yarn generate
dist/ ディレクトリが作成されてそこに書き出されます。
<div v-html="my_calc(props.row.sum_no)"></div>
↑
props.row.sum_no を my_calc メソッドを通した結果を エスケープせずに表示します
<span v-html="rawHtml"></span>
↑
この span のコンテンツは rawHtml プロパティの値に置き換えられ、プレーンな HTML として解釈されます。
http://haixing-hu.github.io/vue-html-editor/
jQueryのsummer note の vue.js移植版
[v-cloak] {
display: none;
}
<div v-cloak>
これだけでレンダリング前は非表示にして、レンダリング後に自動的に表示されるようになります。
<transition-group>
<div v-for="v,i in data_loop" :key="v.id">
(% v.tanto_name %)
</div>
</transition-group>
↓ これはレンダリングするとこのようになります
<span>
<div>担当者A</div>
<div>担当者B</div>
<div>担当者C</div>
</span>
transition-group タグが span タグ に変わります
任意のタグにするには
<transition-group>
↓
<transition-group tag="div">
とします。(div タグになります)
.v-enter-active, .v-leave-active {
transition: opacity 1s;
}
.v-enter, .v-leave-to {
opacity: 0;
}
以上で vue.js のデータを削除した時にアニメーションがつけられます。 簡単ですね。
拡張は色々できます。
数字に3桁ごとにカンマをつけるフィルター「number_format」を作成する
Vue.filter('number_format', function (value) {
if (! value) { return false; }
return value.toString().replace( /([0-9]+?)(?=(?:[0-9]{3})+$)/g , '$1,' );
});
よくあるテンプレートのフィルターと同じ書き方で使えます。
{{ props.row.price_with_shipping_no|number_format }}
{{ 123456789 | number_format }}