Vue 组件技术博客:构建一个交互式披萨定制界面

应用场景介绍

在许多电子商务网站中,用户经常需要根据自己的喜好定制产品。本文将介绍如何使用 Vue 构建一个交互式披萨定制界面,允许用户选择披萨的大小、外皮、浇头和配料,并实时更新总价。

代码基本功能介绍

此 Vue 组件提供了以下功能:

  • 披萨大小、外皮和浇头选项
  • 实时更新的总价
  • 添加到购物车按钮
  • 切换到不同的选项卡(主页、菜单、购物车、更多)

功能实现步骤及关键代码分析说明

1. 安装依赖项

npm install vue vue-router echarts-for-vue v-calendar vue3-baidu-map-gl @wangeditor/editor-for-vue

2. 组件模板

<template>
  <div class="bg-gray-100">
    <!-- 导航栏 -->
    <div class="flex items-center justify-between p-4 border-b border-gray-200">
      <a-back-top />
      <div class="text-lg font-semibold">Detail</div>
      <a-button type="link" icon={<MessageOutlined />} />
    </div>

    <!-- 披萨图片 -->
    <div class="flex items-center justify-center">
      <img
        class="w-48 h-48 rounded-full object-cover"
        src="https://source.unsplash.com/random/400x400"
        alt="Pizza"
      />
    </div>

    <!-- 披萨信息 -->
    <div class="p-4">
      <h2 class="text-2xl font-semibold">Margherita with Tomatoes</h2>
      <div class="flex items-center mt-2">
        <a-rate allow-half value={3} disabled />
        <span class="ml-2 text-sm text-gray-500">3.5</span>
      </div>
      <div class="mt-4">
        <p class="text-gray-500">
          Mauris eu erat quis ante bibendum eleifend. Curabitur egestas sapien sit amet porta sagittis. In semper nibh ac ipsum tempor egestas.
        </p>
      </div>

      <!-- 披萨定制选项 -->
      <div class="mt-4">
        <div class="text-lg font-semibold">Size</div>
        <div class="flex items-center mt-2">
          <a-radio-group v-model="size" class="mr-4">
            <a-radio value="small">Small</a-radio>
            <a-radio value="medium">Medium</a-radio>
            <a-radio value="large">Large</a-radio>
          </a-radio-group>
          <div class="text-sm text-gray-500">
            <span v-if="size === 'small'">320g</span>
            <span v-else-if="size === 'medium'">830g</span>
            <span v-else>1200g</span>
          </div>
        </div>
      </div>
      <div class="mt-4">
        <div class="text-lg font-semibold">Crust</div>
        <div class="flex items-center mt-2">
          <a-radio-group v-model="crust" class="mr-4">
            <a-radio value="standard">Standard</a-radio>
            <a-radio value="garlicRoasted">Garlic Roasted</a-radio>
            <a-radio value="cheeseBurst">Cheese Burst</a-radio>
          </a-radio-group>
        </div>
      </div>
      <div class="mt-4">
        <div class="text-lg font-semibold">Toppings</div>
        <div class="flex items-center mt-2">
          <a-checkbox-group v-model="toppings">
            <a-checkbox value="standard">Standard</a-checkbox>
            <a-checkbox value="extraCheese">Extra Cheese</a-checkbox>
            <a-checkbox value="extraSpice">Extra Spice</a-checkbox>
          </a-checkbox-group>
        </div>
      </div>

      <!-- 总价 -->
      <div class="mt-4">
        <div class="flex items-center justify-between">
          <div class="text-lg font-semibold">TOTAL</div>
          <div class="text-lg font-semibold">$14.90</div>
        </div>
      </div>

      <!-- 添加到购物车按钮 -->
      <div class="mt-4">
        <a-button type="primary" block>Add To Cart</a-button>
      </div>
    </div>

    <!-- 选项卡 -->
    <a-tabs class="mt-4">
      <a-tab-pane tab="Home" key="1">
        <template #tab-content>
          <div class="p-4">
            <a-list
              :dataSource="listData"
              renderItem="{ item }"
            >
              <a-list-item>
                <a-skeleton avatar title={false} paragraph={{ rows: 1 }} />
              </a-list-item>
            </a-list>
          </div>
        </template>
      </a-tab-pane>
      <a-tab-pane tab="Menu" key="2">
        <template #tab-content>
          <div class="p-4">
            <a-list
              :dataSource="listData"
              renderItem="{ item }"
            >
              <a-list-item>
                <a-skeleton avatar title={false} paragraph={{ rows: 1 }} />
              </a-list-item>
            </a-list>
          </div>
        </template>
      </a-tab-pane>
      <a-tab-pane tab="Cart" key="3">
        <template #tab-content>
          <div class="p-4">
            <a-list
              :dataSource="listData"
              renderItem="{ item }"
            >
              <a-list-item>
                <a-skeleton avatar title={false} paragraph={{ rows: 1 }} />
              </a-list-item>
            </a-list>
          </div>
        </template>
      </a-tab-pane>
      <a-tab-pane tab="More" key="4">
        <template #tab-content>
          <div class="p-4">
            <a-list
              :dataSource="listData"
              renderItem="{ item }"
            >
              <a-list-item>
                <a-skeleton avatar title={false} paragraph={{ rows: 1 }} />
              </a-list-item>
            </a-list>
          </div>
        </template>
      </a-tab-pane>
    </a-tabs>
  </div>
</template>

3. 组件脚本

<script lang="tsx" setup>
import * as echarts from 'echarts';
import { h } from "vue";
import { createComponent } from 'echarts-for-vue';
import { Calendar } from 'v-calendar';
import { BMap } from 'vue3-baidu-map-gl';
import { Editor, Toolbar } from "@wangeditor/editor-for-vue";
import { onBeforeUnmount, ref, shallowRef } from 'vue';

const ECharts = createComponent({echarts, h});

const listData = Array.from({ length: 10 }).map((_, i) => ({
  id: i,
  title: `item ${i}`,
  description: `description of item ${i}`,
}));

const size = ref('medium');
const crust = ref('standard');
const toppings = ref(['standard']);

const editorConfig = ref({
  placeholder: '请输入内容...'
});
const editor = shallowRef();

const handleEditorCreated = (editorInstance) => {
  // Attach the editor instance to the ref
  editor.value = editorInstance;
  console.log("editor.value", editor.value, editorInstance)
};

onBeforeUnmount(() => {
  // Destroy the editor instance before the component is unmounted
  editor.value.destroy();
  editor.value = null;
});
</script>

4. 样式

.bg-gray-100 {
  background-color: #f5f5f5;
}

.text-lg {
  font-size: 
登录
ECHO推荐
ScriptEcho.ai

用户批注

信息填写

我要吐槽
新手指引
在线客服