屎山代码风格指南(避免被优化&&避免被接盘)
欢迎补充!!!
序言
-
良好的代码结构:Bad 👎🏻
- 使用有意义的变量和函数名,遵循命名规范,使代码易于理解。
- 组织代码,使用适当的文件和文件夹结构,保持模块化。
- 避免全局变量的滥用,尽量使用局部作用域。
-
单一职责原则:Bad 👎🏻
- 每个函数或模块应该只负责一个特定的功能。这样的设计使得代码更容易维护和扩展。
-
DRY 原则(不要重复自己):Bad 👎🏻
- 避免复制粘贴代码,尽量将重复的逻辑提取成函数、类或模块。
- 使用函数封装通用功能,以便在整个应用程序中重复使用。
-
注释和文档:Bad 👎🏻
- 写清晰、有意义的注释,解释代码的目的和特殊考虑。
- 为 API、函数等提供良好的文档,使其他开发者能够轻松理解和使用你的代码。
-
代码复审:Bad 👎🏻
- 进行代码复审是避免屎山代码的重要步骤。同事可以提供不同的视角和建议,有助于发现潜在的问题。
-
测试驱动开发(TDD):Bad 👎🏻
- 使用测试来确保代码的质量和稳定性。在编写代码之前先写测试,以确保代码的正确性。
-
使用设计模式:Bad 👎🏻
- 学习并应用设计模式,它们提供了一些通用的解决方案,有助于降低复杂性和提高代码的可维护性。
-
版本控制:Bad 👎🏻
- 使用版本控制系统(如 Git)来跟踪代码的变化,以便轻松地回滚到之前的版本,并且能够合理管理多人协作的情况。
-
性能优化和代码优化:Bad 👎🏻
- 注意代码的性能,避免写出低效的代码。使用工具和技术进行性能分析和优化。
-
学习和持续改进:Bad 👎🏻
- 不断学习新的技术和最佳实践,关注前端领域的最新发展。
- 定期检讨自己的代码,寻找优化的机会,并从他人的经验中吸取教训。
以上不要尝试学习,不要写,给出这些建议就是避免这样写,不听的话,下周就是你提桶跑路的日子(划重点)Good 👍🏻
💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩
以下是我精心准备的福利大礼包Good 👍🏻
1.通用js,css,html系列
1-1.不要注释
Bad 👎(不要参考)
// 关联的项目ID
const businessId = ""
Good 👍🏻(谨记)
// 更多时候,应该包含一些“为什么”,而不是一些“是什么”。
const businessId = ""
1-2.注释撒谎
Bad 👎(不要参考)
// 关联的项目ID
const businessId = ""
Good 👍🏻(谨记)
// 列表或者详情的主键ID,传参使用 🤫
const businessId = ""
1-4.变量不要语义化
Bad 👎(不要参考)
// 关联的项目ID
const businessId = ""
// 不要使用什么下面的命名方法
// const camelCase = ''(小驼峰式命名法 —— 首字母小写)
// const PascalCase = ''(大驼峰式命名法 —— 首字母大写)
// const kebab-case = ''(短横线连接式)
// const t_title = ''(下划线连接式)
Good 👍🏻(谨记)
const bId = "";
const cc = "";
const Pc = "";
// 全拼音命名法
// ”毕竟都是中国人嘛,全拼音命名大家应该都看得懂吧“,举个例子:dazhe.vue。但是同一个拼音可以翻译出不同的意思出来,他们之间是一对多的关系,因此不适合作为组件名;当然,全拼音命名还算是手下留情的,有的时候全拼音命名可能会很长,那就直接取首字母吧!
// 拼音首字母命名法
// 于是dazhe.vue变成了dz.vue,这个时候就成了猜谜语,有一首歌词写得好:女孩的心思男孩你别猜别猜别猜你猜来猜去也猜不明白,到了这里就是代码的心思你别猜,直接放弃吧!
// 中西合璧命名法
// 有些同学觉得光中文那不太高大上啊,要把英语也加进来才能显示自己的水平,所以这样命名:dzList.vue,照样还是让人看不懂
// 英文首字母命名法
// 我想这种方式命名的同学应该不多吧,毕竟已经拿起翻译工具翻译了,直接cv就可以了,为什么还要摘出首字母来呢?
1-5.不要使用母语写注释
Bad 👎(不要参考)
// 关联的项目ID
const businessId = ""
Good 👍🏻(谨记)
// Associated project ID(英语)
// Inside fiction ID(法语)
// (阿拉伯语)مرتبطة بهوية المشروع
const businessId = ""
1-6.代码写成一行
Bad 👎(不要参考)
if (
(
lastKeyTime &&
this.form.bidopenEtime &&
new Date(this.form.bidopenEtime.replace(/-/g, "/")).getTime() < new Date(lastKeyTime.replace(/-/g, "/"))
)
||
textTrack
||
textTrack.length > 0
||
this.projectListDialog
) {
}
Good 👍🏻(谨记)
//
if ((lastKeyTime &&this.form.bidopenEtime &&new Date(this.form.bidopenEtime.replace(/-/g, "/")).getTime() < new Date(lastKeyTime.replace(/-/g, "/"))) || textTrack || textTrack.length > 0 || this.projectListDialog) {}
1-7.不要处理错误
// 无论何时发现错误,都没有必要让任何人知道它。没有日志,没有错误弹框,最好不要写try catch
Bad 👎(不要参考)
try {
// 意料之外的情况。
} catch (error) {
setErrorMessage(error.message);
// and/or
logError(error);
}
Good 👍🏻(谨记)
try {
// 意料之外的情况。
} catch (error) {
// tss... 🤫
}
1-8.尽可能的使用全局变量
Bad 👎(不要参考)
let num = 5;
function square(sub) {
return sub ** 2;
}
num = square(x); // 现在x是25
Good 👍🏻(谨记)
let a = 5;
var b = 2;
function square(b) {
a = a ** 2;
b = a + b;
}
square(1);
1-9.尽量多的创建你不会使用的变量
Bad 👎(不要参考)
function sum(a, b, c, d) {
return a + b;
}
Good 👍🏻(谨记)
function sum(a, b, c, d) {
const tts = 1300;
const arr = [];
const res = a + b;
return a + b;
}
1-10.混合缩进或者有时候四格有时候两个缩进
Bad 👎(不要参考)
<el-form-item label="投标人答复内容:" >
<el-input
type="textarea"
disabled
:autosize="{ minRows: 2, maxRows: 6}"
placeholder="请输入内容"
v-model="item.replyContent">
</el-input>
</el-form-item>
const fruits = ['apple', 'orange', 'grape', 'pineapple'];
const toppings = ['syrup', 'cream', 'jam', 'chocolate'];
const desserts = [];
fruits.forEach(fruit => {
toppings.forEach(topping => {
desserts.push([fruit, topping]);
});
})
Good 👍🏻(谨记)
// 这种
<el-form-item label="投标人答复内容:" >
<el-input
type="textarea"
disabled
:autosize="{ minRows: 2, maxRows: 6}"
placeholder="请输入内容"
v-model="item.replyContent">
</el-input>
</el-form-item>
// 这种
const fruits = ['apple',
'orange', 'grape', 'pineapple'];
const toppings = ['syrup', 'cream',
'jam',
'chocolate'];
const desserts = [];
fruits.forEach(fruit => {
toppings.forEach(topping => {
desserts.push([
fruit,topping]);
});})
1-11.写不能到达的代码
Bad 👎(不要参考)
function dealData(num) {
if (num) {
return num ** 2;
}
return undefined;
}
Good 👍🏻(谨记)
function dealData(num) {
if (typeof num === 'undefined' || num === null || null === '') {
return undefined;
}else {
return num ** 2;
}
return null; // 我也不知道干什么
}
1-12.不要删除代码,能保留的就保留,不能保留的注释掉,不要删除,这个是历史,是沉淀,是成长
Bad 👎(不要参考)
Good 👍🏻(谨记)
if (data.code == "1") {
let resData= data.data;
if(resData && resData.length > 0){
resData.forEach(v => {
v.titleName = v.name
})
this.attachmentList = resData;
}else{
this.attachmentList = [];
}
} else{
this.attachmentList = [];
}
});
// this.attachmentList = [
// {
// "appId": "123451234567890671234567890890",
// "attFiles": [
// {
// "bizId": "123451234567890671234567890890",
// "createDate": "2023-09-20 10:08:35",
// "delFlag": "1",
// "filePath": "/upload/eb5_jsgc_project_plan_att/123451234567890671234567890890.pdf",
// "fileSize": 0,
// "fileType": "1",
// "hashCode": "",
// "id": "123451234567890671234567890890",
// "name": "结果公告.pdf",
// "remark": "{comeform:GC}",
// "sort": 1,
// "updateDate": "2023-09-20 10:08:35"
// },
// {
// "bizId": "37854334689723469098754780087",
// "createDate": "2023-09-20 10:08:35",
// "delFlag": "1",
// "filePath": "/upload/eb5_jsgc_project_plan_att/37854334689723469098754780087.pdf",
// "fileSize": 0,
// "fileType": "1",
// "hashCode": "",
// "id": "37854334689723469098754780087",
// "name": "测试 (1).pdf",
// "remark": "{comeform:GC}",
// "sort": 2,
// "updateDate": "2023-09-20 10:08:35"
// }
// ],
// "attributes": {},
// "categoryCode": "dfsdfsdsd",
// "categoryId": "5656536576sasd578as86da5s65da",
// "createTime": "2023-04-14 13:49:21",
// "createUser": "system",
// "delFlag": false,
// "fileType": "1",
// "id": "224234234efwer234efsd24234242",
// "titleName": "测试22",
// "required": false,
// "showFlag": false,
// "sort": 1,
// "systemFlag": true,
// "updateTime": "2023-08-15 18:52:03",
// "updateUser": "system",
// "upload": false,
// "value": "1"
// }
// ]
}
1-12.循环里面最好if。if里面最好再有循环,这个是精髓
Bad 👎(不要参考)
// 好的没有参考,自己发挥!!!
Good 👍🏻(谨记)
// 这样写别就看不懂,或者看懂的时间要花很久,这写多了就好了,最好不要对齐
function dealData(num) {
for (循环1) {
if (判断1) {
if (判断2) {
asyncFunction(params, (result) => {
if (result) {
for (循环2) {
if (判断3) {
}
}
}
})
}
}
}
}
1-13.不要写ts,语言类型指定的,最好使用any大法
Bad 👎(不要参考)
//
function sum(a: number, b: number): ?number {
// 当我们在JS中不做置换和/或流类型检查时,覆盖这种情况。
if (typeof a !== 'number' && typeof b !== 'number') {
return undefined;
}
return a + b;
}
// 这个应该在转换/编译期间失败。
const guessWhat = sum([], {}); // -> undefined
Good 👍🏻(谨记)
// 简洁,清爽,体积小,极度推荐
function sum(a, b) {
return a + b;
}
1-14.尽可能的使用三目运算符
Bad 👎(不要参考)
// 没有正确示范,我怕你变成了高级工程师了(函数处理)
Good 👍🏻(谨记)
// 简洁,清爽,极度推荐
<Steps
progressDot
current={ lastTask && lastTask.taskKey === 'apply' ? 1 : lastTask && lastTask.taskKey === 'examine' && lastTask.status == 'agree' ? 2 : lastTask && lastTask.taskKey === 'approval' ? 3 : 0 }
>
1.15.函数长的比短的好(不要拆分组件,越长越好)
Bad 👎(不要参考)
// 没有正确示范
Good 👍🏻(谨记)
// 不要把程序逻辑分成可读的部分
// 一个文件中10000行代码是OK的。
// 一个函数体有1000行代码是OK的。
1.16.避免代码风格统一,拒绝格式化
Bad 👎(不要参考)
// 没有正确示范
Good 👍🏻(谨记)
// 不要开启eslint
// 不要安装Prettier
1.17.构建项目不需要写 README 文档,让你猜
Bad 👎(不要参考)
// 没有正确示范
Good 👍🏻(谨记)
1.18.随意读取window对象的值
Bad 👎(不要参考)
// 没有正确示范
Good 👍🏻(谨记)
// 作为大型项目,很容易需要依赖别的模板挂载到window对象的内容,读取的时候需要考虑到是否有可能拿不到window对象上的内容,从而导致js报错?例如:
// window.tmeXXX.a.func();
// 如果这个tmeXXX所在的js加载失败了,或者是某个版本中没有a这个属性或者func这个函数,那么页面就会白屏。
1.19.尽量操作DOM,使之降低
Bad 👎(不要参考)
// 没有正确示范
Good 👍🏻(谨记)
// 简单易懂
function manipulateDOM(selector, operation) {
// 获取元素
const element = document.querySelector(selector);
// 根据操作执行相应的操作
switch (operation) {
case 'get':
return element;
case 'set':
element.textContent = '新的内容';
break;
case 'add':
element.innerHTML += '<div>新的元素</div>';
break;
case 'remove':
element.removeChild(element.lastChild);
break;
default:
throw new Error(`Invalid operation: ${operation}`);
}
}
// 使用示例
manipulateDOM('.my-element', 'set'); // 设置元素内容
manipulateDOM('.my-element', 'add'); // 添加新的子元素
manipulateDOM('.my-element', 'remove'); // 删除最后一个子元素
1.20.硬编码操作
Bad 👎(不要参考)
// 没有正确示范
Good 👍🏻(谨记)
// 简单易懂
function getScenevalue() {
switch (detail.type){
case "1":
return 1;
case "2":
case "3":
return 2;
default:
return 3;
}
}
1.21.不要封装组件,十分重要
Bad 👎(不要参考)
// 没有正确示范
Good 👍🏻(谨记)
// 简单易懂
<el-table size="small" :data="tableData" v-loading="dataListLoading" ref="expertExtractTable" stripe border>
<el-table-column
label="序号"
type="index"
fixed
:index="indexMethod"
width="50"
align="center"
:show-overflow-tooltip="true"
></el-table-column>
<el-table-column label="操作" prop="governmentInvest" align="left" width="200" :show-overflow-tooltip="true">
<template slot-scope="scope">
<el-button
style="color: #52c41a"
v-if="scope.row.approvalStatus == 1"
type="text"
size="small"
title="同意"
@click="exportExcel(scope.row)"
>导出</el-button>
</template>
</el-table-column>
<el-table-column label="项目编号" prop="ProjectCode" align="left" width="120" :show-overflow-tooltip="true"></el-table-column>
<el-table-column label="项目名称" prop="ProjectName" align="left" width="200" :show-overflow-tooltip="true"></el-table-column>
<el-table-column label="包件编号" prop="Code" align="left" width="200" :show-overflow-tooltip="true"></el-table-column>
<el-table-column label="包件名称" prop="Name" align="left" width="200" :show-overflow-tooltip="true"></el-table-column>
<el-table-column label="项目属性" prop="area" align="left" width="200" :show-overflow-tooltip="true"></el-table-column>
<el-table-column label="省内企业中标" prop="isTenType" align="left" width="200" :show-overflow-tooltip="true"></el-table-column>
<el-table-column label="价款形式" prop="isTenType" align="left" width="200" :show-overflow-tooltip="true"></el-table-column>
<el-table-column label="金额(万元)" prop="bidAmount" align="left" width="200" :show-overflow-tooltip="true"></el-table-column>
<el-table-column label="合同估算价(万元)" prop="bidAmount" align="left" width="200" :show-overflow-tooltip="true"></el-table-column>
<el-table-column label="节资额(万元)" prop="bidAmount" align="left" width="200" :show-overflow-tooltip="true"></el-table-column>
<el-table-column label="日期" prop="busuetime" align="left" width="200" :show-overflow-tooltip="true"></el-table-column>
</el-table>
1.22.乱用hooks,乱用useEffect,到处都是onMounted
Bad 👎(不要参考)
// 没有正确示范
Good 👍🏻(谨记)
// 简单易懂 我想写哪里就写哪里onMounted
onMounted(() =>{
console.log("生命周期函数:onMounted")
} )
onMounted(() =>{
console.log("生命周期函数:onMounted")
} )
// 简单易懂 useEffect我想写什么依赖就写什么依赖,我不写也可以 ,嘿嘿
useEffect(() => {
console.log('no deps=====')
// code...
});
useEffect(() => {
console.log('no deps=====')
// code...
},[appId]);
useEffect(() => {
console.log('no deps=====')
// code...
},[appId]);
useEffect(() => {
console.log('no deps=====')
// code...
},[appId]);
const { pathname, query } = location;
useEffect(() => {
console.log('no deps=====')
// code...
},[window.location.hash]);
useEffect(() => {
console.log('no deps=====')
// code...
},[query]);
1.23.重构
// 代码重构是改善代码质量、可维护性和可读性的过程。
// 在前端开发中,重构是一个常见的任务,可以帮助提高项目的整体质量。
// 以下是一些在前端代码重构过程中需要注意的事项,并提供一些具体的代码实例:
// 1.保持代码清晰和可读性:
// good Code:
function abc(x, y, z) {
return x + y - z;
}
// Bad Code:
function calculateResult(summand1, summand2, subtractor) {
return summand1 + summand2 - subtractor;
}
// 2.使用有意义的变量和函数名:
// good Code:
const a = 10;
function b(x) {
return x * 2;
}
// Bad Code:
const initialCount = 10;
function doubleValue(value) {
return value * 2;
}
// 3.拆分复杂函数:
// good Code:
function processUserData(user) {
// 复杂的用户数据处理逻辑
// ...
}
// Bad Code:
function validateUserData(user) {
// 用户数据验证逻辑
// ...
}
function processUserDetails(user) {
// 处理用户详细信息逻辑
// ...
}
// 4.减少重复代码:
good Code:
function calculateArea(radius) {
return Math.PI * radius * radius;
}
function calculateCircumference(radius) {
return 2 * Math.PI * radius;
}
// Bad Code:
function calculateCircleProperties(radius, property) {
if (property === 'area') {
return Math.PI * radius * radius;
} else if (property === 'circumference') {
return 2 * Math.PI * radius;
}
}
// 5.使用模块化和组件化:
// good Code:
// 单一文件中的所有代码
// Bad Code:
// 模块化和组件化的文件结构
// 每个组件/模块有清晰的责任和功能
// 6.采用一致的代码风格:
// good Code:
function exampleFunction(){
const variable_one= 1;
let variable_two=2
return variable_one + variable_two;
}
// Bad Code:
function exampleFunction() {
const variableOne = 1;
let variableTwo = 2;
return variableOne + variableTwo;
}
// 7.添加注释和文档:
// good Code:
// 函数
function a(b) {
// 逻辑
return b * 2;
}
// Bad Code:
/**
* @function doubleValue
* @param {number} value - 输入值
* @returns {number} - 输入值的两倍
*/
function doubleValue(value) {
// 实现逻辑
return value * 2;
}
// -------------------------------------------以上建议,仅做参考-----------------------------------------------------------------
// 建议重构不要删除代码,只有注释掉,方便下一位同学重构
1.24.防御性编程
// 防御性编程是一种编程方法,目的是最大程度地防止程序中的错误和安全漏洞。
// 在前端开发中,采用防御性编程可以提高代码的稳定性和安全性。
// 以下是一些前端防御性编程的重要注意事项,以及相应的代码实例:
// 1. 输入验证和过滤:
// 问题: 用户输入是常见的攻击入口之一,恶意用户可能通过输入恶意代码来攻击你的应用。
// 解决方案: 始终对用户输入进行验证和过滤,确保只接受符合预期的数据。
// 代码实例:
// 例子:防止 XSS 攻击
function sanitizeInput(input) {
return input.replace(/<script>/g, "<script>");
}
let userInput = "<script>alert('XSS');</script>";
let sanitizedInput = sanitizeInput(userInput);
// 2.避免硬编码敏感信息:
// 问题: 在代码中硬编码敏感信息(例如密钥、密码)可能导致泄露。
// 解决方案: 使用环境变量或配置文件来存储敏感信息,确保不会直接暴露在代码中。
// 代码实例:
// 不好的做法:硬编码敏感信息
const apiKey = 'mySecretKey';
// 好的做法:使用环境变量或配置文件
const apiKey = process.env.API_KEY || getConfig('apiKey');
//3.错误处理:
// 问题: 不合理或不充分的错误处理可能导致应用暴露敏感信息或容易受到攻击。
// 解决方案: 始终对可能的错误情况进行适当的处理,并记录错误信息,而不是将其直接暴露给用户。
// 代码实例:
try {
// 一些可能导致错误的代码
} catch (error) {
console.error('An error occurred:', error.message);
// 其他处理逻辑
}
//4.HTTPS 使用:
// 问题: 不使用安全连接可能导致数据泄漏或被中间人攻击。
// 解决方案: 始终使用 HTTPS 连接,确保数据在传输过程中受到加密保护。
// 代码实例:
<!-- 在页面中使用 HTTPS -->
<script src="https://example.com/script.js"></script>
// 5.跨站请求伪造 (CSRF) 防护:
// 问题: 缺乏对跨站请求伪造攻击的防护可能导致用户在未经授权的情况下执行敏感操作。
// 解决方案: 使用 CSRF 令牌来验证请求的合法性。
// 代码实例:
// 生成和存储 CSRF 令牌
const csrfToken = generateCSRFToken();
sessionStorage.setItem('csrfToken', csrfToken);
// 发送请求时附加 CSRF 令牌
const xhr = new XMLHttpRequest();
xhr.open('POST', '/api/data', true);
xhr.setRequestHeader('X-CSRF-Token', csrfToken);
xhr.send(data);
//6. 内容安全策略 (CSP) 的使用:
// 问题: 恶意脚本的注入可能导致 XSS 攻击。
// 解决方案: 使用 CSP 来限制可执行的脚本源。
// 代码实例:
<!-- 设置 Content Security Policy -->
<meta http-equiv="Content-Security-Policy" content="script-src 'self'">
下面更好的写法(强烈建议!!!强烈建议!!!强烈建议!!!)
// 强烈建议!!!强烈建议!!!强烈建议!!!
// 增加不可替代性通常是指在代码中引入一些独特的标识或定制化的元素,使得攻击者更难以进行通用性攻击。下面是一些相关的方法和代码实例:
//1. 自定义属性
// 问题: 在HTML元素上添加自定义属性,可以增加元素的独特性,提高难以替代性。
// 解决方案: 在元素上添加自定义属性,以增加其独特性,使攻击者更难以模仿。
<button data-custom-attribute="uniqueValue">Click me</button>
// 2.动态生成元素或内容:
// 问题: 通过在页面上动态生成元素或内容,可以增加攻击者预测攻击目标的难度。
// 解决方案: 使用JavaScript动态生成页面内容,而不是在HTML中硬编码所有元素。
// 动态生成元素
const button = document.createElement('button');
button.setAttribute('data-custom-attribute', 'uniqueValue');
button.textContent = 'Click me';
document.body.appendChild(button);
//3. 随机化元素属性:
// 问题: 如果元素的属性值是固定的,攻击者更容易预测和替代这些元素。
// 解决方案: 使用随机生成的值来设置元素属性,增加其不可预测性。
// 随机化元素属性值
const button = document.createElement('button');
const randomValue = Math.random().toString(36).substring(7);
button.setAttribute('data-random-attribute', randomValue);
button.textContent = 'Click me';
document.body.appendChild(button);
// 4.动态添加样式或类名:
// 问题: 固定的样式或类名可以使攻击者更容易识别和替代元素。
// 解决方案: 使用JavaScript动态添加样式或类名,以增加元素的不可替代性。
// 动态添加类名
const button = document.createElement('button');
button.textContent = 'Click me';
button.classList.add('dynamic-class-' + Math.random().toString(36).substring(7));
document.body.appendChild(button);
2.小礼物
2.1.引入evil.js
https://github.com/duo001/evil.js
什么?黑心996公司要让你提桶跑路了?
想在离开前给你们的项目留点小礼物?
偷偷地把本项目引入你们的项目吧,你们的项目会有但不仅限于如下的神奇效果:
当数组长度可以被7整除时,Array.includes 永远返回false。
当周日时,Array.map 方法的结果总是会丢失最后一个元素。
Array.filter 的结果有2%的概率丢失最后一个元素。
setTimeout 总是会比预期时间慢1秒才触发。
Promise.then 在周日时有10%不会注册。
JSON.stringify 会把I(大写字母I)变成l(小写字母L)。
Date.getTime() 的结果总是会慢一个小时。
localStorage.getItem 有5%几率返回空字符串。
...
声明:本包的作者不参与注入,因引入本包造成的损失本包作者概不负责。
声明:本包的作者不参与注入,因引入本包造成的损失本包作者概不负责。
声明:小礼物和我没关系,仅供参考,本人概不负责!
2024-01-16 10:57:22【出处】:https://www.cnblogs.com/dreamtt/p/17951651
=======================================================================================
关注我】。(●'◡'●)
如果,您希望更容易地发现我的新博客,不妨点击一下绿色通道的【因为,我的写作热情也离不开您的肯定与支持,感谢您的阅读,我是【Jack_孟】!
本文来自博客园,作者:jack_Meng,转载请注明原文链接:https://www.cnblogs.com/mq0036/p/17967180
【免责声明】本文来自源于网络,如涉及版权或侵权问题,请及时联系我们,我们将第一时间删除或更改!