vue优雅使用技巧(一)

vue优雅使用

1. 高频组件全局引入

  • 使用Vue.use()方法
    弊端: 需要多次import 引入组件
// 使用Vue.use()注入全局组件(高频出现)
import Vue from "vue";
import Child2 from "../components/child2"
import Child3 from "../components/child3"

let installComponents = [
    Child2,
    Child3
]

//将install函数挂在到对应得组件上
installComponents.map(component => {
   component.install = Vue => {
       Vue.component(component.name, component);
   }
})
//遍历使用Vue.use()
installComponents.map(component => {
    Vue.use(component);
})

  • 使用require.context方法
//动态引入
//webpack  require.context
//1. 目标文件
//2. 是否匹配子目录
//3. 匹配什么类型文件
import Vue from "vue"

function changeStr(str) {
    return str.charAt(0).toUpperCase() + str.slice(1);
}
//是一个map对象 { "./child": 模块,"./child2": 模块 }
const requireCompoent = require.context(".",false,/\.vue$/);


requireCompoent.keys().forEach(fileName => {
    ////从 map对象 通过 filename找出对应的模块
    const config = requireCompoent(fileName);
    const componentName = changeStr(
        //将相对得目的文件 换成一个ps
        fileName.replace(/^\.\//,"").replace(/\.\w+$/, "")
    )
    Vue.component(componentName, config.default || config)
})

2. 通过指令权限控制到具体元素

    1. 全局指令在入口文件定义
//commom/array.js
//权限控制
export function checkArray(key) {
    //权限数组 
    let arr = [1,3,5,7,9];
    
    let index = arr.indexOf(key);
    if(index > -1) {
        return true
    }else {
        return false
    }
}
//main.js
import "./components/golbal.js"
Vue.config.productionTip = false
import { checkArray} from "./common/array.js"

//vue自定义指令
Vue.directive("permisson", {
    inserted(el,binding) {
        let displayKey = binding.value;
        if(displayKey) {
            let hasPermisson = checkArray(displayKey);
            if(!hasPermisson) {
                el.parentNode && el.parentNode.removeChild(el);
            }
        }else {
            throw new Error("need key!")
        }
    }
})

    1. 通过Vue.use() 注入 多个全局的指令
      src/directives/modules/permission.js
import { checkArray } from '@/common/array';

const permisson = {
    //被绑定的dom插入父节点时调用,必须保证父节点存在
    inserted:(el,binding,vnode, oldNode) => {
        let bindValue = binding.value;
        if(bindValue) {
            let hasPermisson = checkArray(bindValue);
            if(!hasPermisson) {
                el.parentNode && el.parentNode.removeChild(el);
            }

        }else {
            throw new Error("need directive params!!!")
        }
    }
}

export default permisson

src/directives/index.js

// 引入目录下指令文件
import Vue from "vue";
//方式1
import permisson from "./modules/permisson";
// import xxx from "./modules/v-xxx";

let directives = {
    permisson
}
//遍历使用Vue.use() 注册全局指令
Object.keys(directives).forEach(key => {
    Vue.directive(key,directives[key]);
})
 

可以通过require.context方法 优化

let requireDirective = require.context("./modules", true, /\.js$/);
requireDirective.keys().forEach(fileName => {
    //通过map对象的key 获取对应的模块
    let configModule = requireDirective(fileName);
    let directiveName = fileName.replace(/\.\//,"").replace(/\.js/, "");
    console.log(directiveName, configModule.default|| configModule);
    Vue.directive(directiveName, configModule.default|| configModule);
})

3. render函数应用 当组件的处理的判断逻辑繁多使用 render 方便维护

  • 使用render函数的组件

<script>
export default {
    props: {
        type: {
            type:String,
            default: "normal"
        },
        text: {
            type:String,
            default: "默认的"
        }
    },
    render: h => h( 
        "button",{
            class: {
                btn: true,
                "btn-sucess":this.type == "sucess",
                "btn-danger":this.type == "danger",
                "btn-warning":this.type == "warning", 
            },
            domProps: {
                innerHTML: this.text
            }
        }
    )
}
</script>
<style  scoped>
    .btn {
        width: 100px;
        height: 80px;
        background-color: #ffffff;
    }
    .btn-sucess {
        background-color: blue;
    }
    .btn-danger {
        background-color: red;
    }
    .btn-waring {
        background-color: yellow;
    }

</style>
  • 使用
 <ChildRender type="sucess" text="成功的"></ChildRender>
 <ChildRender type="danger" text="危险的"></ChildRender>

4. Vue.mixin和 Vue.extend()

Vue.mixin: 全局注册一个混入,会影响之后的创建的每一个Vue实例对象,谨慎使用全局混入!!!一般推荐使用局部混入。
场景:我们有一对组件, 例如 提示框和模态框,他们的样式不一样,用法不一样,但是他们的行为一样(都是需要显示和隐藏操作)

//mixins/toggle.js
import Modal from "@/views/Modal";
import Tip from "@/views/Tip";
import Vue from "vue";

export default {
    data() {
        return{
            isShowing: false
        }
    },
    methods: {
        show: function(msg,el) {
            // 通过Vue.extend() 返回一个vue的构造器
            const constructor = Vue.extend(Modal);
            //同构造器new 一个 Vue实例对象
            const vm = new constructor();
            
            //注入数据
            vm.$data.msg = msg;
            vm.$mount(el);
        }
    }
}

//指定的组件使用 App.vue
<button @click="show('提示信息2', $refs.cover)">mixin使用</button>
<br>
<div ref="cover">

</div>

深入理解混入和应用

Vue的混入 mixins

混入 (mixin) 提供了一种非常灵活的方式,来分发 Vue 组件中的可复用功能。一个混入对象可以包含任意组件选项。当组件使用混入对象时,所有混入对象的选项将被“混合”进入该组件本身的选项。

  1. 尽量使用局部混入
  2. 选项合并时,以当前组件为主合并

mixins理解

  1. 使用mixins 尽量 抽离vue组件中公共方法和公共数据;这也是 区别与 公共组件的特点,因为公共组件不仅可以抽离方法和数据还可以抽离公共的 模板结构
  2. mixins的数据和方法,在每一个组件中都是独立的,互不干扰的,都属于vue组件的自身; 这也是区别与vuex,因为所有的组件公用一个vuex状态管理器数据和方法

使用mixins优化

如果在某个场景下真的需要通过 mixin来抽离 一个组件的视图,数据,方法呢?
我们要用到一个vue.extend()方法来构建一个 模板;
场景:

  1. 使用mixins 实现 popup功能
  2. 判断当前页面或者按钮,是否登录过,如果没登陆,出现弹框;
  3. 比如在当前页面,突然加一个非业务功能需求(抢红包,抽奖,广告...等),我们都可以在当前页面所改的需求,封装成一个混入。这样可以灵活切换是否使用,代码容易维护。

万水千山总是情,点波关注行不行(●'◡'●)!!!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 157,298评论 4 360
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 66,701评论 1 290
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 107,078评论 0 237
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,687评论 0 202
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,018评论 3 286
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,410评论 1 211
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,729评论 2 310
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,412评论 0 194
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,124评论 1 239
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,379评论 2 242
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,903评论 1 257
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,268评论 2 251
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,894评论 3 233
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,014评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,770评论 0 192
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,435评论 2 269
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,312评论 2 260

推荐阅读更多精彩内容