002_组件的二次封装

一、介绍

针对element-ui的el-input组件进行封装,需要添加element-ui的依赖

二、FirstCustomWrapInput组件

<template>
  <div>
    <el-input
      v-model="value"
      @input="$emit('input', value)"
      @blur="$emit('blur1')"
      @focus="$emit('focus1')"
    ></el-input>
  </div>
</template>


<script>
export default {
  name: "FirstCustomWrapInput",
  //方式一:需要model、props
  model: {
    prop: "initValue",
    event: "input",
  },
  props: ["initValue"],
  data() {
    return {
      value: this.initValue,
    };
  },
  watch:{
    // 监视props种initValue的变化,从而更新当前value,从而实现双向绑定。因为要避免直接修改props属性
    initValue(newValue){
      this.value = newValue
    }
  }
};
</script>

<style scoped>
.el-input {
  padding: 20px;
}

/* 这种方式可以访问到添加hash属性之后的下面样式 */
.el-input >>> .el-input__inner {
  background: #bfa;
  border-top: none;
  border-left: none;
  border-right: none;
}
</style>

三、SecondCustomWrapInput组件

<template>
  <div>
    <!-- 这种使用方式会要求,父组件传递的$listeners里面的属性名称
    是所封装组件能触发的。否则无效 -->
    <el-input v-bind="$attrs" v-on="$listeners"></el-input>
  </div>
</template>


<script>
export default {
  name: "SecondCustomWrapInput",
};
</script>

<style scoped>
.el-input {
  padding: 20px;
}

.el-input >>> .el-input__inner {
  background: #bfa;
  border-top: none;
  border-left: none;
  border-right: none;
}
</style>

四、App组件

<template>
  <div id="app">
    <h3>方式一</h3>
    <first-custom-wrap-input
      v-model="value"
      @blur1="handleBlur"
      @focus1="handleFocus"
    ></first-custom-wrap-input>
    <hr/>
    
    <h3>方式二</h3>
    <second-custom-wrap-input
      v-model="value"
      @blur="handleBlur"
      @focus="handleFocus"
    ></second-custom-wrap-input>
    value当前值:{{ value }}
    <hr/>
    
    <h3>element-ui组件</h3>
    <el-input v-model="value"/>
    <button @click="value='国货之光'">点我</button>
  </div>
</template>

<script>
import FirstCustomWrapInput from "./components/FirstCustomWrapInput.vue";
import SecondCustomWrapInput from "./components/SecondCustomWrapInput.vue";

export default {
  name: "App",
  components: { FirstCustomWrapInput,SecondCustomWrapInput },
  data() {
    return {
      value: "333",
    };
  },
  methods: {
    handleBlur() {
      console.log("blur");
    },
    handleFocus() {
      console.log("focus");
    },
  },
};
</script>

<style scoped>
#app {
  font-family: "Avenir", Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
  padding: 100px;
}
</style>

四、效果图

### 关于 Vue 组件二次封装的示例 #### 创建基础组件 为了展示如何进行 Vue 组件二次封装,先创建一个来自第三方库的基础按钮组件 `BaseButton`。 ```html <template> <el-button :type="type">{{ text }}</el-button> </template> <script setup> defineProps({ type: { type: String, default: 'primary' }, text: { type: String, required: true } }) </script> ``` 此部分展示了建立组件模板并定义通用样式的操作[^2]。同时,也明确了数据输入接口——即 props 的设计。 #### 封装增强功能 接下来构建一个新的组件 `EnhancedButton` 对上述基本按钮做进一步处理: ```html <template> <!-- 属性透传 --> <base-button v-bind="$attrs" @click="handleClick"> {{ buttonText }} </base-button> </template> <script setup> import { ref } from 'vue'; import BaseButton from './BaseButton.vue'; const emit = defineEmits(['custom-click']); const props = defineProps({ initialText: { type: String, default: '' } }); // 定义内部状态管理逻辑 let buttonText = ref(props.initialText); function handleClick() { console.log('点击事件触发'); // 自定义行为 buttonText.value += '! '; // 数据输出:向外部发送自定义事件通知 emit('custom-click', buttonText.value); } </script> ``` 这里实现了属性事件透传以及组件实例方法绑定的概念[^3]。通过这种方式可以灵活调整子组件的行为模式而不必修改原始源码。 #### 插槽机制的应用 如果希望让使用者能够更自由地控制按钮内的显示内容,则可以在 `EnhancedButton` 中引入具名插槽支持: ```html <!-- EnhancedButton.vue 更新版 --> <template> <base-button v-bind="$attrs" @click="handleClick"> <!-- 默认情况下使用文本作为默认插槽的内容 --> <span v-if="!$slots.default">{{ buttonText }}</span> <!-- 支持用户自定义插槽内容 --> <slot></slot> </base-button> </template> ``` 这样不仅保留了原有功能,还允许开发者根据实际场景插入任意复杂的 HTML 片段或其它 VNodes 结构。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值