案例-商品列表(组件封装)

  

标签组件封装


1.双击显示,自动聚焦

2.失去焦点,隐藏输入框
标签一列,不同行的标签内容不同,但是除此之外其他基本一致,所以选择用 标签组件 将这一部分封装为一个组件,需要时组件标签展示。

首先标签处一进去就是显示的 “茶具” 双击之后才显示输入框。所以输入框和 “茶具”的显示两者是互斥的,用 v-if 和 v-else 来控制。

v-if 传值为“isEdit” 如果为 false 就显示 “茶具”,(最初定义的就是false,也就是一开始进去就是 “茶具”,什么时候会变为true继而显示输入框呢),给v-else 也就是“茶具”所在的元素注册一个双击事件,双击之后 isEdit由false变为true,就会显示输入框了。

接下来是聚焦,想要实现的是双击“茶具”出现输入框之后就自动进行聚焦。开始做法是给输入框dom元素添加ref属性,在显示输入框之后this.isEdit=true,通过$refs立刻获取焦点。但是vue是异步更新,输入框显示但是dom并没有进行更新,所以出错。这时,通过$nextTick检测dom元素更新完成之后就立刻获取焦点。

每次想要实现聚焦效果都要写这一段代码,很是麻烦,可以将这个效果进行指令封装,并全局注册,需要时直接添加指令即可。




输入框和茶具不能一同显示,两个是互斥关系,用v-if和v-else



指令封装,dom元素插入页面自动聚焦

或者



输入框失去焦点(显示茶具)



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><!-- 标签组件 --><MyTag></MyTag></td></tr></tbody></table></div>
</template><script>
// my-tag 标签组建的封装
//  1.创建组件 - 初始化
//  2.实现功能
//    (1)双击显示,并且自动聚焦 
//       v-if v-else @dbclick 
//       &nextTick =>$refs获取到dom ,进行focus获取焦点
//       封装v-focus指令
//     (2)失去焦点,隐藏输入框
//     (3)回显标签信息
//     (4)内容修改了,回车 =》 修改标签信息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><style lang="less" scoped>
.table-case {width: 1000px;margin: 50px auto;img {width: 100px;height: 100px;object-fit: contain;vertical-align: middle;}.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>

MyTag.vue

<template>
<div class="my-tag"><input v-if="isEdit"v-focusref="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// // // 通过ref找到元素,立刻获取焦点// // this.$refs.inp.focus()// // 异步更新,切换到显示状态后,dom并没有进行更新,立即获取焦点实际是获取不到的// // 等dom更新王再获取焦点// this.$nextTick(() => {//   this.$refs.inp.focus()// })// // 每次都要点focus进行获取焦点很麻烦,可以将这套指令封装为指令,在main.js中进行全局注册}}}
</script><style lang="less" 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>

main.js





3.回显标签信息

4.内容修改了,回车 =>修改标签信息

回显的标签信息是父组件传递过来的,在data中定义数据tempText,在子组件标签中通过v-model帮绑定该数据,子组件中通过props接收该数据值value,显示为还未双击之前的值,双击之后输入框出现,显示为输入框回显的值 :value="value"。

修改输入框中的内容回车之后希望显示修改后的内容。也就是将修改后的数据传送到父组件,父组件再传送回子组件进行显示。通过键盘回车绑定事件,将用户输入数据传送回父组件,e.target能拿到事件源,也就是dom元素,e.target.value能拿到用户输入的值。


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 v-model="tempText"></MyTag></td></tr><tr><td>1</td><td>梨皮朱泥三绝清代小品壶经典款紫砂壶</td><td><img src="https://yanxuan-item.nosdn.127.net/221317c85274a188174352474b859d7b.jpg" /></td><td><!-- 标签组件 --><MyTag></MyTag></td></tr></tbody></table></div>
</template><script>
// my-tag 标签组建的封装
//  1.创建组件 - 初始化
//  2.实现功能
//    (1)双击显示,并且自动聚焦 
//       v-if v-else @dbclick 
//       &nextTick =>$refs获取到dom ,进行focus获取焦点
//       封装v-focus指令
//     (2)失去焦点,隐藏输入框//     (3)回显标签信息
//        回显的标签信息是父组件传递过来的
//        v-model实现功能(简化代码) v-model => :value 和 @input(事件监听)
//        组件内部通过props接收,:value设置给输入框
//     (4)内容修改了,回车 =》 修改标签信息
//         @keyup.enter,触发事件$emit('input',e.target.value)import MyTag from './components/MyTag.vue'
export default {name: 'TableCase',components: {MyTag,},data() {return {// 测试组件功能临时数据tempText:'茶壶', //希望子组件内容能跟这个数据进行双向绑定,这里传入啥,子组件就显示啥;子组件回车又能修改到这里的数据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 lang="less" scoped>
.table-case {width: 1000px;margin: 50px auto;img {width: 100px;height: 100px;object-fit: contain;vertical-align: middle;}.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>

MyTag.vue

<template>
<div class="my-tag"><!-- v-model不能跟父组件传递过来的数据进行直接绑定,一旦绑定,就相当于直接在修改父组件传递过来的数据,子组件泵你直接修改父组件传递过来的数据 --><!--  :value="value"相当于父组件传递过来什么值,子组件就显示什么值并进行绑定,该值就回显了 --><input v-if="isEdit"v-focusref="inp"class="input"type="text"placeholder="输入标签"@blur="isEdit = false":value="value"@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// // // 通过ref找到元素,立刻获取焦点// // this.$refs.inp.focus()// // 异步更新,切换到显示状态后,dom并没有进行更新,立即获取焦点实际是获取不到的// // 等dom更新王再获取焦点// this.$nextTick(() => {//   this.$refs.inp.focus()// })// // 每次都要点focus进行获取焦点很麻烦,可以将这套指令封装为指令,在main.js中进行全局注册},handleEnter(e){// 非空处理if (e.target.value.trim() === '') return alert('标签不能为空')// 需要子传父,回车时,输入框的内容提交给父组件更新,// 父组件是v-model,触发事件,需要触发input事件this.$emit('input',e.target.value)// 或者this.$refs.inp.value// e.target拿到的是触发事件的事件源,也就是dom元素,想拿到输入框输入的值,直接.value就是了// 提交完成,关闭输入状态}}}
</script><style lang="less" 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>

my-table表格组件封装

表格中表头和中间体不能写死,类似的表格还有很多,可以复用。

中间体:表格组件中接收父组件传过来的数据,进行遍历显示。因为该部分不能固定着,以便将来能复用,所以将该部分td表格中的内容用slot具名插槽进行占位,并将td表格中内容剪切到父组件的表格组件标签中,用template标签接收插槽名。还因为该部分遍历的数据item和index在表格组件里,所以需要用slot以属性的方式将这两个数据打包成对象传到父组件,父组件直接解构接收。


表头:直接将标头的内容剪切到父组件的子组件标签中,并在子组件中使用具名插槽占位


并且在表格组件标签的“标签”一列显示 MyTag标签组件标签,将其v-model绑定的数据改为item中的tag

App.vue

<template><div class="table-case"><MyTable :data="goods"><tempalte :slot="head"><th>>编号</th><th>>图片</th><th>>名称</th><th width="100px">标签</th></tempalte><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>
// my-tag 标签组建的封装
//  1.创建组件 - 初始化
//  2.实现功能
//    (1)双击显示,并且自动聚焦 
//       v-if v-else @dbclick 
//       &nextTick =>$refs获取到dom ,进行focus获取焦点
//       封装v-focus指令
//     (2)失去焦点,隐藏输入框//     (3)回显标签信息// 回显的标签信息是父组件传递过来// v-moedl实现功能(简化代码) v-model => :value 和 @input// 组件内部通过props接收,:value设置给输入框
//     (4)内容修改了,回车 =》 修改标签信息// @keyup.enter,触发事件$emit('input',r.target.value)// my-tag 表格组件的封装
// 1.数据不能写死,动态传递表格渲染的数据
// 2.结构不能写死 - 多处结构自定义// (1)表头支持自定义// (2)主体支持自定义
import MyTag from './components/MyTag.vue'
import MyTable from './components/MyTable.vue'export default {// 测试组件功能临时文本tempText:'茶壶',name: 'TableCase',components: {MyTag,MyTable,},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><style lang="less" scoped>
.table-case {width: 1000px;margin: 50px auto;img {width: 100px;height: 100px;object-fit: contain;vertical-align: middle;}}
</style>

MyTable.vue

<template><table class="my-table"><thead><tr><slot name="head"></slot></tr></thead><tbody><tr v-for="(item,index) in data" :key="item.di"><slot :item="item" :index="index"></slot></tr>    </tbody></table>
</template><script>
export default {props:{data:{type:Array,required:true,}}
}
</script><style lang="less">.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>

MyTag.vue

<template><div class="my-tag"><input v-if="isEdit"v-focusref="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// // // 通过ref找到元素,立刻获取焦点// // this.$refs.inp.focus()// // 异步更新,切换到显示状态后,dom并没有进行更新,立即获取焦点实际是获取不到的// // 等dom更新王再获取焦点// this.$nextTick(() => {//   this.$refs.inp.focus()// })// // 每次都要点focus进行获取焦点很麻烦,可以将这套指令封装为指令,在main.js中进行全局注册},handleEnter(e){if (e.target.value.trim() === '') return alert('标签不能为空')// 子传父,将回车时,输入框的内容提交给父组件更新// 由于父组件是v-model,所以触发事件需要触发input事件this.$emit('input',e.target.value)// 提交完成,关闭输入状态this.isEdit = false}}}</script><style lang="less" 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>




补充:在输入框中的  :value = "value",是指将父组件通过v-model传过来的value值绑定给输入框自定义的属性 :value。后面e.target.value也就是获取元素对象属性value的值。

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Linux socket编程

目录 基础概念端口和端口号Socket&#xff08;套接字&#xff09;UDP和TCP的概念 Socket编程实战socket的类型struct sockaddrstruct sockaddr_in网络字节序socket APITCP网络编程流程分析UDP Demo样例 other概念补充setsockopt函数心跳机制面向字节流与面向报文的理解 参考 基…

Linux update-alternatives 命令详解

1、查看所有候选项 sudo update-alternatives --list &#xff08;java筛选​​​​​​​sudo update-alternatives --list java&#xff09; 2、​​​​​​​更换候选项 sudo update-alternatives --config java 3、自动选择优先级最高的作为默认项 sudo update-alterna…

unity3d—demo(2d人物左右移动发射子弹)

目录 人物代码示例&#xff1a; 子弹代码示例&#xff1a; 总结上面代码&#xff1a; 注意点&#xff1a; 人物代码示例&#xff1a; using System.Collections; using System.Collections.Generic; using UnityEngine;public class PlayerTiao : MonoBehaviour {public f…

JSP技术发展现状

多年前&#xff0c;Java入门时学习的JSP可谓时风光无限&#xff0c;J2EE如日中天&#xff0c;短短数年&#xff0c;技术迭代更新光速般发展&#xff0c;有些技术慢慢就退出历史舞台。 JSP&#xff08;Java Server Pages&#xff09; 技术在早期 Java Web 开发中曾是构建动态网…

科技绽放-EtherCAT转Profinet网关智能连接项目

一、项目名称 备选名称及含义&#xff1a;开疆智能EtherCAT转Profinet网关智能连接项目&#xff1a;直接体现了从Profinet到EtherCAT的连接核心内容&#xff0c;智能连接突出了该项目的技术特点。工业互联方案强调了该项目在工业领域实现不同协议设备互联的目标&#xff0c;方案…

《计算机网络》(408大题)

2009 路由转发和静态路由的计算 子网划分、路由聚合的计算 注&#xff1a;CIDR中的子网号可以全为0或1&#xff0c;但是其主机号不允许。 注&#xff1a; 这里其实是把到互联网的路由当做了一个默认路由&#xff08;当一个目的网络地址与路由表中其他都不匹配时&#xff0c;…

matlab读取NetCDF文件

matlab对NetCDF文件进行信息获取和读取数据 文章目录 前言一、什么是NetCDF文件二、读取NetCDF文件数据 1.引入库 2.读入数据总结 前言 在气象学中&#xff0c;许多气象数据存储在NetCDF文件中&#xff0c;后缀为.nc&#xff0c;通常可以用NCL、python和MATLAB等对该…

MySQL用户管理、权限管理练习

1.使用root用户登录MySQL客户端&#xff0c;创建一个名为userl的用户&#xff0c;初始密码为123456; 创建一个名为user2的用户&#xff0c;无初始密码。然后&#xff0c;分别使用uesr1、user2登录MySQL 客户端。 2.使用root用户登录&#xff0c;将user2用户的密码修改为abcabc。…

SpringAOP手动模拟实现反射注解Jdk动态代理

代理 package com.xtq.aop.proxy;import com.xtq.annotations.After; import com.xtq.annotations.Before; import com.xtq.annotations.Pointcut;import java.lang.annotation.Annotation; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Invocation…

算法-字符串-3.无重复字符的最长子串

一、思路&#xff1a; 无重复针对唯一的元素首选哈希表方法 在字符串中找出最长字串——动态数组 二、使用的一些常见方法 1.HashMap a.声明 HashMap<Character,Integer> mapnew HashMap(); b.添加元素 map.put(s.charAt(i),i); c.查询是否有对应的元素存在并获取 m…

Ubuntu中安装配置交叉编译工具并进行测试

01-下载获取交叉编译工具的源码 按照博文 https://blog.csdn.net/wenhao_ir/article/details/144325141的方法&#xff0c;把imx6ull的BSP下载好后&#xff0c;其中就有交叉编译工具。 当然&#xff0c;为了将来使用方便&#xff0c;我已经把它压缩并传到了百度网盘&#xff…

Idea实现定时任务

定时任务 什么是定时任务&#xff1f; 可以自动在项目中根据设定的时长定期执行对应的操作 实现方式 Spring 3.0 版本之后自带定时任务&#xff0c;提供了EnableScheduling注解和Scheduled注解来实现定时任务功能。 使用SpringBoot创建定时任务非常简单&#xff0c;目前主要…

Cesium 问题: 添加billboard后移动或缩放地球,标记点位置会左右偏移

文章目录 问题分析原先的:添加属性——解决漂移移动问题产生新的问题:所选的经纬度坐标和应放置的位置有偏差解决坐标位置偏差的问题完整代码问题 添加 billboard 后, 分析 原先的: // 图标加载 function addStation ({lon, lat, el, testName

PHP中GD库的使用

由于我要用到php的验证码 <?php session_start();// 生成验证码 $random_code substr(md5(uniqid(mt_rand(), true)), 0, 6);// 将验证码保存到 session 中 $_SESSION[captcha] $random_code;// 创建图片 $font 6; $image_width 100; $image_height 40;// 创建图像 $…

精确的单向延迟测量:使用普通硬件和软件

论文标题&#xff1a;Precise One-way Delay Measurement with Common Hardware and Software&#xff08;精确的单向延迟测量&#xff1a;使用普通硬件和软件&#xff09; 作者信息&#xff1a;Maciej Muehleisen 和 Mazen Abdel Latif&#xff0c;来自Ericsson Research Eri…

数据挖掘:一、Weka软件的基本操作

实验目的和要求 了解Weka软件的使用 实验环境 Windows11 Weka3.8.6 实验内容与过程 实验内容 1、了解Weka使用的一般步骤 2、利用Weka,对数据集进行关联规则挖掘及数据分类 3、记录操作步骤、使用的数据、最终的结果 实验过程 首先打开weka下载官网,选择合适

【Notepad++】---设置背景为护眼色(豆沙绿)最新最详细

在编程的艺术世界里&#xff0c;代码和灵感需要寻找到最佳的交融点&#xff0c;才能打造出令人为之惊叹的作品。而在这座秋知叶i博客的殿堂里&#xff0c;我们将共同追寻这种完美结合&#xff0c;为未来的世界留下属于我们的独特印记。 【Notepad】---设置背景为护眼色&#xf…

【微服务】SpringBoot 对接飞书多维表格事件回调监听流程详解

目录 一、前言 二、前置准备 2.1 创建一个应用 2.2 准备一张测试使用的多维表 2.3 获取对接文档 2.4 工程中添加SDK 三、对接过程 3.1 配置Encrypt Key 和 Verification Token 3.2 配置订阅方式 3.3 添加事件 3.4 申请权限 3.5 编写订阅代码 3.6 订阅文档事件 3.…

从0开始边做边学,用vue和python做一个博客,非规范化项目,怎么简单怎么弄,跑的起来有啥毛病解决啥毛病(三)

基础的内容都差不多了&#xff0c;开始研究文章详情页的内容设计&#xff0c;程序员嘛肯定要用markdown编辑了&#xff0c;找了一些发现这个md-editor看着还不错&#xff0c;文档介绍页比较清晰&#xff0c;用着也比较简单。 md-editor安装配置使用Mock.js模拟请求接口mock.js …

pdf转word/markdown等格式——MinerU的部署:2024最新的智能数据提取工具

一、简介 MinerU是开源、高质量的数据提取工具&#xff0c;支持多源数据、深度挖掘、自定义规则、快速提取等。含数据采集、处理、存储模块及用户界面&#xff0c;适用于学术、商业、金融、法律等多领域&#xff0c;提高数据获取效率。一站式、开源、高质量的数据提取工具&…