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 相关文章推荐
如何实现动态删除javascript函数
May 27 Javascript
如何使用Javascript获取距今n天前的日期
Jul 08 Javascript
简单实现兼容各大浏览器的js复制内容到剪切板
Sep 09 Javascript
Bootstrap每天必学之下拉菜单
Nov 25 Javascript
Hallo.js基于jQuery UI所见即所得的Web编辑器
Jan 26 Javascript
Bootstrap菜单按钮及导航实例解析
Sep 09 Javascript
jQuery UI仿淘宝搜索下拉列表功能
Jan 10 Javascript
利用vueJs实现图片轮播实例代码
Jun 03 Javascript
详解webpack进阶之插件篇
Jul 06 Javascript
Angular限制input框输入金额(是小数的话只保留两位小数点)
Jul 13 Javascript
以v-model与promise两种方式实现vue弹窗组件
May 21 Javascript
详解jQuery如何实现模糊搜索
May 10 jQuery
如何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 Google的translate API代码
2008/12/10 PHP
通过PHP简单实例介绍文件上传
2015/12/16 PHP
对PHP依赖注入的理解实例分析
2016/10/09 PHP
php5.3/5.4/5.5/5.6/7常见新增特性汇总整理
2020/02/27 PHP
JS 修改URL参数(实现代码)
2013/07/08 Javascript
JavaScript操作DOM元素的childNodes和children区别
2015/04/01 Javascript
Nodejs Express4.x开发框架随手笔记
2015/11/23 NodeJs
使用Bootstrap typeahead插件实现搜索框自动补全的方法
2016/07/07 Javascript
仿百度换肤功能的简单实例代码
2016/07/11 Javascript
基于AngularJS前端云组件最佳实践
2016/10/20 Javascript
Ajax高级笔记 JavaScript高级程序设计笔记
2017/06/22 Javascript
vue下history模式刷新后404错误解决方法
2018/08/18 Javascript
vue+axios 前端实现登录拦截的两种方式(路由拦截、http拦截)
2018/10/24 Javascript
es6 symbol的实现方法示例
2019/04/02 Javascript
JS数据类型STRING使用实例解析
2019/12/18 Javascript
js判断一个对象是数组(函数)的方法实例
2019/12/19 Javascript
手机浏览器唤起微信分享(JS)
2020/10/11 Javascript
Python文件操作之合并文本文件内容示例代码
2017/09/19 Python
python opencv检测目标颜色的实例讲解
2018/04/02 Python
Pandas过滤dataframe中包含特定字符串的数据方法
2018/11/07 Python
Python rstrip()方法实例详解
2018/11/11 Python
python学生管理系统的实现
2020/04/05 Python
基于CSS3实现的几个小loading效果
2018/09/27 HTML / CSS
如何让IE9以下版本(ie6/7/8)认识html5元素
2013/04/01 HTML / CSS
详解前端HTML5几种存储方式的总结
2016/12/27 HTML / CSS
计算机专业应届毕业生自荐信
2013/09/26 职场文书
电子信息毕业生自荐信
2013/11/16 职场文书
不打扫卫生检讨书
2014/02/12 职场文书
向领导表决心的话
2014/03/11 职场文书
《埃及的金字塔》教学反思
2014/04/07 职场文书
小学作文评语大全
2014/04/21 职场文书
党的群众路线教育实践活动个人整改措施材料
2014/11/04 职场文书
2014年底工作总结
2014/12/15 职场文书
思想品德评语大全
2014/12/31 职场文书
网络营销计划
2015/01/17 职场文书
在CSS中使用when/else的方法
2022/01/18 HTML / CSS