商品列表
文章目录
- 商品列表
- 核心步骤
- 创建组件
- 1. MyTag组件详细步骤
- 双击显示,自动聚焦
- 失去焦点,隐藏输入框
- 回显标签信息
- 回车修修改内容,同时隐藏输入框
- MyTable组件详细步骤
- 1-动态的设置整个表格的数据 : props
- 2-实现自定义结构-插槽
- 1-表头自定义
- 2-主体定制
- 完整代码
- App.vue组件
- MyTab.vue组件
- MyTable组件
- 最终效果图:
核心步骤
MyTag 组件的封装
-
创建组件 → 初始化
-
实现功能
(1)双击显示,并开启自动聚焦
1. v-if v-else @dblclick
2. 通过注册全局的自定义指令获取焦点 focus
(2)失去焦点的时候,隐藏输入框
1. 然后使用@blur失去焦点隐藏
(3)回显标签信息
-
回显的标签信息是父组件传递过来的
2. 使用 v-model 实现功能(简化代码) 3. v-model ===> :value 和 @input
(4)内容修改了,回车 → 修改标签信息
1. @keyup.enter ,触发了回车事件 执行 $emit(‘input’,e.target.value)
2. 然后父组件中的 v-model 底层的 @input自动帮我们执行数据渲染回显
My-Table 表格组件的封装
- 数据不能写死,需要动态的传递表格渲染数据
使用: props
-
结构不能写死 → 多处结构实现自定义 → 具名插槽
(1) 表头需要支持自定义
(2) 主体支持自定义
创建组件
- 创建组件 → 初始化
1.导入
import MyTag from './components/MyTag.vue'
import MyTable from './components./Mytable.vue'
2. 注册
components: {
MyTag,
MyTable
}
3. 使用
<MyTag></MyTag>
<MyTable></MyTable>
1. MyTag组件详细步骤
双击显示,自动聚焦
1.双击显示
1.双击显示
<div v-else @dblclick="handleedit" class="text">{{ value }}</div>
//提供以下方法
handleedit() {
// 双击切换到显示状态
this.isShow = true;
},
2 自动聚焦
2.自动聚焦
// 封装全局自定义指令(实现获取焦点),当然可以使用$nextTick解决同步Vue的问题,达到异步更新效果
Vue.directive('focus', {
// el 是我们指令所在的dom元素
inserted (el) {
el.focus()
}
})
失去焦点,隐藏输入框
-
失去焦点,隐藏输入框
使用blur事件失去焦点,然后将isShow改为false @blur="isShow = false"
回显标签信息
在我们双击了触发了编辑功能后,显示了输入框,然后再自动获得focus。
- 现在我们需要回显了
-
使用v-model将父组件的值传递过来
-
然后子组件使用 props 接受 进行操作
-
给组件绑定 v-model 指令
<MyTag v-model="item.tag"></MyTag>
-
props接收数据,并回显渲染
1. props接收数据 // 接收父组件传过来的数据 :value props: { value: String, }, 2. 回显渲染 //将数据动态的赋值给我们的需要显示的标签 :value="value"
回车修修改内容,同时隐藏输入框
- 绑定回车事件 @keyup.enter=“方法名”
@keyup.enter="handleEnter"
- 提供对应方法: handleEnter()
1. 通过$emit('事件名',传递的值) 通知父组件 methods: { handleEnter (e) { //子传父,将获取到的输入框给父组件,通知他修改渲染标签 if (e.target.value.trim() === '') { alert('修改的内容不能为空') return //通过 input事件 同志父组件监听,并修改输入框内容 this.$emit('input',e.target.value) } } } 2. 回车后,输入框隐藏 this.isShow = false
到此,我们的编辑功能组件实现完毕
MyTable组件详细步骤
1-动态的设置整个表格的数据 : props
-
数据在App.vue中,使用父传子实现
1. 动态的属性传递数据 <MyTable :data="item.goods"></MyTable> 2. 接收数据 props: { data: { type: Array, required: true 控制判断 } }
2-实现自定义结构-插槽
- 表头自定义
- 主体自定义
- 目的是为了,我们能够灵活的实现结构和数据对应
- 记得在相应的组件中使用 : 占好位置
1-表头自定义
1.表头自定义:切记使用具名插槽,因为我们需要在定制的时候,用到相互之间的数据。
<!-- 使用插槽动态的定制了表头结构 -->
<template #head>
<th>编号</th>
<th>名称</th>
<th>图片</th>
<th width="100px">标签</th>
</template>
2-主体定制
2. 主体定制:同样的使用具名插槽,需要制定并且传递该组件的数据
<!-- 使用插槽作用域传递值,定制主体的内容 -->
<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>
编辑渲染功能和自定义结构功能就实现完毕了
完整代码
App.vue组件
<template>
<div class="table-case">
<MyTable :data="goods">
<!-- 使用插槽动态的定制了表头结构 -->
<template #head>
<th>编号</th>
<th>名称</th>
<th>图片</th>
<th width="100px">标签</th>
</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>
export default{
import MyTag from './components/MyTag.vue'
import MyTable from "./components/MyTable.vue";
export default {
// 2.注册组件
components: {
MyTag,
MyTable,
},
name: "TableCase",
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>
MyTab.vue组件
<template>
<div class="my-tag">
<input
v-if="isShow"
v-focus
@blur="isShow = false"
:value="value"
@keyup.enter="handleEnter"
class="input"
type="text"
placeholder="输入标签"
/>
<div v-else @dblclick="handleedit" class="text">{{ value }}</div>
</div>
</template>
---------------------------------------------------
<script>
export default {
// 接收父组件传过来的数据 :value
props: {
value: String,
},
data() {
return {
isShow: false,
};
},
methods: {
handleedit() {
// 双击切换到显示状态
this.isShow = true
},
handleEnter(e) {
// 子传父,将{输入框的内容}传递给我们的父组件,通知他叫他渲染
// 由于父组件是 v-model 所以触发事件为 @input
if (e.target.value.trim() === "") return alert("修改内容不能为空")
this.$emit("input", e.target.value)
// 回车后输入框隐藏
this.isShow = false
},
},
};
</script>
MyTable组件
<template>
<table class="my-table">
<thead>
<tr>
<slot name="head"></slot>
</tr>
</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>