八、vue2中需要的代码优化

56 阅读1分钟

1 render函数与template

render函数与template有什么异同点:

相同点: 都是类编译器
不同点(Vue的渲染过程): template是vue的模板语法,在编译时,会通过render函数创建真实的元素,然后根据真实的元素会生成虚拟dom,然后再根据虚拟dom生成真实的元素。

*template和render是互补的关系,复杂的可以用render处理

image.png

优化:

<template>
    <div style="height: 400px">
        <!-- 高复用性; 模板更加间接明了; 集中化处理 -->
        <Button :type="type" :text="text"></Button> 
    </div>
</template>
<script>
    import Button from './Button.vue'
    export default {
        data() {
            return {
                type: 'success',
                text: 'successBtn'
            }
        },
        components: {
            Button
        }
    }
</script>
<script>
export default {
    name: 'MzButton',
    props: {
        type: {
            type: String,
            default: ''
        },
        text: {
            type: String,
            default: ''
        },
    },
    render(h) { // 相当于createElement,用来创建真实元素
        return h('button', {
            class: { // v-bind: class
                btn: true,
                'btn-success': this.type === 'success',
                'btn-error': this.type === 'error',
                'btn-warning': this.type === 'warning',
                'normal': !this.type
            },
            domProps: {
                innerText: this.text || '默认按钮'
            }
        })
    }
}
</script>

<style scoped>
.btn {
    width: 100px;
    height: 40px;
    color: white;
    transition: all .5s;
}
.btn-error {
    background: red;
}
.btn-success {
    background: green;
}
.btn-warning {
    background: yellow;
}
.normal {
    background: blue;
}
</style>

2 将abc转化为Abc

    function changeStr(str) {
        return str.charAt(0).toUpperCase() + str.slice(1)
    }

3 全局组件的引入

01 创建一个common文件夹,放置所有的组件,如下面的child组件

<template>
   <h1>
       我是MzChild组件
   </h1>
</template>
<script>
export default {
   name: 'MzChild',
}
</script>

02 在common文件夹下面创建一个global.js, 管理所有组件

常规引入注册:

import Vue from 'vue'
// import Child from './Child'
// import Button from './Button'
// Vue.component('MzChild', Child)
// Vue.component('MzButton', Button)

高级引入(使用require.context):

import Vue from 'vue'

function changeStr(str) {
    return str.charAt(0).toUpperCase() + str.slice(1)
}
/***
 * require.context => webpack Api(动态引入文件)
 * params: 当前路径,是否匹配子集,文件格式
*/
const requireComponent= require.context('./', false, /\.vue$/)
// console.dir(requireComponent.keys()) // 要找的所有路径
requireComponent.keys().forEach(fileName => {
    // 获取当前组件
    const currentCom = requireComponent(fileName)
    // 获取当前组件的组件名 默认将./Button.vue 变成 MzButton
    const defaultComName = 'Mz' + changeStr(fileName.replace(/^\.\//, '').replace(/\.\w+$/,''))
    const comName = currentCom.default.name || defaultComName
    // 全局注册组件
    Vue.component(comName, currentCom.default || currentCom)
})

03 在入口文件(main.js)中引入global

import MzUi from './common/global.js' // 引入所有组件

04 使用

<MzChild></MzChild>

4 按钮权限控制的实现(自定义指令)

<MzChild v-permission="'1'"></MzChild>
import Vue from 'vue'
function checkArray(key) {
    const arr = ['1', '4', '5', '7'] // 后端返回的权限表
    const i = arr.indexOf(key)
    return i > -1
}

Vue.directive('permission', {
    inserted(el, binding) {
        const permissionValue = binding.value // 元素上绑定的权限值
        if (permissionValue) {
            // 判断该用户是否有权限
            const hasPermission = checkArray(permissionValue)
            if (!hasPermission) {
                el.parentNode && el.parentNode.removeChild(el)
            }
        } else {
            throw new Error('请插入权限值')
        }
    }
})