模拟瑞幸小程序购物车
是根据渡一袁老师的大师课写的,如有什么地方存在问题,还请大家指出来哟ど⁰̷̴͈꒨⁰̷̴͈う♡~
index.html
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8" /><meta http-equiv="X-UA-Compatible" content="IE=edge" /><meta name="viewport" content="width=device-width, initial-scale=1.0" /><title>亚亚外卖</title><link rel="shortcut icon" href="./assets/favicon.ico" type="image/x-icon" /><link rel="stylesheet" href="./css/common.css" /><link rel="stylesheet" href="./css/container.css" /><link rel="stylesheet" href="./css/footer.css" /><link rel="stylesheet" href="./css/add-to-car.css" /></head><body><div class="container"><div class="menu"><div class="menu-item active"><span>推荐</span></div><div class="menu-item"><span>热销</span></div><div class="menu-item"><span>折扣</span></div><div class="menu-item"><span>夏日冰咖必喝榜</span></div><div class="menu-item"><span>进店必喝</span></div><div class="menu-item"><span>只喝美式</span></div><div class="menu-item"><span>酷爽特调水果冰萃</span></div><div class="menu-item"><span>经典奶咖</span></div><div class="menu-item"><span>创意奶咖</span></div><div class="menu-item"><span>瑞纳冰季</span></div><div class="menu-item"><span>不喝咖啡</span></div><div class="menu-item"><span>轻食甜品</span></div><div class="menu-item"><span>热卖套餐</span></div></div><div class="goods-list"></div></div><div class="footer"><div class="footer-car-container"><div class="footer-car"><i class="iconfont i-gouwuchefill"></i><span class="footer-car-badge">0</span></div><div class="footer-car-price"><span class="footer-car-unit">¥</span><span class="footer-car-total">0.00</span></div><div class="footer-car-tip">配送费¥0</div></div><div class="footer-pay"><a href="">去结算</a><span>还差¥0元起送</span></div></div><!-- <div class="add-to-car"><i class="iconfont i-jiajianzujianjiahao"></i></div> --><script src="./js/data.js"></script><script src="./js/index.js"></script></body>
</html>
common.css
@import url('https://at.alicdn.com/t/c/font_3555577_me2a6tdmvu8.css');*,
*::before,
*::after {margin: 0;padding: 0;box-sizing: border-box;
}html {font-size: 0.125vw;
}
body {font-size: 35rem;-webkit-tap-highlight-color: transparent;-webkit-font-smoothing: antialiased;user-select: none;font-family: 'Microsoft Yahei', 'sans-serif';
}
a {color: inherit;text-decoration: none;
}
.iconfont {font-size: inherit;
}
container.css
.container {position: fixed;left: 0;top: 0;width: 100%;height: calc(100% - 100rem);display: flex;color: #333;
}
.menu {background: #f5f5f5;width: 190rem;overflow-y: scroll;padding-bottom: 50rem;flex: 0 0 auto;
}
.menu::-webkit-scrollbar {width: 0;
}.menu-item {height: 141rem;display: flex;justify-content: center;align-items: center;padding: 0 30rem;position: relative;
}
.menu-item span {font-size: 30rem;line-height: 40rem;max-height: 80rem;overflow: hidden;
}
.menu-item.active {font-weight: bold;background: #fff;
}
.menu-item.active::before {content: '';position: absolute;left: 0;height: 100%;width: 7.5rem;background: #3190e8;
}.goods-list {flex-grow: 1;overflow-y: scroll;
}
.goods-list::-webkit-scrollbar {width: 0;
}.goods-item {border-bottom: 1rem solid #f8f8f8;padding: 30rem 20rem;display: flex;
}
.goods-pic {width: 200rem;height: 200rem;object-fit: contain;border: 1rem solid rgba(0, 0, 0, 0.06);flex: 0 0 auto;
}
.goods-info {flex: 1 1 auto;padding: 0 35rem;overflow: hidden;
}
.goods-title {font-size: 35rem;overflow: hidden;text-overflow: ellipsis;white-space: nowrap;margin-bottom: 20rem;
}
.goods-desc {font-size: 24rem;white-space: nowrap;overflow: hidden;text-overflow: ellipsis;margin-bottom: 20rem;
}
.goods-sell {color: #858687;font-size: 24rem;white-space: nowrap;overflow: hidden;text-overflow: ellipsis;margin-bottom: 20rem;display: flex;
}
.goods-sell span:first-child {margin-right: 18rem;
}
.goods-confirm {display: flex;justify-content: space-between;
}
.goods-price {display: flex;font-size: 35rem;font-weight: bold;color: #f60;align-items: flex-end;
}
.goods-price-unit {font-size: 25rem;margin-bottom: 4rem;font-weight: normal;
}
.goods-btns {display: flex;justify-content: center;align-items: center;
}
.goods-btns .iconfont {width: 40rem;height: 40rem;background: #4a90e1;color: #fff;border-radius: 50%;font-size: 23rem;line-height: 40rem;text-align: center;
}
.goods-btns span {margin: 0 15rem;display: none;
}
.goods-btns .i-jianhao {border: 1rem solid #4a90e1;background: #fff;color: #4a90e1;font-weight: bold;display: none;
}
.goods-item.active span {display: block;
}
.goods-item.active .i-jianhao {display: block;
}
footer.css
.footer {height: 100rem;color: #fff;position: fixed;left: 0;bottom: 0;width: 100%;display: flex;z-index: 10;
}.footer-car-container {flex-grow: 1;background: #3d3d3f;padding-left: 175rem;position: relative;
}
.footer-car {position: absolute;width: 118rem;height: 118rem;border: 9rem solid #444;left: 25rem;top: -35rem;border-radius: 50%;background: inherit;display: flex;justify-content: center;align-items: center;font-size: 60rem;
}
.footer-car-badge {position: absolute;width: 35rem;height: 35rem;background: #ec5533;font-size: 25rem;text-align: center;border-radius: 50%;line-height: 35rem;right: 0;top: 0;display: none;
}
.footer-car.active {background: #4a90e1;
}
.footer-car.active .footer-car-badge {display: block;
}
.footer-car.animate {animation: footer-car-animate 500ms ease-in-out;
}@keyframes footer-car-animate {0% {transform: scale(1);}25% {transform: scale(0.8);}50% {transform: scale(1.1);}75% {transform: scale(0.9);}100% {transform: scale(1);}
}.footer-car-price {font-size: 40rem;display: flex;margin-top: 5rem;
}
.footer-car-tip {font-size: 20rem;margin-left: 6rem;
}
.footer-pay {background: #535356;width: 250rem;font-size: 35rem;line-height: 100rem;text-align: center;
}
.footer-pay > * {display: block;width: 100%;height: 100%;
}
.footer-pay a {display: none;
}
.footer-pay span {font-size: 30rem;
}
.footer-pay.active {background: #76d572;
}
.footer-pay.active a {display: block;
}
.footer-pay.active span {display: none;
}
add-to-car.css
.add-to-car {position: fixed;color: #fff;font-size: 23rem;line-height: 40rem;text-align: center;z-index: 9;margin-left: -20rem;margin-top: -20rem;left: 0;top: 0;/* 匀速动画 */transition: 0.5s linear;
}.add-to-car .iconfont {width: 40rem;height: 40rem;background: #4a90e1;border-radius: 50%;display: block;/* i元素过渡动画,i不应该设置匀速动画。cubic-bezier函数,x1,y1,x2,y2分别代表起点和终点的坐标 */transition: 0.5s cubic-bezier(0.5, -0.5, 1, 1);
}
data.js
var goods = [{pic: './assets/g1.png',title: '椰云拿铁',// desc是富文本desc: `1人份【年度重磅,一口吞云】√原创椰云topping,绵密轻盈到飞起!原创瑞幸椰云™工艺,使用椰浆代替常规奶盖打造丰盈、绵密,如云朵般细腻奶沫体验椰香清甜饱满,一口滑入口腔【饮用建议】请注意不要用吸管,不要搅拌哦~`,sellNumber: 200,//销量,月售favorRate: 95,//好评率price: 32,//价格},{pic: './assets/g2.png',title: '生椰拿铁',desc: `1人份【YYDS,无限回购】现萃香醇Espresso,遇见优质冷榨生椰浆,椰香浓郁,香甜清爽,带给你不一样的拿铁体验!主要原料:浓缩咖啡、冷冻椰浆、原味调味糖浆图片及包装仅供参考,请以实物为准。建议送达后尽快饮用。到店饮用口感更佳。`,sellNumber: 1000,favorRate: 100,price: 19.9,},{pic: './assets/g3.png',title: '加浓 美式',desc: `1人份【清醒加倍,比标美多一份Espresso】口感更佳香醇浓郁,回味持久图片仅供参考,请以实物为准。建议送达后尽快饮用。`,sellNumber: 200,favorRate: 93,price: 20.3,},{pic: './assets/g4.png',title: '瓦尔登蓝钻瑞纳冰',desc: `1人份【爆款回归!蓝色治愈力量】灵感来自下澄明、碧蓝之境---瓦尔登湖。含藻蓝蛋白,梦幻蓝色源自天然植物成分,非人工合成色素,融入人气冷榨生椰浆,椰香浓郁,清冽冰爽;底部添加Q弹小料,0脂原味晶球,光泽剔透,如钻石般blingbling。搭配奶油顶和彩虹色棉花糖,满足你的少女心~【去奶油小提示】由于去掉奶油后顶料口味会受影响,为保证口感,选择“去奶油”选项时将同时去掉奶油及顶料,请注意哦!【温馨提示】瑞纳冰系列产品形态为冰沙,无法进行少冰、去冰操作,请您谅解。【图片仅供参考,请以实物为准】`,sellNumber: 17,favorRate: 80,price: 38,},{pic: './assets/g5.png',title: '椰云精萃美式',desc: `1人份【不用吸管 大口吞云!】1杯热量*≈0.6个苹果!原创瑞幸椰云™工艺,将「椰浆」变成绵密、丰盈的“云朵”,口感绵密顺滑!0乳糖植物基,清爽轻负担!*数据引自《中国食物成分表》第六版,苹果每100克可食部分中能量约为53千卡,以每个苹果250克/个计,1杯椰云精萃美式约80千卡,相当于约0.6个苹果。【图片仅供参考,请以实物为准】`,sellNumber: 50,favorRate: 90,price: 21.12,},];
index.js
// 这里利用ES6中的类来实现单件商品的数据,这种写法是一种面向对象编程的写法,优势是可以将数据和方法进行封装,
// 单件商品的数据
class UIGoods {// 构造函数constructor(g) {this.data = g; // 初始化data属性为传入的参数gthis.choose = 0; // 初始化choose属性为0// this.totalPrice=0;// 初始化totalPrice属性为0,但这样会导致每次计算总价都要重新计算,造成数据冗余// 数据冗余的解决方法:将totalPrice属性设置为私有属性,通过getter方法来获取和设置值// 数据冗余的优缺点:性能下降,但可以减少代码量。且可以提高代码的可读性、可维护性}/*** 获取、计算总价* @return {number} 总价*/getTotalPrice() {return this.data.price * this.choose;}// 是否选中了此件商品isChoose() {// 如果choose大于0,则表示选中了此件商品return this.choose > 0;}/* 选择的数量+1这么写的好处是,可以避免多次判断,提高性能。而且可以提高代码的可读性、可维护性。如果想要在原有基础上增加数量,可以直接调用increase方法*/increase() {this.choose++;}// 选择的数量-1decrease() {// 如果选择的数量为0,则表示没有选择此件商品,不需要减if (this.choose === 0) {return;}this.choose--;}
}// 整个界面的数据
class UIData {constructor() {// 数组var uiGoods = [];// 遍历原始数据,将原始数据转换为单件商品的数据for (var i = 0; i < goods.length; i++) {var uig = new UIGoods(goods[i]);uiGoods.push(uig);}// 将单件商品的数据保存到uiGoods属性中this.uiGoods = uiGoods;// 起送标准 => 还差多少钱起送this.deliveryThreshold = 30;// 起送标准 => 起送价格,配送费用this.deliveryPrice = 5;}
// 总价getTotalPrice() {var sum = 0;// 遍历循环for (var i = 0; i < this.uiGoods.length; i++) {var g = this.uiGoods[i];sum += g.getTotalPrice();}return sum;}// 增加某件商品的选中数量,通过下标拿到对应的商品increase(index) {this.uiGoods[index].increase();}// 减少某件商品的选中数量decrease(index) {this.uiGoods[index].decrease();}// 得到总共的选择数量getTotalChooseNumber() {var sum = 0;for (var i = 0; i < this.uiGoods.length; i++) {sum += this.uiGoods[i].choose;}return sum;}// 判断购物车中有没有东西hasGoodsInCar() {// 这里调用了getTotalChooseNumber,如果数量大于0,那就代表购物车中有东西return this.getTotalChooseNumber() > 0;}// 是否跨过了起送标准isCrossDeliveryThreshold() {return this.getTotalPrice() >= this.deliveryThreshold;}// 判断是否选中了商品,利用了商品的下标isChoose(index) {return this.uiGoods[index].isChoose();}
}// 整个界面
class UI {constructor() {// 商品数据,对商品进行封装,不管是对商品进行增删改查,还是对商品进行计算,都可以统一封装到一个对象中this.uiData = new UIData();// 是用来获取元素的,因为我们是用js来操作dom,所以需要用到dom元素。这doms里面包含了各种dom元素this.doms = {// 获取商品列表容器goodsContainer: document.querySelector(".goods-list"),// 获取配送费deliveryPrice: document.querySelector(".footer-car-tip"),// 获取页脚footerPay: document.querySelector(".footer-pay"),// 获取页脚内的spanfooterPayInnerSpan: document.querySelector(".footer-pay span"),// 获取总价totalPrice: document.querySelector(".footer-car-total"),// 获取购物车car: document.querySelector(".footer-car"),// 获取购物车的角标badge: document.querySelector(".footer-car-badge"),};// 获取购物车的位置var carRect = this.doms.car.getBoundingClientRect();// 获取购物车的中心点var jumpTarget = {x: carRect.left + carRect.width / 2,y: carRect.top + carRect.height / 5,};// 获取购物车的中心点this.jumpTarget = jumpTarget;// 创建商品列表 => 是为了循环创建商品列表元素this.createHTML();// 更新页脚this.updateFooter();// 监听各种事件this.listenEvent();}// 监听各种事件listenEvent() {// 购物车动画this.doms.car.addEventListener("animationend", function () {this.classList.remove("animate");});}// 根据商品数据创建商品列表元素/*两种方式(这里用第一种方式)1.遍历商品数据,将商品数据转换为html字符串 => 优点:可以减少代码量、简单,但性能下降、执行效率低。因为字符串得parse html,得解析成dom元素,且无法直接操作dom元素(总的来说,就是执行效率低,开发效率高)2.一个一个创建商品列表元素 => 优点:性能高、执行效率高,但代码量多,不好维护。而且不需要解析成dom元素,可以直接操作dom元素(总的来说,执行效率高,开发效率低)*/createHTML() {// 生成html字符串var html = "";// 遍历商品数据for (var i = 0; i < this.uiData.uiGoods.length; i++) {// 获取单个商品数据var g = this.uiData.uiGoods[i];// 将单个商品数据转换为html字符串,这里进行了拼接。因为这里是拼接,所以需要使用+=。而且拼接之后就不用在html中添加<div>了html += `<div class="goods-item"><img src="${g.data.pic}" alt="" class="goods-pic"><div class="goods-info"><h2 class="goods-title">${g.data.title}</h2><p class="goods-desc">${g.data.desc}</p><p class="goods-sell"><span>月售 ${g.data.sellNumber}</span><span>好评率${g.data.favorRate}%</span></p><div class="goods-confirm"><p class="goods-price"><span class="goods-price-unit">¥</span><span>${g.data.price}</span></p><div class="goods-btns"><i index="${i}" class="iconfont i-jianhao"></i><span>${g.choose}</span><i index="${i}" class="iconfont i-jiajianzujianjiahao"></i></div></div></div></div>`;}// 将html字符串添加到商品列表容器中this.doms.goodsContainer.innerHTML = html;}// 界面的增加increase(index) {// 增加商品数量this.uiData.increase(index);// 调用更新某个商品元素的显示状态this.updateGoodsItem(index);// 更新页脚this.updateFooter();// 跳到对应的商品this.jump(index);}// 界面的减少decrease(index) {this.uiData.decrease(index);this.updateGoodsItem(index);this.updateFooter();}// 更新某个商品元素的显示状态updateGoodsItem(index) {// 获取商品元素var goodsDom = this.doms.goodsContainer.children[index];// 判断是否选中if (this.uiData.isChoose(index)) {// 选中,就加上active类goodsDom.classList.add("active");} else {// 未选中,就去掉active类goodsDom.classList.remove("active");}// 更新数量var span = goodsDom.querySelector(".goods-btns span");// 将span元素的文本设置为当前商品的数量span.textContent = this.uiData.uiGoods[index].choose;}// 更新页脚updateFooter() {// 得到总价数据var total = this.uiData.getTotalPrice();// 设置配送费this.doms.deliveryPrice.textContent = `配送费¥${this.uiData.deliveryPrice}`;// 设置起送费还差多少if (this.uiData.isCrossDeliveryThreshold()) {// 到达起送点,就加上active类this.doms.footerPay.classList.add("active");} else {// 没有到达起送点,就去掉active类this.doms.footerPay.classList.remove("active");// 如果没有到达起送点,就更新还差多少钱var dis = this.uiData.deliveryThreshold - total;// 四舍五入。因为计算机中小数点计算不准,所以要四舍五入dis = Math.round(dis);// 更新span元素的文本this.doms.footerPayInnerSpan.textContent = `还差¥${dis}元起送`;}// 设置总价,toFixed(2)表示保留两位小数 => 是因为小数点计算不准,所以要四舍五入。利用toFixed(2)将总价变为了字符串格式的数字this.doms.totalPrice.textContent = total.toFixed(2);// 设置购物车的样式状态if (this.uiData.hasGoodsInCar()) {// 有商品,就加上active类this.doms.car.classList.add("active");} else {// 没有商品,就去掉active类this.doms.car.classList.remove("active");}// 设置购物车中的数量,得到总数this.doms.badge.textContent = this.uiData.getTotalChooseNumber();}// 购物车动画carAnimate() {this.doms.car.classList.add("animate");// 去除动画结束事件,但是这样写的话,动画结束事件会被执行两次。而且每写一次,都会有一次动画结束事件。直接在开始写一个动画结束事件,在动画结束事件中去掉动画结束事件,这样就只会执行一次动画结束事件。=> 上面的listenEvent()方法中有写过,效果一样的// this.doms.car.addEventListener("animationend", function () {// // 这里的this是动画事件触发的元素// this.classList.remove("animate");// });}// 抛物线跳跃的元素jump(index) {// 找到对应商品的加号var btnAdd = this.doms.goodsContainer.children[index].querySelector(".i-jiajianzujianjiahao");// 得到加号的坐标var rect = btnAdd.getBoundingClientRect();// 起始坐标var start = {x: rect.left,y: rect.top,};// 跳吧var div = document.createElement("div");// div的样式div.className = "add-to-car";var i = document.createElement("i");// i的样式i.className = "iconfont i-jiajianzujianjiahao";// 设置初始位置,div管横向,i管纵向div.style.transform = `translateX(${start.x}px)`;i.style.transform = `translateY(${start.y}px)`;// 将i添加到div中div.appendChild(i);// 将div添加到body中document.body.appendChild(div);// 强行渲染div.clientWidth;// 设置结束位置,添加一个过渡效果div.style.transform = `translateX(${this.jumpTarget.x}px)`;i.style.transform = `translateY(${this.jumpTarget.y}px)`;var that = this;// 过渡结束后,删除div => 是为了防止动画结束后,div还在body中,导致动画结束后,div还会执行动画结束事件div.addEventListener("transitionend",function () {div.remove();// 购物车动画得到触发that.carAnimate();},{once: true, // 事件仅触发一次});}
}var ui = new UI();// 事件
// 添加点击事件
ui.doms.goodsContainer.addEventListener("click", function (e) {// 判断点击的元素是否是加号if (e.target.classList.contains("i-jiajianzujianjiahao")) {// 得到商品的索引,如果点击的是加好,就加1,如果点击的是减号,就减1。这里将索引(字符串)转成数字类型var index = +e.target.getAttribute("index");ui.increase(index);} else if (e.target.classList.contains("i-jianhao")) {var index = +e.target.getAttribute("index");ui.decrease(index);}
});// 按键事件,如果用户按了+号,就输出Equal,如果按了-号,就输出Minus。这里只是演示,实际开发中,按键事件要用到keydown事件。
window.addEventListener("keypress", function (e) {if (e.code === "Equal") {ui.increase(0);} else if (e.code === "Minus") {ui.decrease(0);}
});/*
也可以用这种方式写,但是用这种方式写的话,会导致代码冗余
function UIGoods(g) {this.data = g;this.choose = 1;
}
UIGoods.prototype.getTotalPrice = function(){return this.data.price * this.choose;
}
UIGoods.prototype.isChoose = function(){return this.choose >0;
}
new UIGoods(goods[0]);*/// 提前优化的优缺点:永远不要提前优化,因为优化之后,代码会变得更复杂、可读性会变差。
// 什么时候优化:出问题的时候,优化一下。要么就是出问题了,要么就是出问题了,要么就是出问题了。
效果图
相关文章:

模拟瑞幸小程序购物车
是根据渡一袁老师的大师课写的,如有什么地方存在问题,还请大家指出来哟ど⁰̷̴͈꒨⁰̷̴͈う♡~ index.html <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8" /><meta http-e…...
react js自定义实现状态管理
redux基础实现 myRedux export const createStore (reduce) > {if (typeof reduce ! function) throw new Error(Expected the reducer to be a function.)let state,listeners []state reduce()const getState () > stateconst dispatch (action) > {if(typeo…...

行为型设计模式——中介者模式
中介者模式 中介者模式主要是将关联关系由一个中介者类统一管理维护,一般来说,同事类之间的关系是比较复杂的,多个同事类之间互相关联时,他们之间的关系会呈现为复杂的网状结构,这是一种过度耦合的架构,即…...
通信行业无线基本概念
fast roaming(快速漫游):使用户在不同的基站(access point)间可以平滑的切换,在802.11r协议标准中定义。band steering(波段转向):在双频段(2.4G和5G…...

grep 在运维中的常用可选项
一、对比两个文件 vim -d <filename1> <filename2> 演示: 需求:~目录下有两个文件一个test.txt 以及 text2.txt,需求对比两个文件的内容。 执行后会显示如图,不同会高亮。 二、两次过滤 场景:当需要多…...
python读取Dicom文件
文章目录 1. pydicom Library2. SimpleITK Library3. ITK Library (Insight Toolkit)4. GDCM Library (Grassroots DICOM) 下面提供几种用python方法读取Dicom文件 1. pydicom Library import pydicom # Read DICOM file dataset pydicom.dcmread("path_to_dicom_file.d…...

UL2034详细介绍UL 安全单站和多站一氧化碳报警器标准
在介绍相关标准之前先介绍一下UL认证和UL测试报告的区别,检测认证行业6年老司机 UL认证是自愿性的认证,需要检测产品和审核工厂,每个季度审核一次,费用高、时间久,而且审厂非常的严格。 UL测试报告是根据产品选用相应…...
鸿蒙HarmonyOS-SDK管理使用指南
鸿蒙HarmonyOS-SDK管理使用指南 文章目录 鸿蒙HarmonyOS-SDK管理使用指南sdkmgr使用指导查看SDK组件安装组件卸载组件查看sdkmgr版本查看sdkmgr帮助options选项说明ohsdkmgr使用指导查看SDK组件安装组件卸载组件查看ohsdkmgr版本查看ohsdkmgr帮助option...

QT上位机开发(进度条操作)
【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing 163.com】 进度条是一个比较常见的控件。如果某个操作需要很长的时间才能完成,那么这个时候最好有一个进度条提示,这样比较容易平复一…...
637_二叉树的层平均值
描述 给定一个非空二叉树的根节点 root , 以数组的形式返回每一层节点的平均值。与实际答案相差 10-5 以内的答案可以被接受 思路 无需思路,乱杀 解答 # Definition for a binary tree node. # class TreeNode: # def __init__(self, val0, leftNone, righ…...

Ubuntu20.4 Mono C# gtk 编程习练笔记(三)
Mono对gtk做了很努力的封装,即便如此仍然与System.Windows.Form中的控件操作方法有许多差异,这是gtk本身特性或称为特色决定的。下面是gtk常用控件在Mono C#中的一些用法。 Button控件 在工具箱中该控件的clicked信号双击后自动生成回调函数prototype&…...
What is `JsonSanitizer.sanitize` does?
JsonSanitizer.sanitize 是一个Java库中的方法,用于处理和净化JSON字符串,特别是针对跨站脚本攻击(XSS, Cross-Site Scripting)。 例如,在处理富文本内容、用户评论、从第三方服务获取的数据时,使用 JsonSa…...
K8S测试pod
背景 用于测试ping,curl等类型的pod Centos pod apiVersion: apps/v1 kind: Deployment metadata:name: centos-deploymentlabels:app: centos spec:replicas: 1selector:matchLabels:app: centostemplate:metadata:labels:app: centosspec:containers:- name: c…...

序章 熟悉战场篇—了解vue的基本操作
了解vue 的基本目录: dist 是打包后存放的目录(打包目录后续可以改)node_modules 是依赖包public 是静态index页面src 是存放文件的目录assets 是存放静态资源的目录components 是存放组件的目录views 是存放页面文件的目录(没有views 自己新建一个&…...
MongoDB聚合:$bucketAuto
按照指定的表达式对输入文档进行分类后放入指定数字的桶中,跟$bucket不太一样,$bucketAuto可以指定分组的数量(颗粒度),$bucketAuto会根据groupBy的值和颗粒度自动生成桶的边界。 语法 {$bucketAuto: {groupBy: <…...

认识监控系统zabbix
利用一个优秀的监控软件,我们可以: ●通过一个友好的界面进行浏览整个网站所有的服务器状态 ●可以在 Web 前端方便的查看监控数据 ●可以回溯寻找事故发生时系统的问题和报警情况 了解zabbix zabbix是什么? ●zabbix 是一个基于 Web 界面的提供分布…...

东北编程语言???
在GitHub闲逛,偶然发现了东北编程语言: 东北编程语言是由Zhanyong Wan创造的,它使用东北方言词汇作为基本关键字。这种编程语言的特点是简单易懂,适合小学文化程度的人学习,并且易于阅读、编写和记忆。它的语法与其他编…...

React16源码: React中的schedule调度整体流程
schedule调度的整体流程 React Fiber Scheduler 是 react16 最核心的一部分,这块在 react-reconciler 这个包中这个包的核心是 fiber reconciler,也即是 fiber 结构fiber 的结构帮助我们把react整个树的应用,更新的流程,能够拆成…...

springboot mybatis-plus swing实现报警监听
通过声音控制报警器,实现声光报警,使用beautyeye_lnf.jar美化界面如下 EnableTransactionManagement(proxyTargetClass true) SpringBootApplication EnableScheduling public class AlarmWarnApplication {public static void main(String[] args) …...

【计算机网络】网络层——详解IP协议
个人主页:兜里有颗棉花糖 欢迎 点赞👍 收藏✨ 留言✉ 加关注💓本文由 兜里有颗棉花糖 原创 收录于专栏【网络编程】 本专栏旨在分享学习计算机网络的一点学习心得,欢迎大家在评论区交流讨论💌 目录 🐱一、I…...

AI-调查研究-01-正念冥想有用吗?对健康的影响及科学指南
点一下关注吧!!!非常感谢!!持续更新!!! 🚀 AI篇持续更新中!(长期更新) 目前2025年06月05日更新到: AI炼丹日志-28 - Aud…...

React第五十七节 Router中RouterProvider使用详解及注意事项
前言 在 React Router v6.4 中,RouterProvider 是一个核心组件,用于提供基于数据路由(data routers)的新型路由方案。 它替代了传统的 <BrowserRouter>,支持更强大的数据加载和操作功能(如 loader 和…...

什么是库存周转?如何用进销存系统提高库存周转率?
你可能听说过这样一句话: “利润不是赚出来的,是管出来的。” 尤其是在制造业、批发零售、电商这类“货堆成山”的行业,很多企业看着销售不错,账上却没钱、利润也不见了,一翻库存才发现: 一堆卖不动的旧货…...
postgresql|数据库|只读用户的创建和删除(备忘)
CREATE USER read_only WITH PASSWORD 密码 -- 连接到xxx数据库 \c xxx -- 授予对xxx数据库的只读权限 GRANT CONNECT ON DATABASE xxx TO read_only; GRANT USAGE ON SCHEMA public TO read_only; GRANT SELECT ON ALL TABLES IN SCHEMA public TO read_only; GRANT EXECUTE O…...

【JavaWeb】Docker项目部署
引言 之前学习了Linux操作系统的常见命令,在Linux上安装软件,以及如何在Linux上部署一个单体项目,大多数同学都会有相同的感受,那就是麻烦。 核心体现在三点: 命令太多了,记不住 软件安装包名字复杂&…...
高效线程安全的单例模式:Python 中的懒加载与自定义初始化参数
高效线程安全的单例模式:Python 中的懒加载与自定义初始化参数 在软件开发中,单例模式(Singleton Pattern)是一种常见的设计模式,确保一个类仅有一个实例,并提供一个全局访问点。在多线程环境下,实现单例模式时需要注意线程安全问题,以防止多个线程同时创建实例,导致…...

RabbitMQ入门4.1.0版本(基于java、SpringBoot操作)
RabbitMQ 一、RabbitMQ概述 RabbitMQ RabbitMQ最初由LShift和CohesiveFT于2007年开发,后来由Pivotal Software Inc.(现为VMware子公司)接管。RabbitMQ 是一个开源的消息代理和队列服务器,用 Erlang 语言编写。广泛应用于各种分布…...

莫兰迪高级灰总结计划简约商务通用PPT模版
莫兰迪高级灰总结计划简约商务通用PPT模版,莫兰迪调色板清新简约工作汇报PPT模版,莫兰迪时尚风极简设计PPT模版,大学生毕业论文答辩PPT模版,莫兰迪配色总结计划简约商务通用PPT模版,莫兰迪商务汇报PPT模版,…...

2025年渗透测试面试题总结-腾讯[实习]科恩实验室-安全工程师(题目+回答)
安全领域各种资源,学习文档,以及工具分享、前沿信息分享、POC、EXP分享。不定期分享各种好玩的项目及好用的工具,欢迎关注。 目录 腾讯[实习]科恩实验室-安全工程师 一、网络与协议 1. TCP三次握手 2. SYN扫描原理 3. HTTPS证书机制 二…...
快刀集(1): 一刀斩断视频片头广告
一刀流:用一个简单脚本,秒杀视频片头广告,还你清爽观影体验。 1. 引子 作为一个爱生活、爱学习、爱收藏高清资源的老码农,平时写代码之余看看电影、补补片,是再正常不过的事。 电影嘛,要沉浸,…...