Vue3 学习教程,从入门到精通,基于 Vue 3 + Element Plus + ECharts + JavaScript的51购商城项目(45)

51购商城项目语法知识点及使用方法

以下是基于Vue3、Element Plus、ECharts和JavaScript的语法知识点及使用方法。每个知识点都包含详细的解释和案例代码,并附有详细注释。最后提供一些综合性案例,帮助你更好地理解和应用这些技术。


一、Vue3核心语法

1. 组合式API(Composition API)

概述 :Vue3引入了组合式API,使得逻辑复用和代码组织更加灵活。通过setup函数或<script setup>语法糖,可以更简洁地编写组件逻辑。

案例代码

vue 复制代码
<!-- ProductList.vue -->
<template>
  <div>
    <el-button @click="fetchProducts">加载商品</el-button>
    <el-table :data="products" style="width: 100%">
      <el-table-column prop="id" label="ID" width="50"></el-table-column>
      <el-table-column prop="name" label="名称"></el-table-column>
      <el-table-column prop="price" label="价格"></el-table-column>
    </el-table>
  </div>
</template>

<script setup>
import { ref, onMounted } from 'vue';
import axios from 'axios';

// 定义响应式数据
const products = ref([]);

// 方法:获取商品列表
const fetchProducts = async () => {
  try {
    const response = await axios.get('/api/products');
    products.value = response.data;
  } catch (error) {
    console.error('获取商品失败:', error);
  }
};

// 生命周期钩子:组件挂载时获取商品
onMounted(() => {
  fetchProducts();
});
</script>

注释

  • ref用于定义响应式数据。
  • onMounted是生命周期钩子,组件挂载时调用。
  • axios用于HTTP请求获取数据。

2. 组件通信(Props & Emits)

概述 :父子组件之间通过props传递数据,通过emits触发事件进行通信。

案例代码

vue 复制代码
<!-- ParentComponent.vue -->
<template>
  <div>
    <ChildComponent :message="parentMessage" @child-event="handleChildEvent" />
  </div>
</template>

<script setup>
import { ref } from 'vue';
import ChildComponent from './ChildComponent.vue';

const parentMessage = ref('Hello from Parent');
const handleChildEvent = (payload) => {
  console.log('Received from child:', payload);
}
</script>

<!-- ChildComponent.vue -->
<template>
  <el-button @click="sendEvent">发送事件到父组件</el-button>
</template>

<script setup>
import { defineProps, defineEmits } from 'vue';

const props = defineProps({
  message: {
    type: String,
    required: true
  }
});

const emit = defineEmits(['child-event']);

const sendEvent = () => {
  emit('child-event', 'Hello Parent!');
}
</script>

注释

  • defineProps用于定义父组件传递的props
  • defineEmits用于定义子组件触发的事件。
  • 子组件通过emit触发事件,父组件通过@监听事件。

3. 路由(Vue Router)

概述:使用Vue Router实现单页面应用(SPA)的导航。

案例代码

javascript 复制代码
// router/index.js
import { createRouter, createWebHistory } from 'vue-router';
import Home from '../views/Home.vue';
import ProductDetail from '../views/ProductDetail.vue';

const routes = [
  { path: '/', name: 'Home', component: Home },
  { path: '/product/:id', name: 'ProductDetail', component: ProductDetail, props: true },
];

const router = createRouter({
  history: createWebHistory(),
  routes,
});

export default router;
vue 复制代码
<!-- App.vue -->
<template>
  <el-container>
    <el-header>
      <el-menu :default-active="activeRoute" mode="horizontal">
        <el-menu-item index="1" @click="$router.push('/')">首页</el-menu-item>
        <el-menu-item index="2" @click="$router.push('/products')">商品</el-menu-item>
      </el-menu>
    </el-header>
    <el-main>
      <router-view></router-view>
    </el-main>
    <el-footer>51购商城 © 2025</el-footer>
  </el-container>
</template>

<script setup>
import { useRoute, useRouter } from 'vue-router';
const route = useRoute();
const router = useRouter();

const activeRoute = computed(() => {
  return route.path === '/' ? '1' : '2';
});
</script>

注释

  • createRoutercreateWebHistory用于创建路由实例。
  • router-view用于渲染匹配的组件。
  • activeRoute通过useRouteuseRouter获取当前路由状态。

二、Element Plus组件实战

1. 表单处理

案例代码

vue 复制代码
<!-- LoginForm.vue -->
<template>
  <el-form :model="form" :rules="rules" ref="loginForm" label-width="80px">
    <el-form-item label="用户名" prop="username">
      <el-input v-model="form.username"></el-input>
    </el-form-item>
    <el-form-item label="密码" prop="password">
      <el-input type="password" v-model="form.password"></el-input>
    </el-form-item>
    <el-form-item>
      <el-button type="primary" @click="onSubmit">登录</el-button>
      <el-button @click="onReset">重置</el-button>
    </el-form-item>
  </el-form>
</template>

<script setup>
import { reactive, ref } from 'vue';
import { ElMessage } from 'element-plus';
import axios from 'axios';

const form = reactive({
  username: '',
  password: ''
});

const rules = {
  username: [
    { required: true, message: '请输入用户名', trigger: 'blur' },
    { min: 3, max: 15, message: '长度在3到15个字符', trigger: 'blur' }
  ],
  password: [
    { required: true, message: '请输入密码', trigger: 'blur' },
    { min: 6, message: '密码至少6位', trigger: 'blur' }
  ]
};

const loginForm = ref(null);

const onSubmit = () => {
  loginForm.value.validate((valid) => {
    if (valid) {
      // 登录逻辑
      axios.post('/api/login', form)
        .then(() => {
          ElMessage.success('登录成功');
        })
        .catch((error) => {
          ElMessage.error('登录失败');
        });
    } else {
      console.log('验证失败');
      return false;
    }
  });
}

const onReset = () => {
  loginForm.value.resetFields();
}
</script>

注释

  • el-form创建表单,model绑定数据,rules定义验证规则。
  • el-input用于输入,el-button用于提交和重置。
  • ElMessage用于消息提示。

2. 表格组件

案例代码

vue 复制代码
<!-- ProductTable.vue -->
<template>
  <el-table :data="products" style="width: 100%">
    <el-table-column prop="id" label="ID" width="50"></el-table-column>
    <el-table-column prop="name" label="名称"></el-table-column>
    <el-table-column prop="price" label="价格"></el-table-column>
    <el-table-column label="操作" width="150">
      <template #default="scope">
        <el-button type="primary" size="small" @click="viewDetail(scope.row.id)">查看</el-button>
        <el-button type="success" size="small" @click="addToCart(scope.row)">加入购物车</el-button>
      </template>
    </el-table-column>
  </el-table>
</template>

<script setup>
import { ref } from 'vue';
import axios from 'axios';
import { ElMessage } from 'element-plus';

const products = ref([]);

const fetchProducts = async () => {
  try {
    const response = await axios.get('/api/products');
    products.value = response.data;
  } catch (error) {
    ElMessage.error('获取商品失败');
  }
}

const viewDetail = (id) => {
  // 跳转到商品详情页
  console.log('查看商品详情:', id);
}

const addToCart = (item) => {
  // 添加到购物车逻辑
  ElMessage.success(`已加入购物车: ${item.name}`);
}

onMounted(() => {
  fetchProducts();
});
</script>

注释

  • el-table创建表格,el-table-column定义列。
  • scope用于访问当前行数据。
  • ElMessage用于操作提示。

三、ECharts数据可视化

1. 基础图表

案例代码

vue 复制代码
<!-- SalesChart.vue -->
<template>
  <div ref="chartRef" style="width: 600px; height: 400px;"></div>
</template>

<script setup>
import * as echarts from 'echarts';
import { ref, onMounted } from 'vue';

const chartRef = ref(null);

const fetchSalesData = async () => {
  // 获取销售数据
  const response = await axios.get('/api/sales');
  return response.data;
}

onMounted(async () => {
  const salesData = await fetchSalesData();
  const chart = echarts.init(chartRef.value);
  const option = {
    title: {
      text: '销售趋势'
    },
    tooltip: {},
    xAxis: {
      data: salesData.labels
    },
    yAxis: {},
    series: [{
      name: '销量',
      type: 'bar',
      data: salesData.values
    }]
  };
  chart.setOption(option);
});
</script>

注释

  • echarts.init初始化图表,setOption设置图表配置。
  • xAxisyAxis定义坐标轴,series定义数据系列。

2. 动态图表更新

案例代码

vue 复制代码
<!-- DynamicChart.vue -->
<template>
  <div ref="chartRef" style="width: 600px; height: 400px;"></div>
</template>

<script setup>
import * as echarts from 'echarts';
import { ref, onMounted, onUnmounted } from 'vue';

const chartRef = ref(null);
let chart = null;
let timer = null;

const fetchDynamicData = async () => {
  // 获取动态数据
  const response = await axios.get('/api/dynamic-data');
  return response.data;
}

onMounted(() => {
  chart = echarts.init(chartRef.value);
  updateChart();
  timer = setInterval(updateChart, 5000); // 每5秒更新一次
});

const updateChart = async () => {
  const data = await fetchDynamicData();
  const option = {
    title: {
      text: '实时数据'
    },
    tooltip: {},
    xAxis: {
      data: data.labels
    },
    yAxis: {},
    series: [{
      name: '值',
      type: 'line',
      data: data.values
    }]
  };
  chart.setOption(option);
}

onUnmounted(() => {
  if (timer) {
    clearInterval(timer);
  }
  if (chart) {
    chart.dispose();
  }
});
</script>

注释

  • setInterval用于定时更新图表数据。
  • onUnmounted清除定时器和释放图表资源。

四、综合案例

1. 购物车功能实现

案例代码

vue 复制代码
<!-- Cart.vue -->
<template>
  <el-table :data="cartItems" style="width: 100%">
    <el-table-column prop="id" label="ID" width="50"></el-table-column>
    <el-table-column prop="name" label="商品名称"></el-table-column>
    <el-table-column prop="price" label="价格" width="100"></el-table-column>
    <el-table-column label="数量" width="150">
      <template #default="scope">
        <el-input-number v-model="scope.row.quantity" @change="updateQuantity(scope.row)" :min="1" :max="100"></el-input-number>
      </template>
    </el-table-column>
    <el-table-column label="操作" width="100">
      <template #default="scope">
        <el-button type="danger" size="small" @click="removeItem(scope.row)">移除</el-button>
      </template>
    </el-table-column>
  </el-table>
  <div style="margin-top: 20px;">
    <el-button type="primary" @click="checkout">结算</el-button>
  </div>
</template>

<script setup>
import { ref, reactive } from 'vue';
import { ElMessage } from 'element-plus';
import axios from 'axios';

const cartItems = ref([
  { id: 1, name: '商品1', price: 100, quantity: 2 },
  { id: 2, name: '商品2', price: 200, quantity: 1 }
]);

const updateQuantity = (item) => {
  if (item.quantity < 1) {
    item.quantity = 1;
  }
  ElMessage.info(`更新数量为: ${item.quantity}`);
}

const removeItem = (item) => {
  cartItems.value = cartItems.value.filter(i => i.id !== item.id);
  ElMessage.success('移除成功');
}

const checkout = () => {
  axios.post('/api/checkout', cartItems.value)
    .then(() => {
      ElMessage.success('结算成功');
      cartItems.value = [];
    })
    .catch(() => {
      ElMessage.error('结算失败');
    });
}
</script>

注释

  • 使用el-table展示购物车商品,el-input-number用于数量调整。
  • updateQuantity方法确保数量不低于1。
  • removeItem方法移除商品,checkout方法进行结算。

2. 登录与注册功能实现

案例代码

vue 复制代码
<!-- Login.vue -->
<template>
  <el-form :model="form" :rules="rules" ref="loginForm" label-width="80px">
    <el-form-item label="用户名" prop="username">
      <el-input v-model="form.username"></el-input>
    </el-form-item>
    <el-form-item label="密码" prop="password">
      <el-input type="password" v-model="form.password"></el-input>
    </el-form-item>
    <el-form-item>
      <el-button type="primary" @click="onSubmit">登录</el-button>
      <el-button @click="onReset">重置</el-button>
    </el-form-item>
  </el-form>
</template>

<script setup>
import { reactive, ref } from 'vue';
import { ElMessage } from 'element-plus';
import axios from 'axios';

const form = reactive({
  username: '',
  password: ''
});

const rules = {
  username: [
    { required: true, message: '请输入用户名', trigger: 'blur' },
    { min: 3, max: 15, message: '长度在3到15个字符', trigger: 'blur' }
  ],
  password: [
    { required: true, message: '请输入密码', trigger: 'blur' },
    { min: 6, message: '密码至少6位', trigger: 'blur' }
  ]
};

const loginForm = ref(null);

const onSubmit = () => {
  loginForm.value.validate((valid) => {
    if (valid) {
      // 登录逻辑
      axios.post('/api/login', form)
        .then(() => {
          ElMessage.success('登录成功');
        })
        .catch(() => {
          ElMessage.error('登录失败');
        });
    } else {
      console.log('验证失败');
      return false;
    }
  });
}

const onReset = () => {
  loginForm.value.resetFields();
}
</script>

注释

  • 使用el-formel-form-item构建登录表单,el-input用于输入。
  • rules定义表单验证规则,validate方法进行验证。
  • ElMessage用于提示用户操作结果。

3. AIGC辅助优化代码

案例代码

javascript 复制代码
// aiOptimize.js
import axios from 'axios';

const analyzeCode = async (code) => {
  const response = await axios.post('/api/ai-analyze', { code });
  return response.data;
}

const optimizeSuggestions = (suggestions) => {
  // 处理AI建议
  // 例如,提取关键点,排序优先级等
  return suggestions;
}

export const getOptimizedCode = async (code) => {
  const suggestions = await analyzeCode(code);
  const optimizedSuggestions = highlightSuggestions(suggestions);
  // 根据建议优化代码
  // 这里假设返回优化后的代码
  return applySuggestions(code, optimizedSuggestions);
}

const applySuggestions = (code, suggestions) => {
  // 应用AI建议到代码中
  // 例如,使用正则替换某些部分
  // 这里只是示例,实际实现需要具体分析
  return code;
}

注释

  • analyzeCode方法调用AI服务分析代码。
  • optimizeSuggestions方法处理AI建议,applySuggestions方法应用建议到代码中。
  • getOptimizedCode方法整合整个优化流程。

五、总结

以上内容涵盖了Vue3、Element Plus、ECharts和JavaScript的核心语法及实际应用案例。通过这些知识点和案例,你可以更好地理解51购商城的开发过程,并应用到实际项目中。

综合性案例

1. 综合商品展示与购物车功能
vue 复制代码
<!-- ProductListWithCart.vue -->
<template>
  <el-container>
    <el-aside width="200px">
      <el-menu>
        <el-menu-item index="1">分类1</el-menu-item>
        <el-menu-item index="2">分类2</el-menu-item>
      </el-menu>
    </el-aside>
    <el-main>
      <el-table :data="products" style="width: 100%">
        <el-table-column prop="id" label="ID" width="50"></el-table-column>
        <el-table-column prop="name" label="商品名称"></el-table-column>
        <el-table-column prop="price" label="价格" width="100"></el-table-column>
        <el-table-column label="数量" width="150">
          <template #default="scope">
            <el-input-number v-model="scope.row.quantity" @change="updateQuantity(scope.row)" :min="1" :max="100"></el-input-number>
          </template>
        </el-table-column>
        <el-table-column label="操作" width="100">
          <template #default="scope">
            <el-button type="success" size="small" @click="addToCart(scope.row)">加入购物车</el-button>
          </template>
        </el-table-column>
      </el-table>
    </el-main>
    <el-aside width="200px">
      <el-button type="primary" @click="goToCart">查看购物车</el-button>
    </el-aside>
  </el-container>
</template>

<script setup>
import { ref, reactive } from 'vue';
import { ElMessage } from 'element-plus';
import axios from 'axios';

const products = ref([
  { id: 1, name: '商品1', price: 100, quantity: 1 },
  { id: 2, name: '商品2', price: 200, quantity: 1 }
]);

const cart = reactive([]);

const updateQuantity = (item) => {
  if (item.quantity < 1) {
    item.quantity = 1;
  }
  ElMessage.info(`更新数量为: ${item.quantity}`);
}

const addToCart = (item) => {
  const existing = cart.find(i => i.id === item.id);
  if (existing) {
    existing.quantity += item.quantity;
  } else {
    cart.push({ ...item });
  }
  ElMessage.success('加入购物车成功');
}

const goToCart = () => {
  // 跳转到购物车页面
  console.log('查看购物车');
}
</script>

注释

  • 使用el-container布局,el-aside用于侧边栏,el-main用于主内容区。
  • el-input-number用于调整数量,addToCart方法实现加入购物车功能。
  • cart使用reactive实现响应式购物车数据。

2. 综合图表展示与用户交互
vue 复制代码
<!-- Dashboard.vue -->
<template>
  <el-container>
    <el-header>
      <el-menu :default-active="activeRoute" mode="horizontal">
        <el-menu-item index="1" @click="$router.push('/')">首页</el-menu-item>
        <el-menu-item index="2" @click="$router.push('/dashboard')">仪表盘</el-menu-item>
      </el-menu>
    </el-header>
    <el-main>
      <el-row :gutter="20">
        <el-col :span="12">
          <div ref="salesChartRef" style="width: 100%; height: 400px;"></div>
        </el-col>
        <el-col :span="12">
          <div ref="profitChartRef" style="width: 100%; height: 400px;"></div>
        </el-col>
      </el-row>
    </el-main>
  </el-container>
</template>

<script setup>
import * as echarts from 'echarts';
import { ref, onMounted } from 'vue';
import axios from 'axios';

const salesChartRef = ref(null);
const profitChartRef = ref(null);

const fetchSalesData = async () => {
  const response = await axios.get('/api/sales');
  return response.data;
}

const fetchProfitData = async () => {
  const response = await axios.get('/api/profit');
  return response.data;
}

onMounted(() => {
  const salesData = fetchSalesData();
  const profitData = fetchProfitData();
  const salesChart = echarts.init(salesChartRef.value);
  const profitChart = echarts.init(profitChartRef.value);
  salesChart.setOption({
    title: {
      text: '销售趋势'
    },
    tooltip: {},
    xAxis: {
      data: salesData.labels
    },
    yAxis: {},
    series: [{
      name: '销量',
      type: 'line',
      data: salesData.values
    }]
  });
  profitChart.setOption({
    title: {
      text: '利润趋势'
    },
    tooltip: {},
    xAxis: {
      data: profitData.labels
    },
    yAxis: {},
    series: [{
      name: '利润',
      type: 'bar',
      data: profitData.values
    }]
  });
})
</script>

注释

  • 使用el-rowel-col实现响应式布局。
  • echarts.init初始化两个图表,setOption设置图表配置。
  • fetchSalesDatafetchProfitData方法获取图表数据。

3. 综合登录与注册功能

vue 复制代码
<!-- Auth.vue -->
<template>
  <el-tabs v-model="activeTab">
    <el-tab-pane label="登录" name="login">
      <el-form :model="loginForm" :rules="loginRules" ref="loginFormRef" label-width="80px">
        <el-form-item label="用户名" prop="username">
          <el-input v-model="loginForm.username"></el-input>
        </el-form-item>
        <el-form-item label="密码" prop="password">
          <el-input type="password" v-model="loginForm.password"></el-input>
        </el-form-item>
        <el-form-item>
          <el-button type="primary" @click="onLogin">登录</el-button>
        </el-form-item>
      </el-form>
    </el-tab-pane>
    <el-tab-pane label="注册" name="register">
      <el-form :model="registerForm" :rules="registerRules" ref="registerFormRef" label-width="80px">
        <el-form-item label="用户名" prop="username">
          <el-input v-model="registerForm.username"></el-input>
        </el-form-item>
        <el-form-item label="密码" prop="password">
          `