第十七章-组件提纯之派发器思想(一)

59 阅读1分钟

经常会遇到一个组件又臭又长,思考怎么去让组件变得简单,更单纯点

vue2组件设计和派发器

派发器 -> 模式 -> 改造 -> 组件逻辑部分

  • 抽离合适的部分不让method变得臃肿
  • type -> 事件 -> 逻辑 -> type -> 派发器 -> 数据更改

组件化设计

  • 由外到内
    • 页面组件
    • 块组件 -> 组件出口 + 子组件

例子1

  • router/index.js
import Vue from 'vue'
import Router from 'vue-router'

import IndexPage from '@/pages/Index.vue'

Vue.use(Router)

export default new Router({
    routes: [
        {
            path: '/',
            name: 'IndexPage',
            component: IndexPage
        }
    ]
})
  • pages/Index.vue
<template>
    <Counter />
</template>

<script>
import Counter from "@/components/Counter.vue";
export default {
    components: {
        Counter
    }
}
</script>
  • components/Counter.vue
<template>
    <div>
        <counter-result :result='result'/>
        <div>
            <counter-button 
                innerText="+"
                action="PLUS"
                @compute="compute"
            />
            <counter-button 
                innerText="-"
                action="MiNUS"
                @compute="compute"
            />
        </div>
    </div>
</template>

<script>
import CounterResult from './CounterResult'
import CounterButton from './CounterButton'
export default {
    name: "Counter",
    components: {
        CounterResult,
        CounterButton
    },
    data() {
        return {
           result: 0 
        }
    },
    methods: {
        compute(action) {
            swith(action) {
                case "PLUS":
                    this.result += 1;
                    break;
                case "MiNUS":
                    this.result -= 1;
                    break;
                default:
                    break;
            }
        }
    }
}
</script>
  • components/CounterResult.vue
<template>
    <h1>{{ result }}</h1>
</template>
<script>
export default {
    name: "CounterResult",
    props: {
       result: {
        type: Number,
        default: 0
       } 
    }
}
</script>
  • components/CounterButton
<template>
    <button :action="action" @click="compute">{{innerText}}</button>
</template>
<script>
export default {
    name: 'CounterButton',
    props: ['innerText', 'action'],
    methods: {
        compute() {
            this.$emit('compute', this.action);
        }
    }
}
</script>

对上面的进行改造

  • 创建 actions
    • 在目录下建立 counter.js
  • 创建 reducer
    • 在目录下建立 counter.js
  • 创建 dispatch
    • 在目录下建立 counter.js
// => actions/counter.js
export const PLUS = 'PLUS';
export const MINUS = 'MINUS';
// reducer/counter.js
function counterReducer(data) {
    function plus() {
        return data.result + 1;
    }

    function minus() {
        return data.result - 1;
    }

    return {
        plus,
        minus
    }
}

export default counterReducer;
// dispatch/counter.js
import reducer from "@/reducers/counter"
import { PLUS, MINUS } from '@/actions/counter'

/**
 * ctx: 上下文组件
 */
export default (ctx) => {
    const { plus, minus } = reducer(ctx.$data);
    return function (type, ...args) {
        switch(type) {
            case PLUS:
                ctx.result = plus(...args);
                break;
            case MINUS:
                ctx.result = minus(...args);
                break;
            default:
                break;
        }      
    }
}
  • 到组件中去使用
  • components/Counter.vue
<template>
    <div>
        <counter-result :result='result'/>
        <div>
            <counter-button 
                innerText="+"
                action="PLUS"
                @compute="compute"
            />
            <counter-button 
                innerText="-"
                action="MiNUS"
                @compute="dispatch"
            />
        </div>
    </div>
</template>

<script>
import CounterResult from './CounterResult'
import CounterButton from './CounterButton'

// => 使用 dispatch
import dispatch from '@/dispatch/counter'
export default {
    name: "Counter",
    components: {
        CounterResult,
        CounterButton
    },
    data() {
        return {
           result: 0 
        }
    },
    methods: {
        dispatch(...args) {
            dispatch(this)(...args);
        }
    }
}
</script>

总结: 组件的内部逻辑是非常复杂的时候,类型比较多,操作比较多,可通过上述方法进行组件的提纯