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>
语法糖,可以更简洁地编写组件逻辑。
案例代码:
<!-- 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
触发事件进行通信。
案例代码:
<!-- 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)的导航。
案例代码:
// 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;
<!-- 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>
注释:
createRouter
和createWebHistory
用于创建路由实例。router-view
用于渲染匹配的组件。activeRoute
通过useRoute
和useRouter
获取当前路由状态。
二、Element Plus组件实战
1. 表单处理
案例代码:
<!-- 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. 表格组件
案例代码:
<!-- 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. 基础图表
案例代码:
<!-- 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
设置图表配置。xAxis
和yAxis
定义坐标轴,series
定义数据系列。
2. 动态图表更新
案例代码:
<!-- 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. 购物车功能实现
案例代码:
<!-- 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. 登录与注册功能实现
案例代码:
<!-- 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-form
和el-form-item
构建登录表单,el-input
用于输入。 rules
定义表单验证规则,validate
方法进行验证。ElMessage
用于提示用户操作结果。
3. AIGC辅助优化代码
案例代码:
// 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. 综合商品展示与购物车功能
<!-- 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. 综合图表展示与用户交互
<!-- 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-row
和el-col
实现响应式布局。 echarts.init
初始化两个图表,setOption
设置图表配置。fetchSalesData
和fetchProfitData
方法获取图表数据。
3. 综合登录与注册功能
<!-- 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">`