mac电脑vue+node+nginx本地部署解决跨域问题

本文介绍如何通过配置Express服务器及Nginx来解决Vue项目的跨域问题,并演示了从创建Vue项目到部署运行的全过程。

使用vue-cli新建一个vue项目

弄个测试的页面调用接口 

打包好

使用http-serve将这个打包的vue项目在本地跑起来

使用http://192.168.43.100:8080能打开页面就没有问题了

没有处理的时候点击会出现跨域

 

然后新建一个文件夹server

使用终端cd到这个文件夹,安装cnpm install express

然后新建server.js,写出下面的代码

使用终端cd到server文件夹,使用node server.js命令跑下 

在网页上使用 http://localhost:3001/api/user可以看下下面的结果

安装nginx百度下就好了

进入到/usr/local/etc/nginx     找到nginx.conf文件并且编辑

 

 

然后终端进入到/usr/local/Cellar/nginx/1.19.2/bin

使用sudo nginx            开启nginx

使用http://192.168.43.100:8090/#/ceshi就可以访问到vue项目了

这个时候调用接口就不会出现跨域的问题了

 

 

<think>嗯,用户现在正在寻求一个关于使用VueNode.js和MySQL构建管理系统的解决方案或示例。用户已经给出了三条引用,但这些引用似乎主要涉及全栈开发教程和配置片段,而不是直接的解决方案。从用户的问题来看,用户可能是一位全栈开发者或学习者,正在尝试构建一个管理系统。用户明确表示想要示例代码或教程,这表明用户希望看到实际操作的具体指导。用户提到的三个引用中,引用[2]是一个配置webpack的代码片段,引用[1]和[3]是相关书籍的介绍,但用户提到这些引用仅供参考,需要多参考之前的对话。不过用户之前没有其他对话历史,所以需要基于当前的查询来回应。用户深层需求可能包括:希望得到一个分步指南,了解如何整合这三个技术,配置前后端环境,以及如何处理常见的功能如用户认证和CRUD操作。用户可能对架构设计、最佳实践和避免常见错误也有兴趣。接下来需要整理一个清晰的架构方案,包含三个主要部分:前端Vue、后端Node.js和MySQL数据库。同时,用户需要具体示例代码,比如如何建立数据库连接,如何创建API端点,以及如何在Vue中调用这些API。需要考虑提供用户可能遇到的实现细节,比如环境变量配置、路由管理、状态管理等。从系统指令来看,回复必须使用中文,并且需要生成相关问题。用户给出的示例中涉及系统级指令,比如正确使用LaTeX格式(虽然用户当前查询不涉及数学表达式,所以不需要使用LaTeX)。但是用户提到的引用中,引用[2]有一个关于根据环境配置webpack的代码,这个配置可以稍作修改并整合到Vue部分的开发模式中,以优化用户的构建流程。同时,在示例代码部分需要确保语法正确,尤其是在演示Node.js连接MySQL时,可能会用到mysql2或promise-mysql等库,以及使用express定义路由。在Vue部分,可能会使用axios处理HTTP请求,以及vue-router管理路由。还需要考虑如何在前后端之间传递数据,特别是在用户管理场景中如何实现CRUD操作。最后,为了帮助用户深入,相关问题应该围绕扩展功能、优化策略和常见问题解决,例如性能优化、安全性措施以及第三方服务整合。这些问题有助于用户了解构建管理系统后的后续步骤,而不仅仅是基础实现。安全方面需要注意在示例代码中避免硬编码敏感信息(如数据库密码),在config.js中通过环境变量配置,并建议使用dotenv管理这些变量。同时,在响应中要符合用户提到的"回答中引用的段落末尾自然地添加引用标识",需要将引用的书籍作为文献参考。</think> 好的,使用 Vue.js 作为前端框架,Node.js (通常配合 Express 框架) 作为后端 API 服务,MySQL 作为数据存储,构建管理系统是一个非常经典且流行的全栈方案。以下是实现这一方案的详细步骤和关键代码示例: **整体架构:** 1. **前端 (Vue.js):** 构建用户界面,处理用户交互,通过 AJAX (如 Axios) 向后端 API 请求数据或提交数据。 2. **后端 (Node.js + Express):** 提供 RESTful API 接口,处理业务逻辑,与 MySQL 数据库进行交互(增删改查 CRUD)。 3. **数据库 (MySQL):** 持久化存储管理系统的数据(如用户信息、产品信息、订单信息等)。 4. **通信:** 前端与后端通过 HTTP(S) 协议 (通常使用 JSON 格式数据) 进行通信。 **步骤与示例代码:** ### 第一步:环境准备与项目初始化 1. **安装 Node.js:** 确保你的系统已安装 Node.js (包含 npm)。 2. **创建项目目录:** 建议为整个项目创建一个根目录 (例如 `my-vue-node-mysql-admin`),并在其下创建两个子目录: * `client`: 用于存放 Vue.js 前端代码。 * `server`: 用于存放 Node.js + Express 后端代码。 3. **初始化前端 (Vue.js):** ```bash # 进入项目根目录 cd my-vue-node-mysql-admin # 初始化 Vue 项目 (Vue CLI) vue create client # 选择默认预设或手动配置 (推荐手动,确保包含 Vue Router 和 Vuex 选项) # 安装依赖 Axios cd client npm install axios ``` 4. **初始化后端 (Node.js + Express):** ```bash # 在项目根目录下创建并进入 server 目录 mkdir server && cd server # 初始化 Node.js 项目 npm init -y # 安装依赖 npm install express mysql2 body-parser cors dotenv # - express: Web 框架 # - mysql2: MySQL 数据库驱动 (支持 Promise API) # - body-parser: 解析 HTTP 请求体 (JSON, URL-encoded) # - cors: 处理请求 (方便开发时前后端分离) # - dotenv: 管理环境变量 (用于数据库配置等敏感信息) ``` ### 第二步:后端 (Node.js + Express) 开发 1. **创建入口文件 (`server/index.js`):** ```javascript require('dotenv').config(); // 加载 .env 文件中的环境变量 const express = require('express'); const bodyParser = require('body-parser'); const cors = require('cors'); const mysql = require('mysql2/promise'); // 使用 promise 版本 const app = express(); const port = process.env.PORT || 3000; // 从环境变量获取端口或默认 3000 // 应用中间件 app.use(cors()); // 允许 app.use(bodyParser.json()); // 解析 JSON 请求体 app.use(bodyParser.urlencoded({ extended: true })); // 解析 URL-encoded 请求体 // 创建数据库连接池 (提高性能) const pool = mysql.createPool({ host: process.env.DB_HOST || 'localhost', user: process.env.DB_USER || 'root', password: process.env.DB_PASSWORD || '', database: process.env.DB_NAME || 'my_admin_db', waitForConnections: true, connectionLimit: 10, queueLimit: 0 }); // 一个简单的路由测试 app.get('/', (req, res) => { res.send('Node.js + Express + MySQL API is running!'); }); // ---------- 实际业务 API 路由示例:用户管理 (CRUD) ---------- const router = express.Router(); // 获取所有用户 (GET /api/users) router.get('/users', async (req, res) => { try { const [rows] = await pool.query('SELECT * FROM users'); // 假设有 users 表 res.json(rows); } catch (error) { console.error('Error fetching users:', error); res.status(500).json({ message: 'Server error' }); } }); // 创建一个用户 (POST /api/users) router.post('/users', async (req, res) => { const { name, email, role } = req.body; // 假设请求体包含这些字段 if (!name || !email) { return res.status(400).json({ message: 'Name and email are required' }); } try { const [result] = await pool.query('INSERT INTO users (name, email, role) VALUES (?, ?, ?)', [name, email, role]); res.status(201).json({ id: result.insertId, name, email, role }); // 返回创建的用户信息(通常包含生成的 ID) } catch (error) { console.error('Error creating user:', error); res.status(500).json({ message: 'Server error creating user' }); } }); // 更新一个用户 (PUT /api/users/:id) router.put('/users/:id', async (req, res) => { const userId = req.params.id; const { name, email, role } = req.body; // 省略验证... try { const [result] = await pool.query('UPDATE users SET name=?, email=?, role=? WHERE id=?', [name, email, role, userId]); if (result.affectedRows === 0) { return res.status(404).json({ message: 'User not found' }); } res.json({ id: userId, name, email, role }); // 返回更新后的信息 } catch (error) { console.error('Error updating user:', error); res.status(500).json({ message: 'Server error updating user' }); } }); // 删除一个用户 (DELETE /api/users/:id) router.delete('/users/:id', async (req, res) => { const userId = req.params.id; try { const [result] = await pool.query('DELETE FROM users WHERE id = ?', [userId]); if (result.affectedRows === 0) { return res.status(404).json({ message: 'User not found' }); } res.json({ message: `User ${userId} deleted successfully` }); } catch (error) { console.error('Error deleting user:', error); res.status(500).json({ message: 'Server error deleting user' }); } }); // 将用户管理路由挂载到 /api 路径下 app.use('/api', router); // 这样前端访问 `/api/users` 等路径 // 启动服务器 app.listen(port, () => { console.log(`Server running on http://localhost:${port}`); }); ``` 2. **创建环境变量文件 (`.env`):** ```ini # .env (放在 server 目录下) PORT=5000 # 与前端端口区分开 DB_HOST=localhost DB_USER=your_db_username DB_PASSWORD=your_db_password DB_NAME=my_admin_db ``` * 请将 `your_db_username` 和 `your_db_password` 替换为你的 MySQL 凭据。 * 确保 MySQL 中已存在名为 `my_admin_db` 的数据库。 * 创建 `users` 表: ```sql CREATE DATABASE IF NOT EXISTS my_admin_db; USE my_admin_db; CREATE TABLE users ( id INT AUTO_INCREMENT PRIMARY KEY, name VARCHAR(100) NOT NULL, email VARCHAR(100) NOT NULL UNIQUE, role VARCHAR(50) DEFAULT 'user', created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP ); ``` 3. **运行后端:** ```bash cd server node index.js ``` 你应该看到 `Server running on http://localhost:5000` 的输出。访问 `http://localhost:5000/api/users` (GET) 应该返回一个空数组(或你预先插入的数据)。 ### 第三步:前端 (Vue.js) 开发 1. **配置代理 (避免开发):** 在 `client/vue.config.js` 中添加开发服务器代理配置: ```javascript // client/vue.config.js module.exports = { devServer: { proxy: { '/api': { // 以 /api 开头的请求 target: 'http://localhost:5000', // 代理到后端服务器地址 changeOrigin: true, pathRewrite: { '^/api': '' // 可选,去掉 /api 前缀(这样后端实际路径如 `/users`) } } } } }; ``` * 这使得前端开发时访问 `http://localhost:8080/api/users` 实际上会被代理到 `http://localhost:5000/api/users`。 2. **创建用户列表页面 (`client/src/views/UserList.vue`):** ```vue <template> <div> <h2>用户管理</h2> <button @click="openCreateUserModal">添加用户</button> <table> <thead> <tr> <th>ID</th> <th>姓名</th> <th>邮箱</th> <th>角色</th> <th>操作</th> </tr> </thead> <tbody> <tr v-for="user in users" :key="user.id"> <td>{{ user.id }}</td> <td>{{ user.name }}</td> <td>{{ user.email }}</td> <td>{{ user.role }}</td> <td> <button @click="editUser(user)">编辑</button> <button @click="deleteUser(user.id)">删除</button> </td> </tr> </tbody> </table> <!-- 用户创建/编辑模态框组件 (UserForm.vue) 需自行创建 --> <UserForm v-if="isModalOpen" :user="currentUser" :isEditing="isEditing" @save="handleSaveUser" @close="closeModal" /> </div> </template> <script> import axios from 'axios'; import UserForm from '@/components/UserForm.vue'; // 假设有组件 export default { components: { UserForm }, data() { return { users: [], currentUser: null, isModalOpen: false, isEditing: false }; }, mounted() { this.fetchUsers(); }, methods: { async fetchUsers() { try { const response = await axios.get('/api/users'); // 代理到后端 this.users = response.data; } catch (error) { console.error('获取用户列表失败:', error); alert('加载用户数据出错'); } }, openCreateUserModal() { this.currentUser = { name: '', email: '', role: 'user' }; this.isEditing = false; this.isModalOpen = true; }, editUser(user) { this.currentUser = { ...user }; this.isEditing = true; this.isModalOpen = true; }, async deleteUser(userId) { if (confirm('确定删除该用户吗?')) { try { await axios.delete(`/api/users/${userId}`); this.fetchUsers(); // 刷新列表 alert('删除成功'); } catch (error) { console.error('删除用户失败:', error); alert('删除失败'); } } }, async handleSaveUser(userData) { try { if (this.isEditing) { await axios.put(`/api/users/${userData.id}`, userData); alert('用户信息已更新'); } else { await axios.post('/api/users', userData); alert('用户创建成功'); } this.fetchUsers(); // 刷新列表 this.closeModal(); } catch (error) { console.error(this.isEditing ? '更新用户失败' : '创建用户失败', error); const errorMsg = error.response?.data?.message || '操作失败,请重试'; alert(errorMsg); } }, closeModal() { this.isModalOpen = false; this.currentUser = null; } } }; </script> ``` 3. **创建用户表单组件 (`client/src/components/UserForm.vue`):** ```vue <template> <div class="modal" v-if="isOpen"> <div class="modal-content"> <span class="close" @click="$emit('close')">×</span> <h2>{{ isEditing ? '编辑用户' : '创建新用户' }}</h2> <form @submit.prevent="$emit('save', formData)"> <div> <label>姓名:</label> <input type="text" v-model="formData.name" required> </div> <div> <label>邮箱:</label> <input type="email" v-model="formData.email" required> </div> <div> <label>角色:</label> <select v-model="formData.role"> <option value="admin">管理员</option> <option value="user">用户</option> <option value="editor">编辑</option> </select> </div> <button type="submit">{{ isEditing ? '更新' : '创建' }}</button> <button type="button" @click="$emit('close')">取消</button> </form> </div> </div> </template> <script> export default { props: { user: { // 当前要编辑的用户对象或空白对象 type: Object, required: true }, isEditing: { // 是否是编辑模式 type: Boolean, required: true }, isOpen: { // 模态框是否打开 type: Boolean, required: true } }, data() { return { formData: { ...this.user } // 创建副本用于表单绑定 }; }, watch: { user(newVal) { this.formData = { ...newVal }; // 当传入的user改变时更新表单数据 } } }; </script> <style scoped> /* 简单的模态框样式,根据需要进行扩展 */ .modal { position: fixed; top: 0; left: 0; width: 100%; height: 100%; background-color: rgba(0, 0, 0, 0.5); display: flex; justify-content: center; align-items: center; z-index: 1000; } .modal-content { background-color: white; padding: 20px; border-radius: 5px; min-width: 400px; } .close { float: right; font-size: 28px; font-weight: bold; cursor: pointer; } </style> ``` 4. **设置路由 (`client/src/router/index.js`):** ```javascript import Vue from 'vue'; import VueRouter from 'vue-router'; import UserList from '../views/UserList.vue'; Vue.use(VueRouter); const routes = [ { path: '/users', name: 'UserList', component: UserList }, // ...其他路由 ]; const router = new VueRouter({ mode: 'history', base: process.env.BASE_URL, routes }); export default router; ``` 在 `App.vue` 中添加 `<router-view/>`。 ### 第四步:运行项目 1. **启动后端:** ```bash cd path/to/server node index.js ``` 2. **启动前端:** ```bash cd path/to/client npm run serve ``` 3. **访问:** 访问前端开发服务器提供的地址 (通常是 `http://localhost:8080`),然后导航到 `/users` 路径 (`UserList` 组件) 即可看到用户管理功能界面,并通过表单进行用户管理的增删改查操作。 ### 扩展与关键点 * **身份认证 (JWT):** 管理系统通常需要登录验证。后端实现登录接口,使用类似 `jsonwebtoken` 库生成 JWT 令牌返回给前端。前端在后续请求的请求头(如 `Authorization: Bearer <token>`)中携带令牌。后端在需要认证的路由中使用中间件验证 JWT 的有效性。 * **状态管理 (Vuex):** 对于大型应用,建议使用 Vuex 来集中管理前端应用的状态(如用户登录状态、权限信息、全局加载状态等)。 * **权限控制:** 后端可以在路由处理函数中根据 JWT 包含的用户角色信息进行更细粒度的权限验证。前端可以根据用户角色显示/隐藏某些 UI 元素或控制路由访问 (使用 Vue Router 的导航守卫)。 * **安全性:** * **后端:** 使用环境变量管理敏感信息;对用户输入进行严格验证和转义;使用参数化查询防止 SQL 注入;对密码进行加盐哈希存储 (使用 `bcryptjs` 库)。 * **前端:** 进行基本的表单验证。 * **生产部署:** * **前端:** 使用 `npm run build` 打包生成静态文件 (`dist` 目录),可将此目录部署Nginx 或静态 Web 服务器。 * **后端:** 使用 `PM2` 等进程管理器运行 Node.js 服务以提高稳定性。配置数据库连接为生产环境配置。 * **配置:** 前端生产环境中通过配置 `config/index.js` 或使用环境变量指定真正的后端 API 基地址 (不再是 `localhost:5000`)。 **相关问题
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值