vue 扩展现有组件的操作


Posted in Javascript onAugust 14, 2020

1. 使用vue.mixin全局混入

混入 (mixins) 是一种分发 Vue 组件中可复用功能的非常灵活的方式。混入对象可以包含任意组件选项。当组件使用混入对象时,所有混入对象的选项将被混入该组件本身的选项。mixins 选项接受一个混合对象的数组。

混入的主要用途

1、在你已经写好了构造器后,需要增加方法或者临时的活动时使用的方法,这时用混入会减少源代码的污染。

2、很多地方都会用到的公用方法,用混入的方法可以减少代码量,实现代码重用。

<h1>Mixins</h1>
  <hr>
  <div id="app">
    <p>num:{{ num }}</p>
    <P>
      <button @click="add">增加数量<tton>
    </P>
  </div>
  <script type="text/javascript">
    var addLog = { //额外临时加入时,用于显示日志
      updated: function () {
        console.log("数据发生变化,变化成" + this.num + ".");
      }
    }
    Vue.mixin({// 全局注册一个混入,影响注册之后所有创建的每个 Vue 实例
      updated: function () {
        console.log("我是全局的混入")
      }
    })
    var app = new Vue({
      el: '#app',
      data: {
        num: 1
      },
      methods: {
        add: function () {
          this.num++;
        }
      },
      updated() {
        console.log("我是原生的update")
      },
      mixins: [addLog]//混入
    })

输出的结果

vue 扩展现有组件的操作

mixins的调用顺序

从执行的先后顺序来说,混入对象的钩子将在组件自身钩子之前调用,如果遇到全局混入(Vue.mixin),全局混入的执行顺序要前于混入和组件里的方法。

2.使用extends 扩展

extends选项允许声明扩展另一个组件,而无需使用 Vue.extend。

通过外部增加对象的形式,对构造器进行扩展。它和混入mixins非常的类似。只不过接收的参数是简单的选项对象或构造函数,所以extends只能单次扩展一个组件。

var bbb = {
      updated() {
        console.log("我是被扩展出来的");
      },
      methods: {
        add: function () { //跟原生的方法冲突,取原生的方法,这点跟混入一样
          console.log('我是被扩展出来的add方法!');
          this.num++;
        }
      }
    };
    var app = new Vue({
      el: '#app',
      data: {
        num: 1
      },
      methods: {
        add: function () {
          console.log('我是原生add方法');
          this.num++;
        }
      },
      updated() {
        console.log("我是扩展出来的");
      },
      extends: bbb// 接收对象和函数
    })

vue 扩展现有组件的操作

结果

执行的先后顺序和mixins一样,另外扩展的方法与原生的冲突时,扩展的方法不生效,这点跟混入一样

ps extends和mixins优先级比较

vue 扩展现有组件的操作

相对于mixins,extends触发的优先级更高

3.加slot扩展

.默认插槽和匿名插槽

slot用来获取组件中的原内容,此方式用于父组件向子组件传递“标签数据”。有的时候为插槽提供默认的内容是很有用的,例如,一个 组件可能希望这个按钮的默认内容是“如果没有原内容,则显示该内容”,但是同时允许用户覆写为别的内容。

<body>
 <div id="itany">
  <my-hello>180812</my-hello>
 </div>
<template id="hello">
 <div>
  <h3>welcome to xiamen</h3>
  <slot>如果没有原内容,则显示该内容</slot>// 默认插槽
 </div>
</template>
<script>
 var vm=new Vue({
   el:'#itany',
   components:{
   'my-hello':{
   template:'#hello'
  }
   }
 });  
</script>

具名插槽

有些时候我们需要多个插槽, 元素有一个特殊的特性:name。这个特性可以用来定义额外的插槽:

<div id="itany">
  <my-hello>
   <ul slot="s1">
  <li>aaa</li>
  <li>bbb</li>
  <li>ccc</li>
   </ul>
   <ol slot="s2">
  <li>111</li>
  <li>222</li>
  <li>333</li>
   </ol>
  </my-hello>
</div>
<template id="hello">
  <div>
   <slot name="s2"></slot>
   <h3>welcome to xiamen</h3>
   <slot name="s1"></slot>
  </div>
</template>
<script>
 var vm=new Vue({
  el:'#itany',
  components:{
   'my-hello':{
     template:'#hello'
    }
  }
 });

补充知识:Vue extends拓展任意组件功能(el-select实例)-两种写法

用到ElementUI的select组件,要求能够多选并且重复选择。如果直接使用的话,首先el-tag会报错,因为循环中key值重复;其次,他的移除是通过indexof搜索移除的tag的值,且在remove-tag事件中未抛出被移除tag的索引,这样的后果是存在多个相同值的tag时,只会移除第一个相同值的tag

思路

在el-tag的循环中,给close事件增加一个参数index,然后重写deleteTag方法,直接通过index删除该tag

Vue: @close="deleteTag($event, item)"
JSX: on-close={e => this.deleteTag(e, this.selected[0])}
deleteTag(event, tag, tagIndex){
 const value = this.value.slice();
 value.splice(tagIndex, 1);// 核心代码,其他代码省略
}

写法一、Vue template(推荐)

非常简单,改动特别少,可以使用Vue的所有用法,只需要复制el-select的template

新建一个vue文件

复制el-select的template模板内容过来

导入el-select,继承

覆盖methods中的deleteTag

结果

<template>
 <div
  class="el-select"
  :class="[selectSize ? 'el-select--' + selectSize : '']"
  @click.stop="toggleMenu"
  v-clickoutside="handleClose">
  我是示例代码,此处为自定义模板内容
 </div>
</template>

<script>
 import { Select} from 'element-ui';
 export default {
  extends: Select,//继承
  name: 'my-el-select',
  methods: {
   deleteTag(event, tag, tagIndex) {
// 重写该方法
  },
 },
 };
</script>

写法二、JSX(比较麻烦)

需要手动将Vue template转为jsx写法,无法使用事件修饰符,部分指令等等,改动比较大

1、导入继承

import {Select} from 'element-ui';

const myElSelect = {
 extends: Select
}

2、 重写render

Vue template最终编译之后也是生成render函数,这里覆盖render函数,

生成自定义内容。此处的意义只是为了记录以便于方便我用render函数时的jsx写法

render()
{
  const tagContent = () => {
   if (this.collapseTags && this.selected.length) {
    const tag0 = (
     <el-tag
      closable={!this.selectDisabled}
      size={this.collapseTagSize}
      hit={this.selected[0].hitState}
      type='info'
      on-close={e => this.deleteTag(e, this.selected[0])}
      disable-transitions={true}>
      <span class='el-select__tags-text'>{this.selected[0].currentLabel}</span>
     </el-tag>
    );
    const tag1 = (
     <el-tag
      closable={false}
      size={this.collapseTagSize}
      type='info'
      disable-transitions={true}>
      <span class='el-select__tags-text'>+ {this.selected.length - 1}</span>
     </el-tag>
    );

    if (this.selected.length > 1) {
     return (
      <span>
       {tag0}
       {tag1}
      </span>
     );
    }
    return (
     <span>
      {tag0}
     </span>
    );
   }
  };
  const emptyText = () => {
   if (this.emptyText && (!this.allowCreate || this.loading || (this.allowCreate && this.options.length === 0))) {
    return (
     <p class='el-select-dropdown__empty'>{this.emptyText}</p>
    );
   }
  };
  const selectOption = () => {
   return (
    <transition
     name='el-zoom-in-top'
     on-before-enter={this.handleMenuEnter}
     on-after-leave={this.doDestroy}>
     <el-select-menu
      ref='popper'
      append-to-body={this.popperAppendToBody}
      v-show={this.visible && this.emptyText !== false}>
      <el-scrollbar
       tag='ul'
       wrap-class='el-select-dropdown__wrap'
       view-class='el-select-dropdown__list'
       ref='scrollbar'
       class={{'is-empty': !this.allowCreate && this.query && this.filteredOptionsCount === 0}}
       v-show={this.options.length > 0 && !this.loading}>
       {this.showNewOption ? (
        <el-option
         value={this.query}
         created={true}>
        </el-option>
       ) : null}
       {
        this.$slots.default
       }
      </el-scrollbar>
      {emptyText()}
     </el-select-menu>
    </transition>
   );
  };
  return (
   <div
    class={['el-select', this.selectSize ? 'el-select--' + this.selectSize : '']}
    on-click={this.toggleMenu} v-clickoutside={this.handleClose}>
    <div
     class='el-select__tags'
     ref='tags'
     style={{'max-width': this.inputWidth - 32 + 'px'}}>
     {tagContent()}
     <transition-group onAfterLeave={this.resetInputHeight}>
      {this.selected.map((item, index) => {
       return (
        <el-tag
         key={index}
         closable={!this.selectDisabled}
         size={this.collapseTagSize}
         hit={item.hitState}
         type='info'
         on-close={(e) => this.deleteTag(e, item, index)}
         disable-transitions={false}>
         <span class='el-select__tags-text'>{item.currentLabel}</span>
        </el-tag>
       );
      })}
     </transition-group>
    </div>
    <el-input
     ref='reference'
     value={this.selectedLabel}
     type='text'
     placeholder={this.currentPlaceholder}
     name={this.name}
     id={this.id}
     auto-complete={this.autoComplete}
     size={this.selectSize}
     disabled={this.selectDisabled}
     readonly={this.readonly}
     validate-event={false}
     class={{'is-focus': this.visible}}
     on-focus={this.handleFocus}
     on-blur={this.handleBlur}
     on-keyup_native={this.debouncedOnInputChange}
     on-paste_native={this.debouncedOnInputChange}
     on-mouseenter_native={(this.inputHovering = true)}
     on-mouseleave_native={(this.inputHovering = false)}
    >
     <i slot='suffix'
       class={['el-select__caret', 'el-input__icon', 'el-icon-' + this.iconClass]}
       on-click={() => this.handleIconClick}/>
    </el-input>
    {selectOption()}
   </div>
  );
 }

3、 重写method里的deleteTag方法

4、结果

import {Select} from 'element-ui';

const myElSelect = {
 extends: Select,
 methods: {
  deleteTag(event, tag, tagIndex) {
   // *****略
  },
 },
 render() {
  return (
   <div>例子</div>
  );
 }
};
export default myElSelect;

以上这篇vue 扩展现有组件的操作就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
JS Jquery 遍历,筛选页面元素 自动完成(实现代码)
Jul 08 Javascript
探讨js中的双感叹号判断
Nov 11 Javascript
jquery查找父元素、子元素(个人经验总结)
Apr 09 Javascript
用jquery仿做发微博功能示例
Apr 18 Javascript
JavaScript中split与join函数的进阶使用技巧
May 03 Javascript
jQuery实现页面评论栏中访客信息自动填写功能的方法
May 23 Javascript
Javascript中级语法快速入手
Jul 30 Javascript
JavaScript禁止微信浏览器下拉回弹效果
May 16 Javascript
详解vuejs之v-for列表渲染
Jun 22 Javascript
微信小程序学习之数据处理详解
Jul 05 Javascript
Vue编程式跳转的实例代码详解
Jul 10 Javascript
Vue.js组件使用props传递数据的方法
Oct 19 Javascript
如何HttpServletRequest文件对象并储存
Aug 14 #Javascript
解决element-ui里的下拉多选框 el-select 时,默认值不可删除问题
Aug 14 #Javascript
Vue + Element-ui的下拉框el-select获取额外参数详解
Aug 14 #Javascript
vue在App.vue文件中监听路由变化刷新页面操作
Aug 14 #Javascript
解决vue项目中某一页面不想引用公共组件app.vue的问题
Aug 14 #Javascript
在vue中封装方法以及多处引用该方法详解
Aug 14 #Javascript
JS+css3实现幻灯片轮播图
Aug 14 #Javascript
You might like
php懒人函数 自动添加数据
2011/06/28 PHP
浅析HTTP消息头网页缓存控制以及header常用指令介绍
2013/06/28 PHP
php 中文字符串首字母的获取函数分享
2013/11/04 PHP
Yii2.0实现的批量更新及批量插入功能示例
2019/01/29 PHP
Ajax+Jpgraph实现的动态折线图功能示例
2019/02/11 PHP
Prototype1.5 rc2版指南最后一篇之Position
2007/01/10 Javascript
JS setCapture 区域外事件捕捉
2010/03/18 Javascript
node.js中的querystring.parse方法使用说明
2014/12/10 Javascript
Redis基本知识、安装、部署、配置笔记
2015/03/05 Javascript
JQ实现新浪游戏首页幻灯片
2015/07/29 Javascript
简单实现js选项卡切换效果
2016/02/03 Javascript
getElementById().innerHTML与getElementById().value的区别
2016/10/27 Javascript
jquery获取easyui日期控件的值实现方法
2016/11/09 Javascript
对称加密与非对称加密优缺点详解
2017/02/06 Javascript
JavaScript函数柯里化原理与用法分析
2017/03/31 Javascript
详解vue-cil和webpack中本地静态图片的路径问题解决方案
2017/09/27 Javascript
vue实现某元素吸顶或固定位置显示(监听滚动事件)
2017/12/13 Javascript
浅谈Vue2.0中v-for迭代语法的变化(key、index)
2018/03/06 Javascript
JavaScript设计模式之单例模式原理与用法实例分析
2018/07/26 Javascript
react同构实践之实现自己的同构模板
2019/03/13 Javascript
详解vue-cli3多页应用改造
2019/06/04 Javascript
[02:19]DOTA2女子战队FOX视频专访:希望更多美眉一起加入
2013/10/15 DOTA
Python判断变量是否已经定义的方法
2014/08/18 Python
Python set常用操作函数集锦
2017/11/15 Python
pow在python中的含义及用法
2019/07/11 Python
Python 调用有道翻译接口实现翻译
2020/03/02 Python
python中逻辑与或(and、or)和按位与或异或(&amp;、|、^)区别
2020/08/05 Python
Python selenium环境搭建实现过程解析
2020/09/08 Python
python链表类中获取元素实例方法
2021/02/23 Python
SteelSeries赛睿官网:游戏外设和配件的领先制造商(耳机、键盘、鼠标和鼠标垫)
2018/06/17 全球购物
你们项目是如何进行变更控制的
2015/08/26 面试题
英语专业毕业生自荐信
2013/10/28 职场文书
销售员个人求职的自我评价
2014/02/10 职场文书
精神文明建设先进个人事迹材料
2014/12/24 职场文书
干部外出学习心得体会
2016/01/18 职场文书
JavaWeb 入门:Hello Servlet
2021/07/16 Java/Android