美文网首页
Vue_组件封装的心得体会图

Vue_组件封装的心得体会图

作者: coderhzc | 来源:发表于2022-01-12 11:51 被阅读0次

一.心得体会图_传单个的属性和直接传递一个对象的区别:

image.png
总结:以前封装组件的时候喜欢把一个对象直接放进去,后面才发现这样是不可复用的,因为两个组件传递对象过来到你封装的组件内,属性如果要是一致的话,就没啥问题,
要是A传递过来的是: Obj.goods_name,
要是B传递过来的是: Obj.cx_name,
你说在自己封装的组件中,你该怎么去绑定从父组件中传递过来的值呢?
所以说封装的组件,你还是要按照单个属性的这种传值,这样就会有效的提高复用性

二.完整封装一个组件

二.一 定义一个父组件App.vue

<template>
  <div id="app">
    <!-- 这个可以直接把goodsList数组传递过去,但是不推荐,想要有课复用性,就传单个的属性过去 -->
    <CartDataile
      v-for="item in goodsList"
      :key="item.id"
      :id="item.id"
      :price="item.price"
      :checked="item.check"
      :imgurl="item.image_url"
      :goodstitle="item.goods_title"
      @change="change"
    ></CartDataile>
  </div>
</template>

<script>
import CartDataile from "@/components/CartDataile.vue";
export default {
  name: "App",
  data() {
    return {
      goodsList: [
        {
          id: 1,
          price: 180.11,
          check: true,
          goods_name: "风衣",
          goods_title: "风衣商品描述",
          imageurl:
            "https://img1.baidu.com/it/u=3612402013,982327803&fm=26&fmt=auto",
        },
        {
          id: 2,
          price: 580.12,
          check: false,
          goods_name: "卫衣",
          goods_title: "卫衣商品描述",
          image_url:
            "https://img0.baidu.com/it/u=1631902795,2594006009&fm=224&fmt=auto&gp=0.jpg",
        },
        {
          id: 3,
          price: 120.96,
          check: true,
          goods_name: "短袖",
          goods_title: "短袖商品描述",
          image_url:
            "https://img1.baidu.com/it/u=457792117,1201850547&fm=26&fmt=auto",
        },
        {
          id: 4,
          price: 380.78,
          check: false,
          goods_name: "整套女装",
          goods_title: "整套女装商品描述",
          image_url:
            "http://t15.baidu.com/it/u=1024874080,297428470&fm=224&app=112&f=JPEG?w=500&h=500",
        },
      ],
    };
  },
  components: {
    CartDataile,
  },
  methods: {
    change(e) {
      console.log(e);
    }
  },
};
</script>

<style lang="less" scoped>
</style>

二.二封装一个组件CartDetail.vue

<template>
  <div class="detaile-box">
    <div class="detail-item">
      <div class="ipt-box">
        <input
          type="checkbox"
          name="goods"
          :checked="checked"
          @change="change"
        />
      </div>
      <div class="left-box">
        <img :src="imgurl" alt="" />
      </div>
      <div class="right-box">
        <div class="title_info">{{ goodstitle }}</div>
        <div class="price">¥ {{ price }}</div>
      </div>
    </div>
  </div>
</template>

<script>
export default {
  props: {
    id: {
      required: true,
      type: Number,
    },
    imgurl: {
      type: String,
      default:
        "https://img1.baidu.com/it/u=3612402013,982327803&fm=26&fmt=auto",
    },
    price: {
      type: Number,
      default: 0,
    },
    goodstitle: {
      type: String,
      default: "",
    },
    checked: {
      checked: Boolean,
      default: false,
    },
  },
  methods: {
    change(e) {
      const id = this.id;
      const newState = e.target.checked;
      this.$emit("change", { id, newState });
    },
  },
};
</script>

<style lang="less" scoped>
.detaile-box {
  width: 100%;
  .detail-item {
    background-color: #ddd;
    width: 100%;
    display: flex;
    height: 200px;
    .ipt-box {
      line-height: 200px;
      vertical-align: middle;
      input[type="radio"],
      input[type="checkbox"] {
        zoom: 180%;
        color: blue;
      }
    }
    .left-box {
      flex: 1;
      margin-right: 5px;
      border-right: 1px solid #eee;
      vertical-align: middle;
      img {
        height: 180px;
      }
    }

    .right-box {
      flex: 1;
      position: relative;
      .title_info {
        font-weight: bold;
        font-size: 18px;
      }
      .price {
        color: red;
        position: absolute;
        bottom: 0;
        left: 10px;
        font-size: 18px;
        font-weight: bold;
      }
    }
  }
}
</style>

二.三 渲染的实际截图:

image.png

三.怎么在子组件发射事件给父组件具体的应用场景:

三.一 分析流程如下:

image.png

三.二具体代码实现:

image.png

/*************以下是完成功能的封装******************/

父组件App.vue

<template>
  <div id="app">
    <!-- 头部区域 -->
    <CartHeader :title="title"></CartHeader>
    <!-- 这个可以直接把goodsList数组传递过去,但是不推荐,想要有课复用性,就传单个的属性过去 -->
    <CartDataile
      v-for="item in goodsList"
      :key="item.id"
      :id="item.id"
      :price="item.price"
      :checked="item.check"
      :imgurl="item.image_url"
      :goodstitle="item.goods_title"
      :count="item.count"
      @change="change"
    ></CartDataile>

    <!-- 底部区域 -->
    <!-- :allp="allp" -->
    <CartFooter :checked="fullState" @changeFull="changeFull" :allp="allp" :jiesuan="jiesuan"></CartFooter>
  </div>
</template>

<script>
import CartHeader from "@/components/CartHeader.vue";
import CartDataile from "@/components/CartDataile.vue";
import CartFooter from "@/components/CartFooter.vue";
export default {
  name: "App",
  components: {
    CartHeader,
    CartDataile,
    CartFooter,
  },
  data() {
    return {
      title: "购物车案例",
      goodsList: [
        {
          id: 1,
          price: 180.11,
          check: true,
          count: 1,
          goods_name: "风衣",
          goods_title: "风衣商品描述",
          imageurl:
            "https://img1.baidu.com/it/u=3612402013,982327803&fm=26&fmt=auto",
        },
        {
          id: 2,
          price: 580.12,
          check: false,
          count: 2,
          goods_name: "卫衣",
          goods_title: "卫衣商品描述",
          image_url:
            "https://img0.baidu.com/it/u=1631902795,2594006009&fm=224&fmt=auto&gp=0.jpg",
        },
        {
          id: 3,
          price: 120.96,
          check: true,
          count: 4,
          goods_name: "短袖",
          goods_title: "短袖商品描述",
          image_url:
            "https://img1.baidu.com/it/u=457792117,1201850547&fm=26&fmt=auto",
        },
        {
          id: 4,
          price: 380.78,
          check: false,
          count: 3,
          goods_name: "整套女装",
          goods_title: "整套女装商品描述",
          image_url:
            "http://t15.baidu.com/it/u=1024874080,297428470&fm=224&app=112&f=JPEG?w=500&h=500",
        },
      ],
    };
  },
  computed: {
    // 计算全选的状态是true 还是false
    fullState() {
      const state = this.goodsList.every((item) => item.check);
      console.log(state);
      return state;
    },

    // 计算总共用了多少钱
    allp() {
      const allprice = this.goodsList
        .filter((item) => item.check)
        .reduce((proV, item) => (proV + item.price * item.count), 0);
      return allprice;
    },

    // 结算
    jiesuan() {
      const newLength = this.goodsList.filter(item=> item.check).length
      return newLength;
    }
  },

  methods: {
    change(e) {
      console.log(e);
      this.goodsList.some((item) => {
        if (item.id === e.id) {
          item.check = e.value;
          return true;
        }
      });
    },
    // 接收Footer子组件传递过来的事件
    changeFull(e) {
      this.goodsList.forEach((item) => (item.check = e));
    },
  },
};
</script>

<style lang="less" scoped>
</style>

头部组件CartHeader.vue

<template>
<div class="header-box">
  <div class="header-detail">
    <p>{{ title }}</p>
  </div>
</div>
</template>

<script>
export default {
props:{
  title:{
    type:String,
    default: "头部信息"
  }
}
}
</script>

<style lang="less" scoped>
.header-box {
  position: relative;
  .header-detail {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    height: 46px;
    background: rgb(18,121,255);
    color: #fff;
    text-align: center;
    line-height: 46px;
    z-index: 9999;
  }
}

</style>

CartDataile.vue详情组件

<template>
  <div class="detaile-box">
    <div class="detail-item">
      <div class="ipt-box">
        <input
          type="checkbox"
          name="goods"
          :checked="checked"
          @change="change"
        />
      </div>
      <div class="left-box">
        <img :src="imgurl" alt="" />
      </div>
      <div class="right-box">
        <div class="title_info">{{ goodstitle }}</div>
        <div class="price">¥ {{ price }}</div>
        <div class="count">总件数 X {{ count }}</div>
      </div>
    </div>
  </div>
</template>

<script>
export default {
  props: {
    id: {
      required: true,
      type: Number,
    },
    imgurl: {
      type: String,
      default:
        "https://img1.baidu.com/it/u=3612402013,982327803&fm=26&fmt=auto",
    },
    count:{
      type: Number,
      default: 0
    },
    price: {
      type: Number,
      default: 0,
    },
    goodstitle: {
      type: String,
      default: "",
    },
    checked: {
      type: Boolean,
      default: false,
    },
  },
  methods: {
    change(e) {
      const id = this.id;
      const newState = e.target.checked;
      this.$emit("change", { id, value: newState });
    },
  },
};
</script>

<style lang="less" scoped>
.detaile-box {
  width: 100%;
  .detail-item {
    background-color: #ddd;
    width: 100%;
    display: flex;
    height: 200px;
    margin-top: 50px;
    margin-bottom: 50px;
    .ipt-box {
      line-height: 200px;
      vertical-align: middle;
      input[type="radio"],
      input[type="checkbox"] {
        zoom: 180%;
        color: blue;
      }
    }
    .left-box {
      flex: 1;
      margin-right: 5px;
      border-right: 1px solid #eee;
      vertical-align: middle;
      img {
        height: 180px;
      }
    }

    .right-box {
      flex: 1;
      position: relative;
      .title_info {
        font-weight: bold;
        font-size: 18px;
      }
      .price {
        color: red;
        position: absolute;
        bottom: 0;
        left: 10px;
        font-size: 18px;
        font-weight: bold;
      }
      .count {
        color: #333;
        font-size: 12px;
      }
    }
  }
}
</style>

底部组件CartFooter.vue

<template>
  <div class="footer-box">
    <div class="footer-detail">
      <label for="ipt">
        全选
        <input
          id="ipt"
          class="left"
          type="checkbox"
          name="goods"
          :checked="checked"
          @change="change"
        />
      </label>

      <span class="center">总价: {{ allp.toFixed(2) }}</span>
      <span class="right">结算: {{ jiesuan }}件</span>
    </div>
  </div>
</template>

<script>
export default {
  data() {
    return {};
  },
  methods: {
    change(e) {
      const value = e.target.checked;
      console.log(value);
      this.$emit("changeFull", value);
    },
  },
  props: {
    checked: {
      type: Boolean,
      default: false,
    },
    allp: {
      type: Number,
      default: 0,
    },
    jiesuan: {
      type: Number,
      default: 0,
    },
  },
};
</script>

<style lang="less" scoped>
.footer-box {
  position: relative;
  .footer-detail {
    position: fixed;
    bottom: 0;
    left: 0;
    right: 0;
    height: 46px;
    background: #fff;
    color: #fff;
    line-height: 46px;
    z-index: 9999;
    display: flex;
    padding: 0 20px;
    color: red;
    font-weight: bold;
    justify-content: space-between;
    .left {
    }
    .center {
      color: #333;
    }
    .right {
      display: inline-block;
      margin-top: 5px;
      color: #fff;
      width: 80px;
      height: 30px;
      border-radius: 15px;
      text-align: center;
      line-height: 30px;
      background: rgb(18, 121, 255);
    }
  }
}
</style>

实际截图:

image.png

相关文章

  • Vue_组件封装的心得体会图

    一.心得体会图_传单个的属性和直接传递一个对象的区别: 二.完整封装一个组件 二.一 定义一个父组件App.vue...

  • echarts封装组件(动态数据)

    封装echarts饼图组件(其他同理),动态更新数据 方法1 父组件 子组件 效果图 方法2 父组件 html部分...

  • vue-cli3使用svg的最佳实践

    目录 iconfont的三种使用方式及其优缺点 封装svg组件 svg雪碧图 自动导入svg图标 封装svg组件 ...

  • 封装组件

    封装tab组件封装曝光加载组件封装轮播组件 代码

  • react复合组件封装思想(props截取)

    封装react组件经常会封装一些复合组件,比如手风琴,轮播图,等等……与常规组件不一样,复合组件经常会遇到一个问题...

  • 面向对象实战

    封装轮播组件 轮播 封装曝光加载组件 曝光加载 封装Tab 组件 Tab组件

  • 面向对象实战

    1、tab组件封装2、轮播组件封装3、曝光组件封装

  • 封装element-ui的dialog组件

    封装组件: 使用封装的组件:

  • 玩转Vue_组件

    什么是组件: 组件的出现,就是为了拆分Vue实例的代码量的,能够让我们以不同的组件,来划分不同的功能模块,将来我们...

  • 高级-任务3

    封装一个轮播组件 封装一个曝光加载组件 封装一个 Tab 组件 封装一个 Modal 组件

网友评论

      本文标题:Vue_组件封装的心得体会图

      本文链接:https://www.haomeiwen.com/subject/qscwcrtx.html