综合案例 - 商品列表

文章目录

    • 需求说明
      • 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')

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

修复idea,eclipse ,clion控制台中文乱码

控制台乱码问题主要原因并不在编译器IDE身上&#xff0c;还主要是Windows的控制台默认编码问题。。。 Powershell&#xff0c;cmd等默认编码可能不是UTF-8&#xff0c;无需改动IDE的settings或者properties&#xff08;这治标不治本&#xff09;&#xff0c;直接让Windows系统…

编写nginx脚本,安装失败

这是我写的nginx脚本-&#xff08;正确的&#xff0c;已经修改过的&#xff09; 这是我在运行脚本是出现的问题 这是我在nginx官网上粘贴的内容&#xff0c;请注意我用红笔画的地方&#xff0c;与第一张我写的脚本图片作对比&#xff0c;会发现多出现两个转义符号\。第二幅图就…

Axolotl:一款极简的大模型微调(Finetune)开源框架

今天给大家分享一款工具&#xff0c;Axolotl[1] 是一个旨在简化各种AI模型的微调过程的工具&#xff0c;支持多种配置和架构。 特点&#xff1a; 可训练各种 Huggingface 模型&#xff0c;如 llama、pythia、falcon、mpt支持 fullfinetune、lora、qlora、relora 和 gptq使用简…

Linux GPIO模拟SPI接口介绍

一. 前言 上次通过GPIO模拟IIC的驱动一块0.98英寸的OLED后&#xff0c;想着下次用下GPIO模拟SPI接口试下。本文会介绍怎么用GPIO模拟SPI接口的方式为设备添加一块spi nor flash&#xff0c;flash模块如下图所示&#xff1a; 上图是一个spi nor模块&#xff0c;上面焊接了W25Q32…

acwing周赛140 b题

思路&#xff1a;我们按照从小到大的顺序将数组逆转好&#xff0c;然后枚举数组首项&#xff0c;分别让其1&#xff0c;-1&#xff0c;0&#xff0c;然后求出公差&#xff0c;从前往后遍历即可。 代码&#xff1a; int ans1(){//不动int cha (a[n] - a[1] 1) / (n - 1);int…

原创改进 | 融合蝠鲼觅食与联想学习的量子多目标灰狼优化算法(Matlab)

​前面的文章里作者介绍了多目标灰狼优化算法(Multi-Objective Grey Wolf Optimizer&#xff0c;MOGWO)&#xff0c;该算法是由Mirjalili等(灰狼算法的提出者)于2016年提出[1]&#xff0c;发表在中科院一区期刊《expert systems with applications》。 MOGWO保留了灰狼算法的种…

无际线复选框

效果演示 实现了一个网格布局&#xff0c;其中每个网格是一个复选框&#xff0c;可以选择是否显示。每个复选框都有一个漂浮的天花板&#xff0c;表示它是一个房间的天花板。每个房间的天花板都有一个不同的形状和颜色&#xff0c;分别对应不同的房间。整个页面的背景是一个由两…

小米13utltra激活冰箱

安装adb驱动https://www.jianshu.com/p/6c41d34d9202 直接下载使用 连接上小米手机,退出账号,关闭锁屏密码,打开usb调试,usb调试(安全设置) adb shell dpm set-device-owner com.catchingnow.icebox/.receiver.DPMReceiver如果显示Success&#xff0c;则您已成功激活冰箱。 …

【DeepLearning-8】MobileViT模块配置

完整代码&#xff1a; import torch import torch.nn as nn from einops import rearrange def conv_1x1_bn(inp, oup):return nn.Sequential(nn.Conv2d(inp, oup, 1, 1, 0, biasFalse),nn.BatchNorm2d(oup),nn.SiLU()) def conv_nxn_bn(inp, oup, kernal_size3, stride1):re…

PostgreSQL技术大讲堂 - 第43讲:流复制原理

PostgreSQL从小白到专家&#xff0c;是从入门逐渐能力提升的一个系列教程&#xff0c;内容包括对PG基础的认知、包括安装使用、包括角色权限、包括维护管理、、等内容&#xff0c;希望对热爱PG、学习PG的同学们有帮助&#xff0c;欢迎持续关注CUUG PG技术大讲堂。 第43讲&#…

每日OJ题_算法_二分查找⑦_力扣153. 寻找旋转排序数组中的最小值

目录 力扣153. 寻找旋转排序数组中的最小值 解析代码 力扣153. 寻找旋转排序数组中的最小值 153. 寻找旋转排序数组中的最小值 - 力扣&#xff08;LeetCode&#xff09; 难度 中等 已知一个长度为 n 的数组&#xff0c;预先按照升序排列&#xff0c;经由 1 到 n 次 旋转 后…

Java NIO初体验

概述 由于BIO&#xff08;同步阻塞IO&#xff09;对系统资源的浪费较大。Java1.4中引⼊了NIO框架&#xff0c;在java.nio包中提供了Channel、Selector、Buffer等抽象类&#xff0c;可以快速构建多路复⽤的IO程序&#xff0c;⽤于提供更接近操作系统底层的⾼性能数据操作⽅式。…

11. 双目视觉之立体视觉基础

目录 1. 深度恢复1.1 单目相机缺少深度信息1.2 如何恢复场景深度&#xff1f;1.3 深度恢复的思路 2. 对极几何约束2.1 直观感受2.2 数学上的描述 1. 深度恢复 1.1 单目相机缺少深度信息 之前学习过相机模型&#xff0c;最经典的就是小孔成像模型。我们知道相机通过小孔成像模…

零基础轻松学编程,中文编程开发工具下载及构件教程

零基础轻松学编程&#xff0c;中文编程开发工具下载及构件教程 一、前言 零基础学编程&#xff0c;中文编程工具下载&#xff0c;中文编程开发工具构件之选择件列表框构件教程&#xff0c; 想学编程可 编程交流.群.一起交流学习&#xff08;关注收藏或点击最下方官网卡片进入…

【c语言】详解操作符(上)

1. 操作符的分类 2. 原码、反码、补码 整数的2进制表示方法有三种&#xff0c;即原码、反码、补码 有符号整数的三种表示方法均有符号位和数值位两部分&#xff0c;2进制序列中&#xff0c;最高位的1位是被当做符号位其余都是数值位。 符号位都是用0表示“正”&#xff0c;用…

设计模式:简介及基本原则

简介 设计模式是一套被反复使用的、多数人知晓的、经过分类编目的、代码设计经验的总结。使用设计模式是为了重用代码、让代码更容易被他人理解、保证代码可靠性。 毫无疑问&#xff0c;设计模式于己于他人于系统都是多赢的&#xff0c;设计模式使代码编制真正工程化&#xff…

Kotlin快速入门5

Kotlin的继承与重写 kotlin的继承 Kotlin中所有类都继承自Any类&#xff0c;Any类是所有类的超类&#xff0c;对于没有超类型声明的类是默认超类&#xff08;Any 不是 java.lang.Object&#xff09;&#xff1a; class LearnKotlin // 默认继承自Any Any类默认提供三个函数…

Scikit-learn (sklearn)速通 -【莫凡Python学习笔记】

视频教程链接&#xff1a;【莫烦Python】Scikit-learn (sklearn) 优雅地学会机器学习 视频教程代码 scikit-learn官网 莫烦官网学习链接 本人matplotlib、numpy、pandas笔记 1 为什么学习 Scikit learn 也简称 sklearn, 是机器学习领域当中最知名的 python 模块之一. Sk…

IDEA搭建JDK源码学习环境(可添加注释、修改、debug)

工程详见&#xff1a;https://github.com/wenpanwenpan/study-source-jdk1.8.0_281 1、找到src.zip和javafx-src.zip 找到你想要调试的JDK&#xff0c;笔者本地电脑上装了两个版本的JDK&#xff0c;这里以jdk1.8.0_281为例将JDK目录下的javafx-src.zip和src.zip两个压缩包进行…

【GitHub项目推荐--不错的 TypeScript 学习项目】【转载】

在线白板工具 Excalidraw 标星 33k&#xff0c;是一款非常轻量的在线白板工具&#xff0c;可以直接在浏览器打开&#xff0c;轻松绘制具有手绘风格的图形。 如下图所示&#xff0c;Excalidraw 支持最常用的图形元素&#xff1a;方框、圆、菱形、线&#xff0c;可以方便的使用…