VUE进阶案例

VUE图片轮播

以下是一个基于Vue.js的图片轮播组件的简单案例:

代码示例
  1. 创建轮播组件 ImageCarousel.vue

    vue 复制代码
    <template>
      <div class="carousel">
        <div class="carousel-inner" :style="{ transform: `translateX(-${currentIndex * 100}%)` }">
          <div v-for="(image, index) in images" :key="index" class="carousel-item">
            < img :src="image" alt="" />
          </div>
        </div>
        <div class="carousel-indicators">
          <span v-for="(image, index) in images" :key="index" :class="{ active: index === currentIndex }" @click="goToSlide(index)"></span>
        </div>
      </div>
    </template>
    
    <script>
    export default {
      name: 'ImageCarousel',
      props: {
        images: {
          type: Array,
          required: true
        }
      },
      data() {
        return {
          currentIndex: 0,
          interval: null
        };
      },
      methods: {
        goToSlide(index) {
          this.currentIndex = index;
        },
        nextSlide() {
          this.currentIndex = (this.currentIndex + 1) % this.images.length;
        }
      },
      mounted() {
        this.interval = setInterval(this.nextSlide, 3000); // 自动播放
      },
      beforeUnmount() {
        clearInterval(this.interval); // 清除定时器
      }
    };
    </script>
    
    <style scoped>
    .carousel {
      position: relative;
      width: 100%;
      max-width: 800px;
      margin: 0 auto;
      overflow: hidden;
    }
    .carousel-inner {
      display: flex;
      transition: transform 0.5s ease;
    }
    .carousel-item {
      flex-shrink: 0;
      width: 100%;
    }
    .carousel-item img {
      width: 100%;
      display: block;
    }
    .carousel-indicators {
      position: absolute;
      bottom: 10px;
      width: 100%;
      text-align: center;
    }
    .carousel-indicators span {
      display: inline-block;
      width: 10px;
      height: 10px;
      margin: 0 5px;
      background-color: #ccc;
      border-radius: 50%;
      cursor: pointer;
    }
    .carousel-indicators span.active {
      background-color: #333;
    }
    </style>
  2. 在父组件中使用轮播组件

    vue 复制代码
    <template>
      <div>
        <h1>图片轮播示例</h1>
        <ImageCarousel :images="imageList" />
      </div>
    </template>
    
    <script>
    import ImageCarousel from './ImageCarousel.vue';
    
    export default {
      components: {
        ImageCarousel
      },
      data() {
        return {
          imageList: [
            'path/to/image1.jpg',
            'path/to/image2.jpg',
            'path/to/image3.jpg'
          ]
        };
      }
    };
    </script>
功能说明
  • 自动播放:轮播图每隔3秒自动切换到下一张图片。
  • 手动切换:用户可以通过点击底部的指示器切换到指定的图片。
  • 指示器:底部的圆点指示器显示当前显示的图片序号,点击可切换图片。
  • 响应式:轮播图根据容器的宽度自动调整图片大小。
注意事项
  • 请将 path/to/image.jpg 替换为实际的图片路径。
  • 可根据需求调整样式和组件逻辑,例如添加过渡效果、修改切换时间等。

记事本案例

以下是一个基于Vue.js的简易记事本案例,包含基本的增删改查功能:


2. 代码实现

2.1 创建记事本组件 NoteApp.vue
vue 复制代码
<template>
  <div class="note-app">
    <div class="header">
      <h1>记事本</h1>
      <input
        v-model="newNote"
        placeholder="输入内容并按回车添加"
        @keyup.enter="addNote"
      />
    </div>
    <ul class="notes-list">
      <li v-for="note in notes" :key="note.id">
        <div class="content">
          <input
            type="text"
            :value="note.content"
            @input="editNote(note.id, $event.target.value)"
          />
        </div>
        <div class="actions">
          <button @click="deleteNote(note.id)">删除</button>
        </div>
      </li>
    </ul>
  </div>
</template>

<script>
export default {
  data() {
    return {
      notes: [
        { id: 1, content: '默认笔记1' },
        { id: 2, content: '默认笔记2' }
      ],
      newNote: ''
    };
  },
  methods: {
    // 添加新笔记
    addNote() {
      if (this.newNote.trim()) {
        const newId = this.notes.length ? this.notes[this.notes.length - 1].id + 1 : 1;
        this.notes.push({ id: newId, content: this.newNote });
        this.newNote = '';
      }
    },
    // 编辑笔记
    editNote(id, content) {
      const note = this.notes.find(note => note.id === id);
      if (note) {
        note.content = content;
      }
    },
    // 删除笔记
    deleteNote(id) {
      this.notes = this.notes.filter(note => note.id !== id);
    }
  }
};
</script>

<style scoped>
.note-app {
  max-width: 600px;
  margin: 0 auto;
  padding: 20px;
}
.header input {
  width: 100%;
  padding: 10px;
  margin-top: 10px;
  font-size: 16px;
}
.notes-list {
  list-style: none;
  padding: 0;
}
.notes-list li {
  margin-bottom: 15px;
  padding: 15px;
  background: #f4f4f4;
  border-radius: 5px;
  display: flex;
  align-items: center;
  justify-content: space-between;
}
.content input {
  width: 80%;
  padding: 8px;
  border: 1px solid #ccc;
  font-size: 14px;
}
.actions {
  display: flex;
  gap: 10px;
}
.actions button {
  padding: 6px 12px;
  background: #e74c3c;
  color: white;
  border: none;
  cursor: pointer;
  border-radius: 3px;
}
</style>
2.2 在父组件中使用
vue 复制代码
<template>
  <div>
    <NoteApp />
  </div>
</template>

<script>
import NoteApp from './NoteApp.vue';

export default {
  components: {
    NoteApp
  }
};
</script>

3. 功能说明

  1. 添加笔记

    • 在输入框输入内容并按回车键,新笔记将被添加到列表。
    • 自动生成唯一ID(模拟数据持久化)。
  2. 编辑笔记

    • 直接修改列表中的输入框内容,内容会实时保存。
  3. 删除笔记

    • 点击笔记右侧的"删除"按钮,对应笔记会被移除。

4. 注意事项

  • 数据持久化 :当前数据存储在内存中,刷新页面后数据会丢失。如需持久化,可结合localStorage或后端API。
  • 样式调整:可根据需求修改样式,例如增加主题色、动画效果等。
  • 扩展功能:可添加排序、搜索、分类等功能。

购物车案例

以下是一个基于Vue.js的购物车案例,包含商品展示、添加到购物车、数量修改和总价计算等功能:


2. 代码实现

2.1 创建购物车组件 ShoppingCart.vue
vue 复制代码
<template>
  <div class="shopping-cart">
    <h2>商品列表</h2>
    <div class="products">
      <div v-for="product in products" :key="product.id" class="product-item">
        < img :src="product.image" alt="商品图片" />
        <div class="product-info">
          <h3>{{ product.name }}</h3>
          <p>价格:¥{{ product.price }}</p >
          <button @click="addToCart(product.id)" :disabled="isInCart(product.id)">
            {{ isInCart(product.id) ? '已添加' : '加入购物车' }}
          </button>
        </div>
      </div>
    </div>

    <div class="cart" v-if="cartItems.length">
      <h2>购物车</h2>
      <ul>
        <li v-for="item in cartItems" :key="item.id">
          <div class="item-info">
            <span>{{ item.name }}</span>
            <span>¥{{ item.price }}</span>
          </div>
          <div class="quantity">
            <button @click="decrementQuantity(item.id)" :disabled="item.quantity === 1">-</button>
            <span>{{ item.quantity }}</span>
            <button @click="incrementQuantity(item.id)">+</button>
          </div>
          <button @click="removeFromCart(item.id)">移除</button>
        </li>
      </ul>
      <div class="total">
        <span>总价:¥{{ total.toFixed(2) }}</span>
      </div>
    </div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      products: [
        {
          id: 1,
          name: '商品1',
          price: 19.99,
          image: 'https://via.placeholder.com/150/00ff00'
        },
        {
          id: 2,
          name: '商品2',
          price: 29.99,
          image: 'https://via.placeholder.com/150/0000ff'
        },
        {
          id: 3,
          name: '商品3',
          price: 14.99,
          image: 'https://via.placeholder.com/150/ff0000'
        }
      ],
      cartItems: []
    };
  },
  computed: {
    total() {
      return this.cartItems.reduce((sum, item) => sum + item.price * item.quantity, 0);
    }
  },
  methods: {
    addToCart(id) {
      const product = this.products.find(p => p.id === id);
      if (product) {
        const existingItem = this.cartItems.find(item => item.id === id);
        if (existingItem) {
          existingItem.quantity++;
        } else {
          this.cartItems.push({ ...product, quantity: 1 });
        }
      }
    },
    removeFromCart(id) {
      this.cartItems = this.cartItems.filter(item => item.id !== id);
    },
    incrementQuantity(id) {
      const item = this.cartItems.find(item => item.id === id);
      if (item) {
        item.quantity++;
      }
    },
    decrementQuantity(id) {
      const item = this.cartItems.find(item => item.id === id);
      if (item && item.quantity > 1) {
        item.quantity--;
      }
    },
    isInCart(id) {
      return this.cartItems.some(item => item.id === id);
    }
  }
};
</script>

<style scoped>
.shopping-cart {
  max-width: 800px;
  margin: 20px auto;
  padding: 20px;
  background: #f4f4f4;
  border-radius: 8px;
}
.products {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
  gap: 20px;
}
.product-item {
  display: flex;
  align-items: center;
  padding: 15px;
  background: white;
  border-radius: 5px;
  box-shadow: 0 2px 4px rgba(0,0,0,0.1);
}
.product-item img {
  width: 80px;
  height: 80px;
  margin-right: 15px;
}
.product-info button {
  padding: 5px 10px;
  background: #2ecc71;
  color: white;
  border: none;
  border-radius: 3px;
  cursor: pointer;
}
.cart ul {
  list-style: none;
  padding: 0;
}
.cart li {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 10px;
  border-bottom: 1px solid #ddd;
}
.quantity button {
  padding: 5px;
  background: #3498db;
  color: white;
  border: none;
  border-radius: 3px;
  margin: 0 5px;
  cursor: pointer;
}
.total {
  margin-top: 20px;
  font-size: 18px;
  font-weight: bold;
}
</style>
2.2 在父组件中使用
vue 复制代码
<template>
  <div>
    <ShoppingCart />
  </div>
</template>

<script>
import ShoppingCart from './ShoppingCart.vue';

export default {
  components: {
    ShoppingCart
  }
};
</script>

3. 功能说明

  1. 商品展示

    • 列表展示商品名称、价格和图片,点击"加入购物车"按钮可添加到购物车。
    • 已添加的商品按钮会显示"已添加"并禁用。
  2. 购物车管理

    • 购物车显示已添加的商品、数量和单价。
    • 支持修改数量(+/-按钮)、移除商品。
    • 实时计算总价并显示。

4. 注意事项

  • 数据持久化 :当前数据存储在内存中,刷新页面后数据会丢失。如需持久化,可结合localStorage或后端API。
  • 样式调整:可根据需求修改样式,例如增加动画效果、主题颜色等。
  • 扩展功能:可添加商品分类、优惠券、支付流程等。

组件通信案例

以下是Vue组件通信的案例,涵盖父子组件、兄弟组件和跨层级组件之间的通信方式。

案例一:父子组件通信

场景:父组件传递数据给子组件,子组件通过事件通知父组件。

代码

父组件(Parent.vue)

vue 复制代码
<template>
  <div>
    <h2>父组件</h2>
    <p>消息:{{ message }}</p >
    <ChildComponent :initialMessage="message" @updateMessage="message = $event" />
  </div>
</template>

<script>
import ChildComponent from './ChildComponent.vue';

export default {
  components: {
    ChildComponent
  },
  data() {
    return {
      message: '来自父组件的消息'
    };
  }
};
</script>

子组件(ChildComponent.vue)

vue 复制代码
<template>
  <div>
    <h3>子组件</h3>
    <input type="text" v-model="currentMessage" @input="updateMessage">
  </div>
</template>

<script>
export default {
  props: {
    initialMessage: String
  },
  data() {
    return {
      currentMessage: this.initialMessage
    };
  },
  methods: {
    updateMessage() {
      this.$emit('updateMessage', this.currentMessage);
    }
  }
};
</script>

说明

  • 父组件通过propsmessage传递给子组件。
  • 子组件使用v-model双向绑定输入框和currentMessage
  • 子组件通过$emit触发updateMessage事件,将修改后的消息传递给父组件。
案例二:兄弟组件通信(通过事件总线)

场景:两个兄弟组件通过事件总线传递数据。

代码

创建事件总线(eventBus.js)

javascript 复制代码
import mitt from 'mitt';

export const bus = mitt();

组件A(ComponentA.vue)

vue 复制代码
<template>
  <div>
    <h3>组件A</h3>
    <button @click="sendMessage">发送消息给组件B</button>
  </div>
</template>

<script>
import { bus } from './eventBus.js';

export default {
  methods: {
    sendMessage() {
      bus.emit('message-to-b', '来自组件A的消息');
    }
  }
};
</script>

组件B(ComponentB.vue)

vue 复制代码
<template>
  <div>
    <h3>组件B</h3>
    <p>收到的消息:{{ receivedMessage }}</p >
  </div>
</template>

<script>
import { bus } from './eventBus.js';

export default {
  data() {
    return {
      receivedMessage: ''
    };
  },
  mounted() {
    bus.on('message-to-b', (message) => {
      this.receivedMessage = message;
    });
  }
};
</script>

父组件(Parent.vue)

vue 复制代码
<template>
  <div>
    <ComponentA />
    <ComponentB />
  </div>
</template>

<script>
import ComponentA from './ComponentA.vue';
import ComponentB from './ComponentB.vue';

export default {
  components: {
    ComponentA,
    ComponentB
  }
};
</script>

说明

  • 创建事件总线bus用于组件间通信。
  • 组件A通过bus.emit发送消息。
  • 组件B通过bus.on监听并接收消息。
案例三:跨层级组件通信(使用provideinject

场景:祖组件向后代组件传递数据。

代码

祖组件(GrandParent.vue)

vue 复制代码
<template>
  <div>
    <h2>祖组件</h2>
    <ParentComponent />
  </div>
</template>

<script>
import ParentComponent from './ParentComponent.vue';

export default {
  components: {
    ParentComponent
  },
  provide() {
    return {
      sharedData: '来自祖组件的数据'
    };
  }
};
</script>

父组件(ParentComponent.vue)

vue 复制代码
<template>
  <div>
    <h3>父组件</h3>
    <ChildComponent />
  </div>
</template>

<script>
import ChildComponent from './ChildComponent.vue';

export default {
  components: {
    ChildComponent
  }
};
</script>

子组件(ChildComponent.vue)

vue 复制代码
<template>
  <div>
    <h4>子组件</h4>
    <p>接收到的数据:{{ sharedData }}</p >
  </div>
</template>

<script>
export default {
  inject: ['sharedData']
};
</script>

说明

  • 祖组件通过provide提供数据sharedData
  • 后代组件通过inject接收并使用sharedData
相关推荐
无名客01 分钟前
npm run dev 启动项目 报Error: listen EACCES: permission denied 0.0.0.0:80 解决方法
前端·javascript·vue.js
零点七九3 分钟前
vue npm install卡住没反应
前端·vue.js·npm
墨菲安全7 分钟前
NPM组件 @0xme5war/apicli 等窃取主机敏感信息
前端·npm·node.js·主机信息窃取·npm恶意包·npm投毒
Komorebi_99998 分钟前
vue create 项目名 和 npm init vue@latest 创建vue项目的不同
前端·vue.js·npm
好好研究3 小时前
使用JavaScript实现轮播图的自动切换和左右箭头切换效果
开发语言·前端·javascript·css·html
paopaokaka_luck5 小时前
基于Spring Boot+Vue的吉他社团系统设计和实现(协同过滤算法)
java·vue.js·spring boot·后端·spring
伍哥的传说7 小时前
Radash.js 现代化JavaScript实用工具库详解 – 轻量级Lodash替代方案
开发语言·javascript·ecmascript·tree-shaking·radash.js·debounce·throttle
程序视点7 小时前
IObit Uninstaller Pro专业卸载,免激活版本,卸载清理注册表,彻底告别软件残留
前端·windows·后端
前端程序媛-Tian7 小时前
【dropdown组件填坑指南】—怎么实现下拉框的位置计算
前端·javascript·vue
iamlujingtao8 小时前
js多边形算法:获取多边形中心点,且必定在多边形内部
javascript·算法