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鼠标左右键 键盘值小结
Jun 11 Javascript
我的Node.js学习之路(二)NPM模块管理
Jul 06 Javascript
JavaScript获取网页中第一个图片id的方法
Apr 03 Javascript
php结合imgareaselect实现图片裁剪
Jul 05 Javascript
jQuery Easyui Tabs扩展根据自定义属性打开页签
Aug 15 Javascript
JavaScript定义数组的三种方法(new Array(),new Array('x','y')
Oct 04 Javascript
Javascript 创建类并动态添加属性及方法的简单实现
Oct 20 Javascript
简单实现jQuery级联菜单
Jan 09 Javascript
一篇看懂vuejs的状态管理神器 vuex状态管理模式
Apr 20 Javascript
微信小程序 获取session_key和openid的实例
Aug 17 Javascript
如何自动化部署项目?折腾服务器之旅~
Apr 16 Javascript
微信小程序webview组件交互,内联h5页面并网页实现微信支付实现解析
Aug 16 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
使用php4加速网络传输
2006/10/09 PHP
php读取出一个文件夹及其子文件夹下所有文件的方法示例
2017/06/15 PHP
框架页面高度自动刷新的Javascript脚本
2013/11/01 Javascript
Extjs grid添加一个图片状态或者按钮的方法
2014/04/03 Javascript
解析NodeJS异步I/O的实现
2017/04/13 NodeJs
Vue数组更新及过滤排序功能
2017/08/10 Javascript
Node.js使用Koa搭建 基础项目
2018/01/08 Javascript
vue 配置多页面应用的示例代码
2018/10/22 Javascript
Node.js中Koa2在控制台输出请求日志的方法示例
2019/05/02 Javascript
vue+webpack dev本地调试全局样式引用失效的解决方案
2019/11/12 Javascript
Vue项目打包压缩的实现(让页面更快响应)
2020/03/10 Javascript
简单了解常用的JavaScript 库
2020/07/16 Javascript
微信小程序实现多行文字滚动
2020/11/18 Javascript
python中字符串的操作方法大全
2018/06/03 Python
python+pyqt5实现KFC点餐收银系统
2019/01/24 Python
python 设置输出图像的像素大小方法
2019/07/04 Python
Python的条件锁与事件共享详解
2019/09/12 Python
pyhton中__pycache__文件夹的产生与作用详解
2019/11/24 Python
python动态文本进度条的实例代码
2020/01/22 Python
canvas需要在标签里直接定义宽高
2014/12/17 HTML / CSS
印度网上购物首选目的地:Flipkart
2016/08/01 全球购物
意大利奢侈品购物网站:Giglio
2018/01/05 全球购物
幼儿园教师辞职信
2014/01/18 职场文书
2014年大学生自我评价
2014/01/19 职场文书
技术总监管理职责范本
2014/03/06 职场文书
在校大学生的职业生涯规划书
2014/03/14 职场文书
关于环保的标语
2014/06/13 职场文书
2014年国庆节演讲稿
2014/09/02 职场文书
股东授权委托书范文
2014/09/13 职场文书
2014财产信托协议书范本
2014/11/18 职场文书
2014年保险公司工作总结
2014/11/22 职场文书
管理人员岗位职责
2015/02/14 职场文书
校长一岗双责责任书
2015/05/09 职场文书
消防验收申请报告
2015/05/15 职场文书
工作计划范文之财务管理
2019/08/09 职场文书
Python字符串的转义字符
2022/04/07 Python