综合案例 - 商品列表

news2024/11/15 17:27:35

文章目录

    • 需求说明
      • 1.my-tag组件封装(完成初始化)
      • 2.may-tag封装(控制显示隐藏)
      • 3.my-tag组件封装(v-model处理:信息修改)
      • 4.my-table组件封装(整个表格)
        • ①数据不能写死,动态传递表格渲染的数据
        • ②结构不能写死 - 多处结构自定义【具名插槽】
    • 案例完整代码:
      • 1.App.vue
      • 2.MyTag.vue
      • 3.MyTable.vue
      • 4.Main.js

需求说明

在这里插入图片描述

  1. my-tag标签封装组件
  • 双击显示输入框,输入框获取焦点
  • 失去焦点,隐藏输入框
  • 回显标签信息
  • 修改内容,回车 → 修改标签信息
  1. my-table表格组件封装
  • 动态传递数据渲染
  • 表头支持用户自定义
  • 主题支持用户自定义

1.my-tag组件封装(完成初始化)

App/vue
<template>
  <div class="table-case">
    <table class="my-table">
      <thead>
        <tr>
          <th>编号</th>
          <th>名称</th>
          <th>图片</th>
          <th width="100px">标签</th>
        </tr>
      </thead>
      <tbody>
        <tr>
          <td>1</td>
          <td>梨皮朱泥三绝清代小品壶经典款紫砂壶</td>
          <td>
            <img src="https://yanxuan-item.nosdn.127.net/f8c37ffa41ab1eb84bff499e1f6acfc7.jpg" />
          </td>
          <td>
            <!-- 标签组件 -->
            <MyTag></MyTag>
          </td>
        </tr>
        <tr>
          <td>1</td>
          <td>梨皮朱泥三绝清代小品壶经典款紫砂壶</td>
          <td>
            <img src="https://yanxuan-item.nosdn.127.net/221317c85274a188174352474b859d7b.jpg" />
          </td>
          <td>
       <!-- 标签组件 -->

          </td>
        </tr>
      </tbody>
    </table>
  </div>
</template>

<script>
// may-tag 标签组件的封装
//1.创建组件 - 初始化
//2.实现功能
import MyTag from './components/MyTag.vue'

export default {
  name: 'TableCase',
  components: {
    MyTag
  },
  data() {
    return {
      goods: [
        {
          id: 101,
          picture:
            'https://yanxuan-item.nosdn.127.net/f8c37ffa41ab1eb84bff499e1f6acfc7.jpg',
          name: '梨皮朱泥三绝清代小品壶经典款紫砂壶',
          tag: '茶具',
        },
        {
          id: 102,
          picture:
            'https://yanxuan-item.nosdn.127.net/221317c85274a188174352474b859d7b.jpg',
          name: '全防水HABU旋钮牛皮户外徒步鞋山宁泰抗菌',
          tag: '男鞋',
        },
        {
          id: 103,
          picture:
            'https://yanxuan-item.nosdn.127.net/cd4b840751ef4f7505c85004f0bebcb5.png',
          name: '毛茸茸小熊出没,儿童羊羔绒背心73-90cm',
          tag: '儿童服饰',
        },
        {
          id: 104,
          picture:
            'https://yanxuan-item.nosdn.127.net/56eb25a38d7a630e76a608a9360eec6b.jpg',
          name: '基础百搭,儿童套头针织毛衣1-9岁',
          tag: '儿童服饰',
        },
      ],
    }
  },
}
</script>
MyTag.vue(标签组件)
<template>
    <div class="my-tag">
              <!-- <input 
                class="input"
                type="text"
                placeholder="输入标签"
              /> -->
        <div class="text">
                茶具
        </div>
    </div>
</template>

在这里插入图片描述

2.may-tag封装(控制显示隐藏)

在这里插入图片描述

上面这两个不能同时显示,用到v-if 和 v-else
双击事件:@dblclick=""
自动聚焦:
法①$nextTick => $refs 获取到dom,进行focus获取焦点
法②封装v-focus指令
失去焦点,隐藏输入框:@blur操作isEdit = false

MyTag.vue
<template>
    <div class="my-tag">
              <input 
                v-if="isEdit"
                v-focus 
                ref="inp"
                class="input"
                type="text"
                placeholder="输入标签"
                @blur="isEdit=false"
              />
        <div v-else @dblclick="handleClick" class="text">
                茶具
        </div>
    </div>
</template>

<script>
export default {
    data () {
        return {
            isEdit:false
        }
    },
    methods:{
        handleClick () {
            //双击后,切换到显示状态
            this.isEdit = true
            // //等dom更新完,再获取焦点
            // this.$nextTick(() => {
            //     this.$refs.inp.focus()
            // })  每次都需要获取焦点,所以可以把它封装(全局)
        }
    }
}

</script>

全局注册

main.js

Vue.config.productionTip = false
//封装全局指令 focus
Vue.directive('focus',{
  //inserted是指令所在的dom元素,被插入到页面中时触发
  inserted (el) {
    el.focus()
  }
})

3.my-tag组件封装(v-model处理:信息修改)

  1. 回显标签信息:回显的标签信息是父组件传过来的,用v-model实现功能(简化代码)
    v-model => :value@input
    组件内部通过props接收 "value设置给输入框
  2. 内容修改了,回车 => 修改标签信息
    ·@keyup.enter·,回车时触发input事件。
    $emit写了一个input,并且把输入框的值实时拿到并提交,用到e.target.value→$emit('input',e.target.value)

以下代码只与此部分有关,上节已展示过的代码不再加入

App.vue
<template>
  <div class="table-case">
		//两个组件标签都放进去就可以了
          <td>
            <!-- 标签组件 -->
            <MyTag v-model="tempText"></MyTag>
          </td>
          <td>
       <!-- 标签组件 -->
            <MyTag v-model="tempText2"></MyTag>
          </td>
  </div>
</template>
<script>
// may-tag 标签组件的封装
//1.创建组件 - 初始化
//2.实现功能
import MyTag from './components/MyTag.vue'

export default {
  name: 'TableCase',
  components: {
    MyTag
  },
  data() {
    return {
      //测试组件功能的临时数据
      tempText:'水杯',
      tempText2:'钢笔',
  }
}
</script>


~.vue
<template>
    <div class="my-tag">
              <input 
                v-if="isEdit"
                v-focus 
                ref="inp"
                class="input"
                type="text"
                placeholder="输入标签"
                :value="value"
                @blur="isEdit=false"
                @keyup.enter="handleEnter"
              />
        <div v-else @dblclick="handleClick" class="text">
                {{ value }}
        </div>
    </div>
</template>

<script>
export default {
    props:{
        value:String
    },
    data () {
        return {
            isEdit:false
        }
    },
    methods:{
        handleClick () {
            //双击后,切换到显示状态
            this.isEdit = true
            // //等dom更新完,再获取焦点
            // this.$nextTick(() => {
            //     this.$refs.inp.focus()
            // })  每次都需要获取焦点,所以可以把它封装(全局)
        },
        handleEnter (e) {
            if(e.target.value.trim() ==='') return alert('标签内容不能为空')

            //子传父,将回车时,输入框的内容交给父组件更新
            //由于父组件时 v-model ,所以触发事件时,需要触发 input 事件
            this.$emit('input',e.target.value)
            //提交完成,关闭输入框状态
            this.isEdit = false
        }
    }
}

</script>

4.my-table组件封装(整个表格)

  1. 数据不能写死,动态传递表格渲染的数据
  2. 结构不能写死 - 多处结构自定义【具名插槽】
    (1). 表头支持自定义
    (2).主体支持自定义
①数据不能写死,动态传递表格渲染的数据
<template>
     <table class="my-table">
      <thead>
        <tr>
          <th>编号</th>
          <th>名称</th>
          <th>图片</th>
          <th width="100px">标签</th>
        </tr>
      </thead>
      <tbody>
        <tr v-for="(item,index) in data" :key="item.id">
          <td>{{ index + 1 }}</td>
          <td>{{ item.name }}</td>
          <td>
            <img :src="item.picture" />
          </td>
          <td>
            标签组件
            <!-- <MyTag v-model="tempText"></MyTag> -->
          </td>
        </tr>
       
      </tbody>
    </table>
</template>

<script>
export default {
    props:{
        data:{
            type:Array,
            required:true
        }
    }
}
</script>

②结构不能写死 - 多处结构自定义【具名插槽】
App.vue
<template>
  <div class="table-case">
    <MyTable :data="goods">
      <template #head>
        <tr>
          <th>编号</th>
          <th>名称</th>
          <th>图片</th>
          <th width="100px">标签</th>
        </tr>
      </template>

      <template #body="{ item,index }">
        <td>{{ index + 1 }}</td>
          <td>{{ item.name }}</td>
          <td>
            <img :src="item.picture" />
          </td>
          <td>
            <MyTag v-model="item.tag"></MyTag>
          </td>
      </template>
    </MyTable>
  </div>
</template>


~.vue
<template>
     <table class="my-table">
      <thead>
        <slot name="head"></slot>
      </thead>
      <tbody>
        <tr v-for="(item,index) in data" :key="item.id">
         <slot name="body" :item="item" :index="index"></slot>
        </tr>
       
      </tbody>
    </table>
</template>

在这里插入图片描述

案例完整代码:

1.App.vue

<template>
  <div class="table-case">
    <MyTable :data="goods">
      <template #head>
        <tr>
          <th>编号</th>
          <th>名称</th>
          <th>图片</th>
          <th width="100px">标签</th>
        </tr>
      </template>

      <template #body="{ item,index }">
        <td>{{ index + 1 }}</td>
          <td>{{ item.name }}</td>
          <td>
            <img :src="item.picture" />
          </td>
          <td>
            <MyTag v-model="item.tag"></MyTag>
          </td>
      </template>
    </MyTable>
  </div>
</template>

<script>
// may-tag 标签组件的封装
//1.创建组件 - 初始化
//2.实现功能
import MyTag from './components/MyTag.vue'
import MyTable from './components/MyTable.vue';

export default {
  name: 'TableCase',
  components: {
    MyTag,
    MyTable
  },
  data() {
    return {
      //测试组件功能的临时数据
      tempText:'水杯',
      tempText2:'钢笔',
      goods: [
        {
          id: 101,
          picture:
            'https://yanxuan-item.nosdn.127.net/f8c37ffa41ab1eb84bff499e1f6acfc7.jpg',
          name: '梨皮朱泥三绝清代小品壶经典款紫砂壶',
          tag: '茶具',
        },
        {
          id: 102,
          picture:
            'https://yanxuan-item.nosdn.127.net/221317c85274a188174352474b859d7b.jpg',
          name: '全防水HABU旋钮牛皮户外徒步鞋山宁泰抗菌',
          tag: '男鞋',
        },
        {
          id: 103,
          picture:
            'https://yanxuan-item.nosdn.127.net/cd4b840751ef4f7505c85004f0bebcb5.png',
          name: '毛茸茸小熊出没,儿童羊羔绒背心73-90cm',
          tag: '儿童服饰',
        },
        {
          id: 104,
          picture:
            'https://yanxuan-item.nosdn.127.net/56eb25a38d7a630e76a608a9360eec6b.jpg',
          name: '基础百搭,儿童套头针织毛衣1-9岁',
          tag: '儿童服饰',
        },
      ],
    }
  },
}
</script>

<style scoped>
.table-case {
  width: 1000px;
  margin: 50px auto;
  img {
    width: 100px;
    height: 100px;
    object-fit: contain;
    vertical-align: middle;
  }
}
</style>

2.MyTag.vue

<template>
    <div class="my-tag">
              <input 
                v-if="isEdit"
                v-focus 
                ref="inp"
                class="input"
                type="text"
                placeholder="输入标签"
                :value="value"
                @blur="isEdit=false"
                @keyup.enter="handleEnter"
              />
        <div v-else @dblclick="handleClick" class="text">
                {{ value }}
        </div>
    </div>
</template>

<script>
export default {
    props:{
        value:String
    },
    data () {
        return {
            isEdit:false
        }
    },
    methods:{
        handleClick () {
            //双击后,切换到显示状态
            this.isEdit = true
            // //等dom更新完,再获取焦点
            // this.$nextTick(() => {
            //     this.$refs.inp.focus()
            // })  每次都需要获取焦点,所以可以把它封装(全局)
        },
        handleEnter (e) {
            if(e.target.value.trim() ==='') return alert('标签内容不能为空')

            //子传父,将回车时,输入框的内容交给父组件更新
            //由于父组件时 v-model ,所以触发事件时,需要触发 input 事件
            this.$emit('input',e.target.value)
            //提交完成,关闭输入框状态
            this.isEdit = false
        }
    }
}

</script>

<style scoped>
    .my-tag {
    cursor: pointer;
    .input {
      appearance: none;
      outline: none;
      border: 1px solid #ccc;
      width: 100px;
      height: 40px;
      box-sizing: border-box;
      padding: 10px;
      color: #666;
      &::placeholder {
        color: #666;
      }
    }
  }
</style>

3.MyTable.vue

<template>
     <table class="my-table">
      <thead>
        <slot name="head"></slot>
      </thead>
      <tbody>
        <tr v-for="(item,index) in data" :key="item.id">
         <slot name="body" :item="item" :index="index"></slot>
        </tr>
       
      </tbody>
    </table>
</template>

<script>
export default {
    props:{
        data:{
            type:Array,
            required:true
        }
    }
}
</script>
<style>
.my-table {
    width: 100%;
    border-spacing: 0;
    img {
      width: 100px;
      height: 100px;
      object-fit: contain;
      vertical-align: middle;
    }
    th {
      background: #f5f5f5;
      border-bottom: 2px solid #069;
    }
    td {
      border-bottom: 1px dashed #ccc;
    }
    td,
    th {
      text-align: center;
      padding: 10px;
      transition: all 0.5s;
      &.red {
        color: red;
      }
    }
    .none {
      height: 100px;
      line-height: 100px;
      color: #999;
    }
  }
</style>

4.Main.js

import Vue from 'vue'
import App from './App.vue'

Vue.config.productionTip = false

//封装全局指令 focus
Vue.directive('focus',{
  //inserted是指令所在的dom元素,被插入到页面中时触发
  inserted (el) {
    el.focus()
  }
})

new Vue({
  render: h => h(App),
}).$mount('#app')

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1415534.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

三角形中任一边小于其余两边之和

在△ABC沿AC做等长BC的延长线CD ∵ B C C D ∵BCCD ∵BCCD ∴ A C B C A D , ∠ D ∠ C B D ∴ACBCAD,∠D∠CBD ∴ACBCAD,∠D∠CBD ∵ ∠ D < ∠ A B D ∵∠D<∠ABD ∵∠D<∠ABD ∴ A B < A D ∴AB<AD ∴AB<AD ∴ A B < A C B C ∴AB<ACBC ∴…

obsidian阅读pdf和文献——与zotero连用

参考&#xff1a; 【基于Obsidian的pdf阅读、标注&#xff0c;构建笔记思维导图&#xff0c;实现笔记标签化、碎片化&#xff0c;便于检索和跳转】 工作流&#xff1a;如何在Obsidian中阅读PDF - Eleven的文章 - 知乎 https://zhuanlan.zhihu.com/p/409627700 操作步骤 基于O…

IMXULL驱动学习——通过总线设备驱动模型点亮野火开发板小灯【参考韦东山老师教程】

参考&#xff1a;【IMX6ULL驱动开发学习】11.驱动设计之面向对象_分层思想&#xff08;学习设备树过渡部分&#xff09;-CSDN博客 韦东山课程&#xff1a;LED模板驱动程序的改造_总线设备驱动模型 我使用的开发板&#xff1a;野火imx6ull pro 欢迎大家一起讨论学习 实现了总线设…

5.Hive表修改Location,一次讲明白

Hive表修改Loction 一、Hive中修改Location语句二、方案1 删表重建1. 创建表&#xff0c;写错误的Location2. 查看Location3. 删表4. 创建表&#xff0c;写正确的Location5. 查看Location 三、方案2 直接修改Location并恢复数据1.建表&#xff0c;指定错误的Location&#xff0…

LeetCode---122双周赛

题目列表 3010. 将数组分成最小总代价的子数组 I 3011. 判断一个数组是否可以变为有序 3012. 通过操作使数组长度最小 3013. 将数组分成最小总代价的子数组 II 一、将数组分成最小总代价的子数组I 这道题纯纯阅读理解题&#xff0c;关键在于理解题意。注意&#xff1a;第一…

C#常见内存泄漏

背景 在开发中由于对语言特性不了解或经验不足或疏忽&#xff0c;往往会造成一些低级bug。而内存泄漏就是最常见的一个&#xff0c;这个问题在测试过程中&#xff0c;因为操作频次低&#xff0c;而不能完全被暴露出来&#xff1b;而在正式使用时&#xff0c;由于使用次数增加&…

Win32 PE图标资源提取(ICO图标提取)

最近需要写一个提取EXE或者DLL图标资源的功能, 网上找了很久, 要么功能不好用, 最后结果如下: 1.很多是加载为HICON句柄后转换为图片保存, 全损画质..., 2.后来找了个还能用的, 详见 https://github.com/TortoiseGit/TortoiseGit/blob/master/src/Utils/IconExtractor.cpp …

Springboot+Netty搭建基于TCP协议的服务端

文章目录 概要pom依赖Netty的server服务端类Netty通道初始化I/O数据读写处理测试发送消息 并 接收服务端回复异步启动Netty运行截图 概要 Netty是业界最流行的nio框架之一&#xff0c;它具有功能强大、性能优异、可定制性和可扩展性的优点 Netty的优点&#xff1a; 1.API使用简…

深度强化学习(王树森)笔记03

深度强化学习&#xff08;DRL&#xff09; 本文是学习笔记&#xff0c;如有侵权&#xff0c;请联系删除。本文在ChatGPT辅助下完成。 参考链接 Deep Reinforcement Learning官方链接&#xff1a;https://github.com/wangshusen/DRL 源代码链接&#xff1a;https://github.c…

分布式id-雪花算法

一、雪花算法介绍 Snowflake&#xff0c;雪花算法是有Twitter开源的分布式ID生成算法&#xff0c;以划分命名空间的方式将64bit位分割成了多个部分&#xff0c;每个部分都有具体的不同含义&#xff0c;在Java中64Bit位的整数是Long类型&#xff0c;所以在Java中Snowflake算法生…

Linux 文件和文件夹的创建与删除

目录 一. 新建1.1 mkdir 新建文件夹1.2 touch 新建空文件1.3 vi命令创建文件1.4 > 和 >> 新建文件 二. 删除 一. 新建 1.1 mkdir 新建文件夹 -p&#xff1a;递归的创建文件夹&#xff0c;当父目录不存在的时候&#xff0c;会自动创建 mkdir -p test1/test2/test31.…

stable-diffusion-webui 汉化(中文界面)

大家好&#xff0c;我是水滴~~ 本文主要介绍 Stable Diffusion WebUI 是如何汉化的&#xff0c;文章详细的介绍汉化过程&#xff0c;并加上配图能够清晰的展示该过程。 Stable Diffusion WebUI 官方并没有出中文界面&#xff0c;需要通过安装插件来汉化&#xff0c;下面是详细…

工业空调转IEC104协议转换网关BE108

随着电力系统信息化建设和数字化转型的进程不断加速&#xff0c;对电力能源的智能化需求也日趋增强。健全稳定的智慧电力系统能够为工业生产、基础设施建设以及国防建设提供稳定的能源支持。在此背景下&#xff0c;高性能的工业电力数据传输解决方案——协议转换网关应运而生&a…

如何免费注册一个二级域名

目录 1.sitelutions账号注册 2.添加域名 3.做A记录或者cname解析步骤 1.sitelutions账号注册 注册网址:Sitelutions - Solutions for your site. All in one place. 打开首页点击右上角的红色 free sign up 来注册。注册只需邮箱即可。 首先填写注册信息,然后提交。提交之后…

Tortoise-tts Better speech synthesis through scaling——TTS论文阅读

笔记地址&#xff1a;https://flowus.cn/share/a79f6286-b48f-42be-8425-2b5d0880c648 【FlowUs 息流】tortoise 论文地址&#xff1a; Better speech synthesis through scaling Abstract: 自回归变换器和DDPM&#xff1a;自回归变换器&#xff08;autoregressive transfo…

算法38:子数组的最小值之和(力扣907题)----单调栈

题目&#xff1a; 给定一个整数数组 arr&#xff0c;找到 min(b) 的总和&#xff0c;其中 b 的范围为 arr 的每个&#xff08;连续&#xff09;子数组。 示例 1&#xff1a; 输入&#xff1a;arr [3,1,2,4] 输出&#xff1a;17 解释&#xff1a; 子数组为 [3]&#xff0c;[…

设计模式:工厂方法模式

工厂模式属于创建型模式&#xff0c;也被称为多态工厂模式&#xff0c;它在创建对象时提供了一种封装机制&#xff0c;将实际创建对象的代码与使用代码分离&#xff0c;有子类决定要实例化的产品是哪一个&#xff0c;把产品的实例化推迟到子类。 使用场景 重复代码 : 创建对象…

机器学习---可能近似正确(PAC)、出错界限框架

1. 计算学习理论概述 从理论上刻画了若干类型的机器学习问题中的困难和若干类型的机器学习算法的能力 这个理论要回答的问题是&#xff1a; 在什么样的条件下成功的学习是可能的&#xff1f; 在什么条件下某个特定的学习算法可保证成功运行&#xff1f; 这里考虑两种框架&…

【开源】基于JAVA+Vue+SpringBoot的固始鹅块销售系统

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 数据中心模块2.2 鹅块类型模块2.3 固始鹅块模块2.4 鹅块订单模块2.5 评论管理模块 三、系统设计3.1 用例设计3.2 数据库设计3.2.1 鹅块类型表3.2.2 鹅块表3.2.3 鹅块订单表3.2.4 鹅块评论表 四、系统展示五、核心代码5.…

基于C语言的趣味游戏之五子棋

目录 趣味五子棋游戏 第一步 text.c文件 第二步 game.h文件 第三步 初始化 打印棋盘 玩家输入 电脑输入 判断输赢 game.c 趣味五子棋游戏 第一步 先写菜单&#xff0c;然后在主函数里调用&#xff0c;由于这是一个可以重复的游戏所以将do while循环里调用menu函数。…