Vue.js实践-组件基础下

目录

一、动态组件

1、概念

2、代码及演示

二、插槽

1、概念

2、代码及演示

三、引用静态资源

1、引用public目录中的静态资源

[2、 引用src\assets目录中的静态资源](#2、 引用src\assets目录中的静态资源)

四:阶段案例-商品管理


通过上一节的学习,相信读者对组件的基础知识已经有了一定的了解。接下来,本章将继续对组件的基础知识进行讲解,主要包括动态组件、插槽、自定义指令和引用静态资源,学习这些内容,可以帮助读者更灵活地运用组件来开发Vue项目。

一、动态组件

1、概念

2、代码及演示

创建src\components\MyLeft.vue文件。

复制代码
<template>MyLeft组件</template>

创建src\components\MyRight.vue文件

复制代码
<template>MyRight组件</template>

创建src\components\DynamicComponent.vue文件,在该文件中导入并使用MyLeft和MyRight组件,实现单击按钮时动态切换组件的效果。

复制代码
<template>
  <button @click="showComponent = MyLeft">展示MyLeft组件</button>
  <button @click="showComponent = MyRight">展示MyRight组件</button>
  <div><component :is="showComponent"></component></div>
</template>
<script setup >
import MyLeft from './MyLeft.vue'
import MyRight from './MyRight.vue'
import { shallowRef } from 'vue'
const showComponent  = shallowRef(MyLeft)
</script>

修改src\main.js文件,切换页面中显示的组件。

复制代码
import DynamicComponent from './components/DynamicComponent.vue'
createApp(DynamicComponent).mount('#app')

二、插槽

1、概念

2、代码及演示

创建src\components\SlotSubComponent.vue文件,展示子组件的内容

复制代码
<template>
  <div>测试插槽的组件</div>
  <slot></slot>
</template>

创建src\components\MySlot.vue文件,用于展示插槽的相关内容。

复制代码
<template>
  父组件-----{{ message }}
  <hr>
  <!-- 子组件需要写成双标签形式 -->
  <SlotSubComponent>
    <!-- 这是传给子组件插槽的内容 -->
     <span style="color: blue;">下面是测试插槽组件,并传递数据给插槽</span>
    <p>{{ message }}</p>
  </SlotSubComponent>
</template>
<script setup>
import SlotSubComponent from './SlotSubComponent.vue'
const message = '这是组件的使用者自定义的内容'
</script>

具名插槽

代码及演示效果

创建src\components\ArticleInfo.vue文件,用于展示文章内容模板。

复制代码
<template>
  <div class="article-container">
    <div class="header-box"><slot name="header"></slot></div>
    <div class="content-box"><slot name="content"></slot></div>
    <div class="footer-box"><slot name="footer"></slot></div>
  </div>
</template>
<style>
.article-container > div { border: 1px solid black; }
</style>

创建src\components\MyArticle.vue文件,用于提供文章数据,在MyArticle组件中导入并使用ArticleInfo组件,并在<ArticleInfo>标签中为不同插槽添加不同的信息。

复制代码
<template>
  <ArticleInfo>
    <template v-slot:header><p>这是文章的头部区域</p></template>
    <template v-slot:content><p>这是文章的内容区域</p></template>
    <template #footer><p>这是文章的尾部区域</p></template>
  </ArticleInfo>
</template>
<script setup>import ArticleInfo from './ArticleInfo.vue' </script>

三、引用静态资源

1、引用public目录中的静态资源

创建src\components\Image.vue文件

复制代码
<template>
  <img src="/vite.svg" >
</template>

2、 引用src\assets目录中的静态资源

创建src\components\Icon.vue文件。

复制代码
<template>
  <img :src="icon">
</template>
<script setup>
import icon from '../assets/vue.svg'
</script>

在引用src\assets目录中的图片时,首先将图片保存到本地,然后使用import语法将图片导入需要的组件,最后通过img元素的src属性添加图片的路径。

四:阶段案例-商品管理

1、安装并全局引入Element Plus 组件

npm install element-plus

修改main.js

复制代码
// 👇 必须同时引入这两行
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'

createApp(shangpin).use(ElementPlus).mount('#app')

2、全部代码

复制代码
<!-- 商品管理完整可运行代码 -->
<template>
  <el-table :data="goodsList" border style="width: 100%">
    <!-- 编号列 -->
    <el-table-column type="index" label="编号" />

    <!-- 商品名称 -->
    <el-table-column prop="goods_name" label="商品名称" />

    <!-- 商品价格 -->
    <el-table-column prop="goods_price" label="商品价格" />

    <!-- 标签列(作用域插槽) -->
    <el-table-column label="标签">
      <template v-slot="{ row }">
        <div class="flex gap-2 items-center">
          <!-- 标签循环 -->
          <el-tag
            v-for="(tag, index) in row.tags"
            :key="index"
            closable
            disable-transitions
            @close="() => handleClose(row, tag)"
          >
            {{ tag }}
          </el-tag>

          <!-- 新增标签输入框 -->
          <el-input
            v-if="row.inputVisible"
            v-model="row.inputValue"
            size="small"
            class="w-20"
            @keyup.enter="() => handleInputConfirm(row)"
            @blur="() => handleInputConfirm(row)"
          />

          <!-- +Tag 按钮 -->
          <el-button
            v-else
            class="button-new-tag"
            size="small"
            @click="() => showInput(row)"
          >
            + Tag
          </el-button>
        </div>
      </template>
    </el-table-column>

    <!-- 操作列 -->
    <el-table-column label="操作">
      <template v-slot="{ row }">
        <el-button type="danger" plain @click="onRemove(row.id)">
          删除
        </el-button>
      </template>
    </el-table-column>
  </el-table>
</template>

<script setup>
import { ref, nextTick } from 'vue'

// 商品列表数据
const goodsList = ref([
  {
    id: 1,
    goods_name: '夏季专柜同款女鞋',
    goods_price: 298,
    tags: ['舒适', '透气'],
    inputVisible: false,
    inputValue: ''
  },
  {
    id: 2,
    goods_name: '冬季保暖女士休闲雪地靴 舒适加绒防水短靴 防滑棉鞋',
    goods_price: 89,
    tags: ['保暖', '防滑'],
    inputVisible: false,
    inputValue: ''
  },
  {
    id: 3,
    goods_name: '秋冬新款女士毛衣 套头宽松针织衫 简约上衣',
    goods_price: 199,
    tags: ['秋冬', '毛衣'],
    inputVisible: false,
    inputValue: ''
  },
  {
    id: 4,
    goods_name: '2023春秋装新款大码女装 衬衫 上衣',
    goods_price: 19,
    tags: ['雪纺衫', '打底'],
    inputVisible: false,
    inputValue: ''
  },
  {
    id: 5,
    goods_name: '长款长袖圆领女士毛衣 2022秋装新款假两件连衣裙',
    goods_price: 178,
    tags: ['圆领', '连衣裙'],
    inputVisible: false,
    inputValue: ''
  }
])

// 关闭标签
const handleClose = (row, tag) => {
  const i = row.tags.indexOf(tag)
  if (i >= 0) row.tags.splice(i, 1)
}

// 显示输入框
const showInput = async (row) => {
  row.inputVisible = true
  await nextTick()
  // 让输入框自动聚焦
  const input = document.querySelector('.el-input__inner:focus')
  input?.focus()
}

// 确认添加标签
const handleInputConfirm = (row) => {
  if (row.inputValue.trim()) {
    row.tags.push(row.inputValue.trim())
  }
  row.inputValue = ''
  row.inputVisible = false
}

// 删除整行
const onRemove = (id) => {
  goodsList.value = goodsList.value.filter(item => item.id !== id)
}
</script>

<style scoped>
.flex {
  display: flex;
}
.gap-2 {
  gap: 8px;
}
.items-center {
  align-items: center;
}
.w-20 {
  width: 80px;
}
.button-new-tag {
  height: 24px;
  line-height: 24px;
  padding: 0 8px;
}
</style>
相关推荐
小白学大数据1 小时前
JS 混淆加密下的 Python 爬虫解决方案
javascript·爬虫·python
一棵白菜1 小时前
Claude Code + Amazon Bedrock 使用指南
前端
大家的林语冰2 小时前
前端周刊:axios 疑遭朝鲜黑客“钓鱼“;CSS 新函数上线;npm 上线深色主题;Oxlint 兼容表;ESLint 支持 Temporal......
前端·javascript·css
哀木3 小时前
一个简单的套壳方案,就能让你的 Agent 少做重复初始化
前端
问心无愧05133 小时前
ctf show web入门27
前端
小村儿4 小时前
给 AI Agent 装上"长期记忆":Karpathy 的 LLM Wiki 思想,我做成了工具
前端·后端·ai编程
竹林8184 小时前
用ethers.js连接MetaMask实现Web3钱包登录:从踩坑到稳定运行的完整记录
前端·javascript
heyCHEEMS4 小时前
如何用 Recast 实现静态配置文件源码级读写
前端·node.js
心连欣4 小时前
从零开始,学习所有指令!
前端·javascript·vue.js