vue3 自定義指令
阿新 • • 發佈:2022-01-18
mkdir custom-directives
cd custom-directives
npm init -y
yarn add [email protected] [email protected] [email protected] -D
yarn add @vue/[email protected] [email protected] [email protected] [email protected] -D
包作用解析:
@vue/compiler-sfc (處理.vue的單檔案元件)
vue-loader (處理.vue的檔案的邏輯)
vue-style-loader(處理.vue的樣式放到相應的html檔案中去進行打包)
vue-template-compiler (處理vue檔案的template標籤裡面的東西的)
yarn add [email protected] css-loader@4 [email protected] [email protected] -D
注意:sass版本搭配不能出錯
sass-loader@5 <=> node-sass@4
修改package.json
"scripts": { "dev": "webpack-dev-server", "build": "webpack" },
根目錄下新建webpack.config.js檔案 遵循commonjs的規範 因為是執行在服務端
const htmlWebpackPlugin = require('html-webpack-plugin'), { VueLoaderPlugin } = require('vue-loader'), { resolve } = require('path') module.exports = { mode: 'development', entry: './src/main.js', output: { path: resolve(__dirname, 'dist'), filename: 'bundle.js', }, devtool: 'source-map', module: { rules: [ { test: /.vue$/i, loader: 'vue-loader', }, { test: /.scss$/i, use: ['vue-style-loader', 'css-loader', 'sass-loader'], }, ], }, resolve: { extensions: ['.js', '.jsx', '.vue'], }, externals: { vue: 'Vue', }, plugins: [ new VueLoaderPlugin(), new htmlWebpackPlugin({ template: resolve(__dirname, 'public/index.html'), }), ], }
常規方法:\src\components\MyTab.vue
<template>
<div>
<a
v-for="(item, index) in tabData"
:key="index"
href="javascript:;"
@click="handleClick(index)"
:class="['tab-item', { active: index === activeIdx }]"
>
{{ item.title }}
</a>
</div>
<div>{{ tabContent }}</div>
</template>
<script>
export default {
name: "my-tab",
props: {
tabData: {
type: Array,
default() {
return [];
},
},
currentIdx: {
type: [Number, String],
default: 0,
},
},
computed: {
tabContent() {
return this.tabData[this.activeIdx].content;
},
},
data() {
return {
activeIdx: this.currentIdx,
};
},
methods: {
handleClick(index) {
this.activeIdx = index;
},
},
};
</script>
\src\App.vue
<template>
<div>
<my-tab :tabData="tabData" :currentIdx="currentIdx"></my-tab>
</div>
</template>
<script>
import MyTab from "./components/MyTab";
export default {
name: "App",
components: {
MyTab,
},
data() {
return {
tabData: [
{
id: 1,
title: "選項1",
content: "內容1",
},
{
id: 2,
title: "選項2",
content: "內容2",
},
{
id: 3,
title: "選項3",
content: "內容3",
},
{
id: 4,
title: "選項4",
content: "內容4",
},
],
currentIdx: 1,
};
},
};
</script>
<style lang="scss">
a {
padding-left: 20px;
&.active {
text-decoration: none;
color: black;
}
}
</style>
方法二 使用自定義指令:
\src\components\MyTab.vue
<template>
<div
v-nav-change="{
tabClass: 'tab-item',
activeClass: 'active',
activeIdx,
}"
>
<a
v-for="(item, index) in tabData"
:key="item.id"
href="javascript:;"
@click="handleClick(index)"
class="tab-item"
>
{{ item.title }}
</a>
</div>
<div>{{ tabContent }}</div>
</template>
<script>
import navChange from "../directives/navChange";
export default {
name: "my-tab",
directives: {
navChange,
},
props: {
tabData: {
type: Array,
default() {
return [];
},
},
currentIdx: {
type: [Number, String],
default: 0,
},
},
computed: {
tabContent() {
return this.tabData[this.activeIdx].content;
},
},
data() {
return {
activeIdx: this.currentIdx,
};
},
methods: {
handleClick(index) {
this.activeIdx = index;
},
},
};
</script>
<style lang="scss">
</style>
\src\directives\navChange.js
export default {
mounted(el, bindings) {
const { tabClass, activeClass, activeIdx } = bindings.value
// tabClass, activeClass el.oldTabItems 不變 掛載到el,update中不需要重新獲取
el.tabClass = tabClass
el.activeClass = activeClass
el.oldTabItems = el.getElementsByClassName(el.tabClass)
el.oldTabItems[activeIdx].className = `${tabClass} ${activeClass}`
},
updated(el, bindings) {
const { activeIdx: oldIdx } = bindings.oldValue
const { activeIdx: newIdx } = bindings.value
const { tabClass, activeClass, oldTabItems } = el
el.oldTabItems[oldIdx].className = `${tabClass}`
el.oldTabItems[newIdx].className = `${tabClass} ${activeClass}`
},
}