vue框架简单实现商品列表项目,代码+注解

项目需求:将如下图标签一栏点击效果处理

效果解释:

  1. 双击显示输入框,输入框获取焦点

  1. 失去焦点,隐藏输入框
  2. 第2步之后显示标签信息
  3. 内容修改,回车,实现修改标签信息

效果实现:

1.页面整体架构:

此页面为基本的表格页面,包括头部,和元素主要内容呈现,主要实现的功能是在标签一栏内容实现修改。

2.组件元素:

表格整体组件MyTable.vue,包括头部,和元素主要内容呈现。

标签一栏功能组件MyTag.vue,主要是input标签效果实现。

3.根组件App.vue引用组件MyTable.vue,MyTag.vue,main.js文件实现封装获取焦点指令。

代码演示:

App.vue

<template>
  <div class="table-case" id="app">
   <Mytable :list="goods">
    <template #head>
      <th>编号</th>
      <th>名称</th>
      <th>图片</th>
      <th width="100px">标签</th>
    </template>
    <!-- {item,index}也可写为{obj},
      #tbody="{item,index}",直接使用引用组件中数组元素和下标 -->
    <template #tbody="{item,index}">
      <!-- 在MyTable组件中使用具名插槽,
        调用插槽使用,还原内部标签写法,td -->
      <td>{{ index + 1 }}</td>
      <td>{{ item.name }}</td>
      <td>
        <img :src="item.picture" />
      </td>
      <td>
        <!-- 此处进行了组件封装,好处:多次复用 -->
        <Mytag v-model="item.tag"></Mytag>
        <!-- <Mytag v-model="item.tag"></Mytag>
        <Mytag v-model="item.tag"></Mytag>
        <Mytag v-model="item.tag"></Mytag> -->
        
      </td>

    </template>
  </Mytable>
   
  </div>
</template>

<script>
// 导入组件
import Mytag from './components/MyTag.vue'
import Mytable from './components/MyTable.vue'

export default {
  // 设置命名空间
  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;
  }

  .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>

main.js

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

Vue.config.productionTip = false

// 自定义封装全局指令focus
//全局指令设置directive
Vue.directive('focus', {
    // 指令所在的dom元素,被插入到页面中时被触发
    inserted(el) {
        el.focus();
    }
})
new Vue({
    render: h => h(App),
}).$mount('#app')

MyTable.vue

<template>
  <!-- table表格标签 -->
   <table class="my-table">
      <thead>
        
        <tr>
          <!-- 表格头部标签使用具名插槽,使用name属性进行区分 -->
          <slot name="head"></slot>
        </tr>
      </thead>
      <tbody>
        <!-- tbody标签,遍历数组,使用具名插槽,使用name属性进行区分 -->
        <tr v-for="(item,index) in list" :key="item.id">
         <slot name="tbody" :item="item" :index="index"></slot>
        </tr>
      </tbody>
    </table>
</template>

<script>
export default {
  // 接收根组件App.vue传值,此处写法是props校验规范,确认传过来的值是一个数组
    props:{
      list:Array
    }

} 
</script>

<style lang="less" scoped>
.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>
  <!-- table表格标签 -->
   <table class="my-table">
      <thead>
        
        <tr>
          <!-- 表格头部标签使用具名插槽,使用name属性进行区分 -->
          <slot name="head"></slot>
        </tr>
      </thead>
      <tbody>
        <!-- tbody标签,遍历数组,使用具名插槽,使用name属性进行区分 -->
        <tr v-for="(item,index) in list" :key="item.id">
         <slot name="tbody" :item="item" :index="index"></slot>
        </tr>
      </tbody>
    </table>
</template>

<script>
export default {
  // 接收根组件App.vue传值,此处写法是props校验规范,确认传过来的值是一个数组
    props:{
      list:Array
    }

} 
</script>

<style lang="less" scoped>
.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>

暂且分享到这,有问题欢迎一起讨论!共同进步。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值