项目开发

本文详细介绍了基于前后端分离的项目开发架构,包括设置跨域、接口配置、数据库操作、用户注册登录等核心流程。同时,讲解了项目初始化步骤,如Vue脚手架的使用、Element-UI和axios库的配置,以及Git仓库的创建和管理。此外,还涵盖了项目开发流程、JSON数据使用、动态读取文件中的图片路径、Vue事件修饰符的应用等关键环节。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.项目开发架构

前后端分离

在服务端启动文件中加入跨域解决(2句)

const express=require('express');
//引入用户路由器
const userRouter=require('./router/user.js');
const ajaxRouter=require('./router/ajax.js');
const proRouter=require('./router/pro.js');
const cors=require("cors");
//引入body-parser中间件模块
const bodyParser=require('body-parser');
//console.log(userRouter);
//创建web服务器
const app=express();
//设置端口
app.listen(8080);
//只写一次,就可让整个服务端中所有接口都支持跨域
app.use(cors({origin:"http://127.0.0.1:5500"}))
//托管静态资源到public目录
app.use( express.static('./public') );
//应用body-parser中间件,将post请求的数据解析为对象
app.use( bodyParser.urlencoded({
  extended:false
}) );
//路由器最后
//挂载用户路由器,添加前缀/user   
app.use( '/user',userRouter );
app.use( '/ajax',ajaxRouter );
app.use( '/pro',proRouter );

将后端所给的接口文件拷贝到routes文件夹下,在启动文件中引入接口文件

const express=require('express');
//引入用户路由器
const details=require("./routes/details");
const cors=require("cors");
//引入body-parser中间件模块
const bodyParser=require('body-parser');
//console.log(userRouter);
//创建web服务器
const app=express();
//设置端口
app.listen(8080);
//只写一次,就可让整个服务端中所有接口都支持跨域
app.use(cors({origin:"http://127.0.0.1:5500"}))
//托管静态资源到public目录
app.use( express.static('./public') );
//应用body-parser中间件,将post请求的数据解析为对象
app.use( bodyParser.urlencoded({
  extended:false
}) );
//路由器最后
//挂载用户路由器,添加前缀/user   
app.use("/details",details);

前端淘宝详情页接口文件写法

//在js文件夹下新建details.js
//在details.html中<body>内的底部
//添加<script src="js/header.js">
//和<script src="js/details.js">
$(function(){
  if(location.search!==""){
    //获得地址栏中的?lid=2中的2
    var lid=location.search.split("=")[1]
    console.log(lid);
    //用lid作为参数向服务端发送请求
    $.ajax({
      url:"http://localhost:3000/details",
      //http://localhost:3000/user/login
      type:"get",
      data:{lid},//{lid:lid},//"lid="+lid
      //"uname=dingding&upwd=123456"
      //实际发送的url是:url+?+data
      //http://localhost:3000/datails?lid=5
      dataType:"json",//JSON.parse()
      success:function(result){
        //先将三大块数据解构出来
        var {product,specs,pics}=result;
        //1.填充右上角基本信息
        var {title,subtitle,price,promise}=product;
        $("#title").html(title);
        $("#subtitle").html(subtitle);
        $("#price").html(`¥${price.toFix(2)}`);
        $("#promise").html(promise);
        //2.填充右侧规格列表
        //先定义空html,等着接a的模板
        var html="";
        //遍历specs数组中每个规格对象
        for(var sp of specs){
          //每遍历一个规格对象,就多拼接一段a模板
          html+=`<a class="btn btn-sm btn-outline-secondary ${product.lid==sp.lid?'active':''}" href="product_details.html?lid=${sp.lid}">${sp.spec}</a>`
        }
        //将html整体填充回页面div中
        $("#specs").html(html);
        //3.放大镜效果
        //3.1填充图片
        //3.1.1填充小图片列表
        //先定义空的html,准备接多个模板片段
        var html="";
        //遍历pics数组中每张图片对象
        for(var p of pics){
          //就向html中追加一段li片段
          html+=`<li class="float-left p-1"><img src="${p.sm}" data-md="${p.md}" data-lg="${p.lg}"></li>`
        }
        //将整段html片段填充到ul-imgs中
        var $ulImgs=$("#ul-imgs");
        //定义变量保存每个li的宽度,反复使用
        var LIWIDTH=62;
        $ulImgs.html(html)
        //临时根据图片张数计算ul的宽:张数*图片宽
        .css("width",pics.length*LIWIDTH);
        //3.1.2填充1张中图片
        //设置mimg的src为pics中第一张图片的中图片版本
        var $mImg=$("#ming");
        var $lgDiv=$("#div-lg");
        $mImg.attr("src",pics[0].md)
        $lgDiv.css("background-image",`url(${pics[0].lg})`)
        //3.2点击箭头,移动小图片
        var $btnLeft=$("#btn-left");
        var $btnRight=$("#btn-right");
        if(pics.length<=4){
          $btnRight.addClass("disabled")
        }
        var times=0;//记录单击按钮的次数
        //每单击一次右边按钮,times+1,重新计算$ulImgs的marginLeft
        $btnRight.click(function(){
          if(!$btnRight.is(".disabled")){
            times++;
            $ulImgs.css(
              "margin-left",-times*LIWIDTH
            )
            $btnLeft.removeClass("disabled")
            if(times==pics.length-4){
              $btnRight.addClass("disabled")
            }
          }
        })
        //每单击一次左边按钮,times-1,重新计算$ulImgs的marginLeft
        $btnLeft.click(function(){
          if(!$btnLeft.is(".disabled")){
            times--;
            $ulImgs.css(
              "margin-left",-times*LIWIDTH
            )
            $btnRight.removeClass("disabled");
            if(times==0){
              $btnLeft.addClass("disabled")
            }
          }
        })
        //3.3鼠标进入小图片,切换中图片
        $ulImgs.on("mouseenter","li>img",function(){
          $mImg.attr("src",$(this).attr("data-md"));
          $lgDiv.css("background-image",`url(${$(this).attr("data-lg")})`)

        })
        //3.4鼠标进入中图片,显示遮罩层,并跟随鼠标移动
        var $mask=$("#mask");
        var $smask=$("#super-mask");
        var MSIZE=176;
        var SMSIZE=352;
        var $lgDiv=$("div-lg");
        $smask.hover(function(){
          $mask.toggleClass("d-none");
          $lgDiv.toggleClass("d-none");
        })
        .mousemove(function(e){
          var top=e.offsetY-MSIZE/2;
          var left=e.offsetX-MSIZE/2;
          if(top<0){
            top=0;
          }else if(top>SMSIZE-MSIZE){
            top=SMSIZE-MSIZE;
          }
          if(left<0){
            left=0;
          }else if(left>SMSIZE-MSIZE){
            left=SMSIZE-MSIZE;
          }
          $mask.css({
            top:top+"px",
            left:left+"px"
          })
          $lgDiv.css("background-position",`${-left*16/7}px ${-top*16/7}px`)
        })
        //3.5鼠标进入中图片,显示大图片 
      }
    })
  }
})

项目结构

项目结构
项目运行
node_modules/第三方的包
public/静态的HTML,css,js,图片
routes/处理各种请求的路由接口模块
app.js node.js express框架主程序
pool.js/专门链接数据库的模块
1.打开xampp,点击config进入启动apache和mysql,点击mysql一行中的Admin确保localhost/phpmyadmin管理网站中有完整的项目数据库;
2.先打开一个vscode,打开后台项目文件夹,右键点击app.js选择在终端|命令行|command…中打开,在终端中输入:node app.js;结果:服务端启动了;
3.再打开一个vscode,打开public项目文件夹,确保public文件夹中有img文件夹,右键单击index.html,选择用Live server打开;
4.结果首页一楼中应该显示6个商品
如果出现:::8080错误,说明端口占用,关闭vs code重启,再运行node app.js

项目链接

连接运行:1.服务器文件中需要引入路由器并使用路由器(访问方式变成服务器中使用路由器的url+路
由器中的路由“127.0.0.1:8080/user/reg”)
2.服务器文件得启动才可以运行(终端拉入文件启动)
3.mysql同样需要开启

路由器router:1.引入express模块,连接池文件
2.创建路由器对象
3.添加路由并运用mysql语法操作数据或者js操作判断
4.导出路由器对象
文件:ajax.js
const express=require(‘express’);
//引入连接池模块
const pool=require(’…/pool.js’);
//创建路由器对象
const r=express.Router();
//1.ajax测试接口
//url:127.0.0.1:8080/ajax/test
//浏览器的地址栏只能验证get方法
r.get("/test",(req,res)=>{
var _uname=req.query.uname;
var _upwd=req.query.upwd;
console.log(_uname,_upwd);
res.send(“第一个ajax操作接口”);
});

//2.练习
r.get("/ajax2",(req,res)=>{
var _uname=req.query.uname;
var _upwd=req.query.upwd;
res.send(“您的用户名为”+_uname+",您的密码为"+_upwd);
});
//3.原生http-get方法登录
r.get("/http_get_login",(req,res)=>{
var _uname=req.query.uname;
var _upwd=req.query.upwd;
var sql=“select * from xz_user where uname=? and upwd=?”;
pool.query(sql,[_uname,_upwd],(err,result)=>{
if(err) throw err;
if(result.length>0){
res.send(“1”);
}else{
res.send(“0”);
}
});
});
//4.获取所有用户信息
r.get("/http_list",(req,res)=>{
var sql=“select * from xz_user”;
pool.query(sql,(err,result)=>{
if(err) throw err;
res.send(result);
});
});
//5.原生get请求登录 /ajax/home_http_get_login
//127.0.0.1:8080/ajax/home_http_get_login?uname=…&upwd=…
r.get("/home_http_get_login",(req,res)=>{
var _uname=req.query.uname;
var _upwd=req.query.upwd;
var sql=“select * from xz_user where uname=? and upwd=?”;
pool.query(sql,[_uname,_upwd],(err,result)=>{
if(err) throw err;
if(result.length>0){
res.send(“1”);
}else{
res.send(“0”);
}
});
});
//6.restful规则的get接口
//127.0.0.1:8080/ajajx/rest_login/dangdang&123456
//接口定义的时候有冒号,使用接口传参数不写冒号
//xhr.open(“get”,/ajax/rest_login/${_uname}&${_upwd});
r.get("/rest_login/:uname-:upwd",(req,res)=>{
var _uname=req.params.uname;
var _upwd=req.params.upwd;
console.log(_uname,_upwd);
var sql=“select * from xz_user where uname=? and upwd=?”;
pool.query(sql,[_uname,_upwd],(err,result)=>{
if(err) throw err;
if(result.length>0){
res.send(“1”);
}else{
res.send(“0”);
}
});
});
//7.restful的del
r.delete("/restful_del/:uid",(req,res)=>{
var _uid=req.params.uid;
var sql=“delete from xz_user where uid=?”;
pool.query(sql,[_uid],(err,result)=>{
if(err) throw err;
if(result.affectedRows>0){
res.send(“1”);
}else{
res.send(“0”);
}
});
});
//8.查询所有信息 restful—>get,没有传参
r.get("/restful_list",(req,res)=>{
var sql=“select * from xz_user”;
pool.query(sql,(err,result)=>{
if(err) throw err;
res.send(result);
});
});
//9.post登录
r.put("/v1/post_login",(req,res)=>{
var _uname=req.body.uname;
var _upwd=req.body.upwd;
res.send(_uname+"…"+_upwd);
//数据库操作
});
//导出路由器对象
module.exports=r;
文件:pro.js
const express=require(‘express’);
//引入连接池模块
const pool=require(’…/pool.js’);
//创建路由器对象
const r=express.Router();
//1.登录
r.get("/v1/login/:uname&:upwd",(req,res)=>{
var _uname=req.params.uname;
var _upwd=req.params.upwd;
var sql=“select * from xz_user where uname=? and upwd =?”;
pool.query(sql,[_uname,_upwd],(err,result)=>{
if(err) throw err;
if(result.length>0){
res.send(“1”);
}else{
res.send(“0”);
}
});
});
//2.获取用户列表
r.get("/v1/list",(req,res)=>{
var sql=“select * from xz_user”;
pool.query(sql,(err,result)=>{
if(err) throw err;
res.send(result);
});
});
//3.根据uid删除
r.delete("/v1/del/:uid",(req,res)=>{
var _uid=req.params.uid;
var sql=“delete from xz_user where uid=?”;
pool.query(sql,[_uid],(err,result)=>{
if(err) throw err;
if(result.affectedRows>0){
res.send(“1”);
}else{
res.send(“0”);
}
});
});
//4.根据uid查询用户
r.get("/v1/search/:uid",(req,res)=>{
var _uid=req.params.uid;
var sql=“select * from xz_user where uid=?”;
pool.query(sql,[_uid],(err,result)=>{
if(err) throw err;
res.send(result);
});
});
//5.用户名冲突的验证
r.get("/v1/sel/:uname",(req,res)=>{
var _uname=req.params.uname;
var sql=“select * from xz_user where uname=?”;
pool.query(sql,[_uname],(err,result)=>{
if(err) throw err;
if(result.length>0){
res.send(“1”);
}else{
res.send(“0”);
}
});
});
//6.根据uid修改用户信息
r.put("/v1/update",(req,res)=>{
var obj=req.body;
var sql=“UPDATE xz_user SET ? WHERE uid=?”;
pool.query(sql,[obj,obj.uid],(err,result)=>{
if(err) throw err;
if(result.affectedRows>0){
res.send(“1”);
}else{
res.send(“0”);
}
});
});
//导出路由器对象
module.exports=r;
文件:user.js
const express=require(‘express’);
//引入连接池模块
const pool=require(’…/pool.js’);
//console.log(pool);
//创建路由器对象
const r=express.Router();
//1.用户注册 post /reg
r.post(’/reg’,(req,res)=>{
//1.1获取post请求的数据
let obj=req.body;
console.log(obj);
//1.2检测各项数据是否为空
if(!obj.uname){
res.send({code:401,msg:‘uname required’});
//阻止往后执行
return;
}
if(!obj.upwd){
res.send({code:402,msg:‘upwd required’});
return;
}
if(!obj.email){
res.send({code:403,msg:‘email required’});
return;
}
if(!obj.phone){
res.send({code:404,msg:‘phone required’});
return;
}
//1.3将数据插入到数据表xz_user中
//执行SQL命令
pool.query(‘INSERT INTO xz_user SET ?’,[obj],(err,result)=>{
if(err) throw err;
console.log(result);
res.send({code:200,msg:‘reg suc’});
});
});
//2.用户登录 post /login
r.post(’/login’,(req,res)=>{
//2.1获取post请求的数据
let obj=req.body;
console.log(obj);
//2.2检测各项数据是否为空
if(!obj.uname){
res.send({code:401,msg:‘uname required’});
return;
}
if(!obj.upwd){
res.send({code:402,msg:‘upwd required’});
return;
}
//3.执行SQL命令,查询数据库中是否有用户名和密码同时匹配的数据
pool.query(‘SELECT * FROM xz_user WHERE uname=? AND upwd=?’,[obj.uname,obj.upwd],(err,result)=>{
if(err) throw err;
//结果为数组
console.log(result);
//如果是空数组,则说明登录失败,否则说明登录成功
if(result.length=0){
res.send({code:301,msg:‘login err’});
}else{
res.send({code:200,msg:‘login suc’});
}
});
});
//3.修改用户 post /update
r.post(’/update’,(req,res)=>{
//3.1获取post请求的数据
let obj=req.body;
console.log(obj);
//3.2检测各项数据是否为空
//遍历对象obj,得到每个属性值
//声明变量记录状态码
let i=400;
for(let k in obj){
//每次循环,状态码加1
i++;
//k代表属性名,obj[k]对应的属性值
//console.log(k,obj[k]);
//判断属性值是否为空,提示属性名这项是必须的
if(!obj[k]){
res.send({code:i,msg:k+’ required’});
return;
}
}
//3.3执行SQL命令,修改用户的数据
pool.query(‘UPDATE xz_user SET ? WHERE uid=?’,[obj,obj.uid],(err,result)=>{
if(err) throw err;
//结果是一个对象
console.log(result);
//如果对象下的affectedRows为0,则修改失败,否则修改成功
if(result.affectedRows
=0){
res.send({code:301,msg:‘update err’});
}else{
res.send({code:200,msg:‘update suc’});
}
});
});
//4.用户列表 get /list
r.get(’/list’,(req,res)=>{
//4.1获取查询字符串传递的数据
let obj=req.query;
console.log(obj);
//4.2检测各项数据是否为空
//如果每页大小为空设置默认显示5条数据
if(!obj.size) obj.size=5;
//如果当前页码为空设置默认显示第1页
if(!obj.pno) obj.pno=1;
console.log(obj);
//4.3计算开始查询的值
let start=(obj.pno-1)*obj.size;
//4.4将每页的大小转为整型
let count=parseInt(obj.size);
//执行SQL命令,查询数据
pool.query(‘SELECT * FROM xz_user LIMIT ?,?’,[start,count],(err,result)=>{
if(err) throw err;
//结果是数组
console.log(result);
//把数组直接响应给浏览器端
res.send(result);
});
});
//导出路由器对象
module.exports=r;

静态资源piblic:

用户注册

用户
密码
邮箱
电话

web创建(js文件):1.引入express模块,引入路由器文件,引入body-parser中间件
2.创建web服务器
3.托管静态资源到public目录
4.应用body-parwer中间件,将post请求数据解析为对象
5.挂载路由器
const express=require(‘express’);
//引入用户路由器
const userRouter=require(’./router/user.js’);
const ajaxRouter=require(’./router/ajax.js’);
const proRouter=require(’./router/pro.js’);
const cors=require(“cors”);
//引入body-parser中间件模块
const bodyParser=require(‘body-parser’);
//console.log(userRouter);
//创建web服务器
const app=express();
//设置端口
app.listen(8080);
//只写一次,就可让整个服务端中所有接口都支持跨域
app.use(cors({origin:“http://127.0.0.1:5500”}))
//托管静态资源到public目录
app.use( express.static(’./public’) );
//应用body-parser中间件,将post请求的数据解析为对象
app.use( bodyParser.urlencoded({
extended:false
}) );
//路由器最后
//挂载用户路由器,添加前缀/user
app.use( ‘/user’,userRouter );
app.use( ‘/ajax’,ajaxRouter );
app.use( ‘/pro’,proRouter );

创建连接池(js文件):1.引入mysql模块
2.创建连接池对象
3.导出连接池对象
const mysql=require(‘mysql’);
//创建连接池对象
const pool=mysql.createPool({
host:‘127.0.0.1’,
port:‘3306’,
user:‘root’,
password:’’,
database:‘xz’,
connectionLimit:‘15’
});
//导出连接池对象
module.exports=pool;

2.项目初始化

1.创建项目文件夹步骤
(1)安装Vue脚手架
先安装一个能创建脚手架项目的命令行工具:看到 + @vue/cli@4.5.9 说明安装成功
npm i -g @vue/cli

(2)通过Vue脚手架创建项目
(3)配置Vue路由
1)在要创建项目的目录,地址栏中: cmd 回车
2)在弹出的命令行窗口中输入: vue create 新项目名 回车
vue create 项目文件夹名

3)用淘宝镜像网址更快安装:输入 y 回车
Your connection to the default npm registry seems to be slow.Use https://registry.npm.taobao.org for faster installation? (Y/n)Y
4)选择功能:上下键选择Manually select features 回车
? Please pick a preset: (Use arrow keys)
Default ([Vue 2] babel, eslint)
Default (Vue 3 Preview) ([Vue 3] babel, eslint)

Manually select features
5)勾选你需要的功能:点击空格键选中,选好以后 回车
Babel:必选,脚手架中用了很多ES6甚至ES7的新语法,大多数浏览器不支持。所以不要
Babel将新的语法编译为ES5的语法,让大多数浏览器都能支持。
TypeScript:不选,微软出的严格的script。
Router:必选,单页面应用的核心组件
Vuex:Vue中的状态机制,当多个组件需要共用一些数据:比如当前登录用的用户名。这个
公共的数据就要放在Vuex中
Linter/Formatter:千万不要选,代码质量检查工具,即使代码没错,格式不规范,也报错
? Check the features needed for your project:(Press to select, to toggle all, to invert selection)
() Choose Vue version
(
) Babel
( ) TypeScript
( ) Progressive Web App (PWA) Support
() Router
(
) Vuex
( ) CSS Pre-processors
( ) Linter / Formatter
( ) Unit Testing
( ) E2E Testing
6)vue版本选择:上下键选择2.x 回车
7)是否使用history模式作为路由器的导航方式:输入 y 回车
必须要服务端支持。如果不选,默认Vue的地址栏中都是用#/路径来跳转,但是#可能和你
的锚点地址冲突。如果既想用vue,又想要锚点地址,只能启动history模式,启用后地址栏
中就没有#了,而是直接用"/路径"
? Use history mode for router?(Requires proper server setup for index fallback in production) (Y/n) n
8)上下键选择ESLint + Standard config 回车
9)选择 Lint on save 回车
10)将各项配置信息放在一个package.json文件中,还是分别放在不同的配置文件中:
上下键选择In package.json 回车
? Where do you prefer placing config for Babel, ESLint, etc.? (Use arrowkeys)
In dedicated config files
In package.json 放在一个package.json文件中
11)是否将当前选择作为将来项目的默认配置:输入 n 回车
看到 Successfully created project 新项目名 说明脚手架项目创建完成
? Save this as a preset for future projects? (y/N) N

2.配置插件和依赖
(1)配置Element-UI组件库
1)安装:在脚手架当前目录下 命令行npm i element-ui -S
验证:node_modules/mint-ui/lib 所有组件 或 package.json
2)启动脚手架指令:npm run serve 其中serve可以配置package.json
3)配置element组件库:在main.js中引入其它库并且配置库
import ElementUI from ‘element-ui’
import ‘element-ui/lib/theme-chalk/index.css’

Vue.use(ElementUI)
(2)配置axios库
1)安装:在脚手架当前目录下 命令行npm install axios -s
2)配置axios库:在main.js中引入并且配置库
import axios from ‘axios’
//配置请求的根路径
axios.defaults.baseURL=‘http://接口文档中地址’
Vue.prototype.$http=axios

3.git
(1)初始化git远程仓库
https://gitee.com/
添加SSH公钥操作文档: SSH公钥 -> 怎样生成公钥 -> 仓库管理 -> 生成/添加SSH公钥
(2)将本地项目托管到Github或码云中

git操作指令:
git checkout -b 分支名称 创建子分支进行开发

git add . 暂存到本地
git status 查看此时代码状态
git commit -m “提交信息” 暂存本地仓库上

git branch 查看当前项目所有分支,*为当前所在分支
git checkout 分支名 切换分支,合并到哪个分支就切换到哪个分支
git merge 需要被合并的分支名 合并分支
git push 推送到git中
git push -u origin 分支名 第一次推送git上

4.后台项目的环境安装配置
(1)安装MySQL数据库

(2)安装Node.js环境:官网下载安装,再在后台文件夹中打开终端输入 node app.js 启动数据库
(3)配置项目相关信息
(4)启动项目:npm run serve
(5)使用Postman测试后台项目接口是否正常

3.项目开发流程

1.创建组件流程:
1)创建空组件
src/components/Exam01.vue

第一个组件,唯一根元素div

2)为空组件指定路径
src/router.js中 path:’/Exam01’
//router.js 引入路由
import Vue from ‘vue’
import Router from ‘vue-router’
//自定义组件
//1.引入组件
import HelloContainer from ‘./components/HelloWorld.vue’
import Exam01 from “./components/Exam01.vue”
Vue.use(Router)
//2.为组件配置路径
export default new Router({
routes:[
{path:’/’, component:HelloContainer},
{path:’/Exam01’, component:Exam01},
]
})
3)运行组件:在浏览器地址栏中输入空组件地址回车
http://127.0.0.1:8080/#/Exam01
4)添加内容再运行
https://mint-ui.github.io/#!/zh-cn

2.字体图标:https://www.iconfont.cn/
1)下载图片
点击图片加入购物车
点击购物车->点击[下载代码]按钮
文件download.zip #ttf 图标字体文件
2)将图标应用当前项目
在src目录下创建新目录font保存所有图标字体文件
main.js引入字体图标css文件,import “./font/iconfont.css”
在组件中Exam01.vue 使用图标,this.$toast({ iconClass:“iconfont 图标名称” });
3)字体图标可以修改大小
.iconfont{ font-family:“iconfont” !important; font-size:16px; }

3.父子组件传参
子组件S09.vue
父组件F10.vue

{{msg}}

父组件F10.vue

父组件

4.json文件(数据)的使用
(1)引入到当前项目
import 数据名 from “文件路径”
data(){ return { list:数据名 }}
(2)使用
<元素 v-for="(item,i) of list.json文件中数组名" :key=“i”
:需要的数据=“item.该数据在json文件中名”
:需要的数据=“item.该数据在json文件中名”></元素>

5.如何动态读取文件中图片路径
图片路径一定是在服务器端 示例:http://127.0.0.1:3000/1.jpg
本地图片路径报错

6.vue事件修饰符:native原生事件
如果自定义属性直接使用事件绑定即可,如果调用组件库中的组件直接绑定失败情况,添加修饰符
native 启动原生事件绑定

4.项目关联文件

全局样式:assets/css/global.css
/* 全局样式表 */
html,
body,
#app{
height: 100%;
margin: 0;
padding: 0;
}

.el-breadcrumb{
margin-bottom: 15px;
font-size: 12px;
}

.el-card{
box-shadow: 0 1px 1px rgba(0, 0, 0, 0.15) !important;
}

.el-table{
margin-top: 15px;
font-size: 12px;
}

.el-pagination{
margin-top: 15px;
}
根组件App.vue

main.js——引入插件,全局样式,图标文件
import Vue from ‘vue’
import App from ‘./App.vue’
import router from ‘./router’
import store from ‘./store’
import ElementUI from ‘element-ui’
import ‘element-ui/lib/theme-chalk/index.css’
// 导入全局样式表
import ‘./assets/css/global.css’
//引入接口
import axios from ‘axios’
//配置请求的根路径
axios.defaults.baseURL=‘http://127.0.0.1:8888/api/private/v1/’
// 请求拦截,设置权限
axios.interceptors.request.use(config=>{
console.log(config)
config.headers.Authorization=window.sessionStorage.getItem(‘token’)
// 在最后必须return config
return config
})
Vue.prototype.$http=axios

Vue.use(ElementUI)

Vue.config.productionTip = false

new Vue({
router,
store,
render: h => h(App)
}).$mount(’#app’)
路由文件——引入组件,并配置
import Vue from ‘vue’
import VueRouter from ‘vue-router’
import Login from ‘…/components/Login.vue’
import Home from ‘…/components/Home.vue’
import Welcome from ‘…/components/Welcome.vue’
import Users from ‘…/components/user/Users.vue’

Vue.use(VueRouter)

const routes = [
{ path: ‘/’, redirect: ‘/login’ },
{ path: ‘/login’, component: Login },
{
path: ‘/home’,
component: Home,
redirect:’/welcome’,
children: [
{ path: ‘/Welcome’, component: Welcome },
{ path: ‘/users’, component: Users }
]
}
]

const router = new VueRouter({
mode: ‘history’,
base: process.env.BASE_URL,
routes
})

//挂载路由导航守卫控制访问权限
router.beforeEach((to, from, next) => {
//to 将要访问的路径
//from 代表从哪个路径跳转而来
//next 是一个函数,表示放行
//next() 放行 next(’/login’) 强制跳转
if (to.path === ‘/login’) return next()
//获取token
const tokenStr = window.sessionStorage.getItem(‘token’)
if (!tokenStr) return next(’/login’)
next()
})

export default router

5.登录退出

1.登录概述
(1)登录业务流程
1)在登录页面输入用户名和密码
2)调用后台接口进行验证
3)通过验证之后,根据后台的响应状态跳转到项目主页
(2)登录业务的相关技术点
1)http是无状态
2)通过cookie在客户端记录状态:不存在跨域问题时使用
3)通过session在服务端记录状态:不存在跨域问题时使用
4)通过token方式维持状态:存在跨域问题时使用

2.token原理分析

3.登录功能实现
通过Element-UI组件实现布局 el-form el-form-item el-input el-button 字体图标
vscode中项目文件终端打开,确保 git status 干净;
git checkout -b 分支名称 创建子分支进行开发
git branch 查看当前项目所有分支

4.知识点
ref=" " 表单的引用对象

5.路由导航守卫控制访问权限
如果用户没有登录,但是直接通过URL访问特定页面,需要重新导航到登录页面
路由文件中写:
//为路由对象添加beforeEach导航守卫
router.beforeEach((to,from,next)=>{
//to 将要访问的路径
//from 代表从哪个路径跳转而来
//next 是一个函数,表示放行
//next() 放行 next(’/login’) 强制跳转
//如果用户访问的是登录页,直接放行
if(to.path===’/login’) return next()
//从sessionStorage中获取到保存的token值
const tokenStr=window.sessionStorage.getItem(‘token’)
//没有token,强制跳转到登录页
if(!tokenStr) return next(’/login’)
next()
})

6.退出功能实现原理
基于token的方式实现退出比较简单,只需要销毁本地的token即可,这样后续的请求就不会携带
token,必须重新登录生成一个新的token之后才可以访问页面。
<el-button type=“info” @click=“logout”>退出

methods:{
logout(){
//清空token
window.sessionStorage.clear();
//跳转到登录页
this.$router.push(’/login’);
}
}

7.严谨模式下配置文件解决不是问题的报错
根目录文件下创建文件 .prettierrc
{ “semi”: false, “singleQuote”: true }
在 .eslintrc.js 文件中找到 rules:{ } 在其中写上
‘space-before-function-paren’: 0

6.导航布局

1.整体布局:先上下划分,再左右划分。Container布局容器
2.通过接口获取菜单数据:通过axios请求拦截器添加token,保证拥有获取数据的权限
//axios请求拦截
axios.interceptors.request.use(config=>{
//为请求头对象,添加Token验证的Authorization字段
config.headers.Authorization=window.sessionStorage.getItem(‘token’)
// 在最后必须return config
return config
})

电商后台管理系统

7.列表页

首页 用户管理 用户列表 添加用户
  <!-- 列表区域 -->
  <el-table :data="userlist" border stripe>
    <el-table-column type="index" width="90"></el-table-column>
    <el-table-column prop="username" label="姓名"></el-table-column>
    <el-table-column prop="email" label="邮箱"> </el-table-column>
    <el-table-column prop="mobile" label="电话"> </el-table-column>
    <el-table-column prop="role_name" label="角色"> </el-table-column>
    <el-table-column label="状态">
      <template slot-scope="scope">
        <el-switch v-model="scope.row.mg_state" @change="userStateChanged(scope.row)"></el-switch>
      </template>
    </el-table-column>
    <el-table-column label="操作">
      <template slot-scope="scope">
        <!-- 修改按钮 -->
        <el-button
          type="primary"
          icon="el-icon-edit"
          size="mini"
          @click="handleEdit(scope.$index)"
        ></el-button>
        <!-- 删除按钮 -->
        <el-button
          type="danger"
          icon="el-icon-delete"
          size="mini"
          @click="handleDelete(scope.$index)"
        ></el-button>
        <!-- 分配角色按钮 -->
        <el-tooltip
          class="item"
          effect="dark"
          content="分配角色"
          placement="top"
          :enterable="false"
        >
          <el-button
            type="warning"
            icon="el-icon-setting"
            size="mini"
            @click="handleEdit(scope.$index)"
          ></el-button>
        </el-tooltip>
      </template>
    </el-table-column>
  </el-table>

  <!-- 页码区域 -->
  <el-pagination
    @size-change="handleSizeChange"
    @current-change="handleCurrentChange"
    :current-page="queryInfo.pagenum"
    :page-sizes="[1,2, 5,10]"
    :page-size="queryInfo.pagesize"
    layout="total, sizes, prev, pager, next, jumper"
    :total="total"
  >
  </el-pagination>
</el-card>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值