难以置信,一个小小的需求让我捣鼓出一个提效的网站来

难以置信,一个小小的需求让我捣鼓出一个提效的网站来

需求介绍

事情是这样的,有个群友在业务当中碰到一个小小的需求,需求是这样的: 页面当中存在多个输入框,输入框的 value 值是一个数值组成的字符串(盲猜应该是身份证号码),这个字符串的位数是 15 位或者是 18 位,例如:'621848063680370'(15 位)和'621848063688370808'(18 位),然后默认的值是这样的,现在问题来了,需求希望在这些数值中插入空白符号,比如 15 位的数字就按照 6 + 6 + 3 的格式分隔,分隔的时候需要使用空白符号。比如'621848063680370'分隔后应该变成'621848 063680 370',也就是数字位数到了第 6 位就加个空白符号分隔,...依次类推,而 18 位数字的分割规则则是:6 + 4 + 4 + 4。比如'621848063688370808'应该分隔成'621848 0636 8837 0808'。

这个需求就是对字符串的处理,提到分隔替换,那么我们就可以想到强大的字符串替换方法 replace,这个方法可以接受 2 个参数,一个参数通常是一个正则表达式,第二个参数则是一个回调函数,用于定义替换后返回字符串。因此,我的第一个想法就是使用正则表达式去处理,如何处理呢?

原理分析

首先我们需要去理解这个规则,从需求我们可以发现,不同的位数,规则就会有所不同,因此我们可以提前用一个数据来表示这种规则,为了保持良好的扩展性,我设计了如下字段:

type spaceRule = {digit: number; // 位数rule: RegExp; //规则symbolNumber: number; // 插入符号数量symbolName: string; // 插入符号
};

可以看到,我设计了四个参数,正如注释所说,每一个参数都有具体的含义,为什么要如此设计参数呢?还是看需求,我们需求首先是限定了数字的位数,只可能是 15 位或者是 18 位,那如果存在 19 位又或者 20 位的场景呢?因此我们需要设计一个位数的参数,然后是每一个位数对应的规则是不一样的,因此我们也需要设计一个 rule 参数,然后是插入符号数量,也许会存在 1 个空白,2 个空白等等场景,或者我们不一定插入空白符号,也有可能是其它符号例如"-"等等,因此就设计 symbolNumber 和 symbolName 参数。

既然规则是类似 6 + 6 + 3 这样的规则,因此我们想到使用正则表达式来完成这个功能是可以的,我们将其拆分开来,分成 3 个分组,第一个分组匹配 6 个数字,第二个分组匹配 6 个数字,第三个分组匹配 3 个数字,然后针对分组之间插入特定的符号即可。

正则表达式中匹配数字可以使用'\d'来表示,然后匹配位数位 6,我们就可以使用量词'{6,}'来表示,因此我们的 6 + 6 + 3 规则就可以写成如下:

const rule = /(\d{6,})(\d{6,})(\d{3,})/g;

replace方法核心参数

接下来根据 mdn 对 replace 第二个参数回调函数参数的介绍,我们就知道,如果匹配到了正则表达式,则回调函数的参数会是如下所示:

function replacer(match, p1, p2, /* …, */ pN, offset, string, groups) {return replacement;
}

其中 p1,p2...pN 就是我们这里需要用到的匹配分组,有个专业的名词叫做捕获组,前面 9 个捕获组对应的就是正则表达式实例对象的$1....$9 属性。

然后其返回值就会用作字符串被替代的部分,因此这里我们可以使用展开运算符将中间的捕获组截取出来,然后利用 join 方法,传入需要插入的符号即可转成符合需求的字符串。

ps: 由于这里经过我对谷歌浏览器的测试,replacer 的倒数第 3 个参数不存在,因此我这里截取结束索引值就是 args.length - 2。

因此,我们可以写出如下代码:

const spaceRule = {digit: 15,rule: /(\d{6,})(\d{6,})(\d{3,})/g,symbolNumber: 1,symbol: " ",
};
const allInputs = document.querySelectorAll("input");
allInputs.forEach((item) => {const v = item.value;const { symbolNumber, symbol, rule } = spaceRule;item.value = v.replace(rule, (...args) =>args?.slice(1, args.length - 2)?.join(symbol.repeat(symbolNumber)));
});

这样就达到了将输入框中 15 位数字中间插入符号的需求,并且满足 6 + 6 + 3 的规则。如果是 18 位数字,规则也变成了 6 + 4 + 4 + 4,我们就只需要修改 digit 和 rule 值即可,如下:

const spaceRule = {digit: 18,rule: /(\d{6,})(\d{4,})(\d{4,})(\d{4,})/g,symbolNumber: 1,symbol: " ",
};
const allInputs = document.querySelectorAll("input");
allInputs.forEach((item) => {const v = item.value;const { symbolNumber, symbol, rule } = spaceRule;item.value = v.replace(rule, (...args) =>args?.slice(1, args.length - 2)?.join(symbol.repeat(symbolNumber)));
});

可以看到,我们核心的替换逻辑是没有变动的,变动的只是我们定义的规则而已,哪怕是用在 vue 和 react 框架当中,我们也只是修改一些框架特定的语法,但其实核心替换逻辑还是不会变动,比如 vue2 代码如下:

const spaceRule = {digit: 18,rule: "6 + 4 + 4 + 4",symbolNumber: 1,symbol: " ",
};
export default {methods: {onFormatValue(item) {const { symbolNumber, symbol, rule } = spaceRule;const regExp = new RegExp(`${rule.split("+").map((item) => `(\\d{${Number(item)},})`).reduce((res, item) => ((res += item), res), "")}`,"g");const formatValue = item.replace(regExp, (...args) =>args?.slice(1, args.length - 2)?.join(symbol.repeat(symbolNumber)));return formatValue;},},
};

vue3 代码如下:

const spaceRule = {digit: 18,rule: "6 + 4 + 4 + 4",symbolNumber: 1,symbol: " ",
};
const onFormatValue = computed(() => (item) => {const { symbolNumber, symbol, rule } = spaceRule;const regExp = new RegExp(`${rule.split("+").map((item) => `(\\d{${Number(item)},})`).reduce((res, item) => ((res += item), res), "")}`,"g");const formatValue = item.replace(regExp, (...args) =>args?.slice(1, args.length - 2)?.join(symbol.repeat(symbolNumber)));return formatValue;
});

react 代码如下:

const spaceRule = {digit: 18,rule: "6 + 4 + 4 + 4",symbolNumber: 1,symbol: " ",
};
const FormatInput = () => {const onFormatValue = React.useCallback((value) => {const { symbolNumber, symbol, rule } = spaceRule;const regExp = new RegExp(`${rule.split("+").map((item) => `(\\d{${Number(item)},})`).reduce((res, item) => ((res += item), res), "")}`,"g");const formatValue = value.replace(regExp, (...args) =>args?.slice(1, args.length - 2)?.join(symbol.repeat(symbolNumber)));return formatValue;}, []);return <input type="text" value={onFormatValue("621848063688370808")} />;
};
export default FormatInput;

纵观以上的代码,我们可以发现核心的 js 逻辑是没有变动的,变动的只是一些框架有的概念而已,例如 vue2 中,我们使用方法结合双向绑定指令 v-model 来修改,而 react 也是同理,vue3 我们则是使用计算属性来表示。

网站介绍

基于以上的分析,接下来,就是我们这个提效网站实现的雏形,首先来看一下网站,如下图所示:

截图截的不全,更详细可以点这里查看。

通过以上的网站展示,我们已经初步构思好了整个网站的构架:

  1. 创建规则的表单部分。
  2. 预览效果部分。
  3. 代码展示部分。

其中代码展示部分又提供了不同框架和原生版本的展示以及复制,同样的还提供了在线示例的下载,其它就是一些额外展示功能组件,没什么可说的,比如底部链接展示,头部组件,还有就是需求介绍展示组件。

核心原理我们已经知道了,接下来无非就是写好页面架构,技术选型上我们使用的是 vue3 + vite + naive-ui 组件库。

重点代码分析

核心页面我们也不必要介绍,这里只重点提一下一些重要功能的实现点,首先是代码压缩包的下载,我们采用的是 file-saver 和 jszip 库,代码很简单,如下所示:

const zip = new JSZip();
zip.file(`${codeTypeValue.value}-demo.html`,htmlTemplate(renderTemplateCode.value.html,renderTemplateCode.value.js,codeTypeValue.value)
);
// 调用zip的generateAsync生成一个blob文件
const content = await zip.generateAsync({ type: "blob" });
// saveAs 方法实现下载
saveAs(content, `${codeTypeValue.value}-demo.zip`);

其实这里的 htmlTemplate 就是构造一个下载代码模板,如下所示:

import { CodeTemplateKey } from "./code";export const getScriptTemplate = (type: CodeTemplateKey) => {if (type.includes("vue")) {const src =type === "vue2"? "https://cdn.bootcdn.net/ajax/libs/vue/2.6.7/vue.min.js": "https://cdn.bootcdn.net/ajax/libs/vue/3.3.4/vue.global.min.js";return `<script src="${src}"></script>`;} else if (type === "react") {return `<script src="https://cdn.bootcdn.net/ajax/libs/react/18.2.0/umd/react.production.min.js"></script><script src="https://cdn.bootcdn.net/ajax/libs/react-dom/18.2.0/umd/react-dom.production.min.js"></script><script src="https://cdn.bootcdn.net/ajax/libs/babel-standalone/7.22.17/babel.min.js"></script>`;} else {return "";}
};
export const htmlTemplate = (htmlContent: string,jsContent: string,type: CodeTemplateKey
) => `
<!DOCTYPE html>
<html>
<head><meta charset="utf-8"><meta name="viewport" content="width=device-width"><title>输入框生成插入符号 ${type} demo</title><style>body {margin: 0;}input {padding: 8px 24px;border: 0;border-radius: 15px;background-color: #fefefe;color: rgba(0, 0, 0, .85);margin: 8px 0;border: 1px solid #232323;min-width: 250px;}</style>
</head>
<body><div id="app">${htmlContent}</div>${getScriptTemplate(type)}<script type="${type === "react" ? "text/babel" : "text/javascript"}">${jsContent}</script>
</body>
</html>`;

代码模板如下:

export const codeTemplate = {js: (options: IFormValue) => ({html: Array.from({ length: options.inputNumber }).map((_, i) => options.inputContent[i]).map((item) => `<input type="text" value="${item}"/>\n`).join(""),js: `
const spaceRule = {digit: ${options.digit},rule: /${options.rule.split("+").map((item) => `(\\d{${Number(item)},})`).reduce((res, item) => ((res += item), res), "")}/g,symbolNumber: ${options.symbolNumber},symbol: '${options.symbol}'
};
const allInputs = document.querySelectorAll('input');
allInputs.forEach(item => {const v = item.value;const { symbolNumber, symbol, rule } = spaceRule;item.value = v.replace(rule, (...args) => args?.slice(1, args.length - 2)?.join(symbol.repeat(symbolNumber)));
})`,}),vue2: (options: IFormValue) => ({html: Array.from({ length: options.inputNumber }).map((_, i) => options.inputContent[i]).map((_) => `<input type="text" v-model="onFormatValue('${_}')" />\n`).join(""),js: `
const spaceRule = {digit: ${options.digit},rule: '${options.rule}',symbolNumber: ${options.symbolNumber},symbol: '${options.symbol}'
};
export default {methods:{onFormatValue(item){const { symbolNumber,symbol,rule } = spaceRule;const regExp = new RegExp(\`\${rule.split('+').map(item => \`(\\\\d{\$\{Number(item)\},})\`).reduce((res, item) => (res += item, res), '')}\`, 'g');const formatValue = item.replace(regExp, (...args) => args?.slice(1, args.length - 2)?.join(symbol.repeat(symbolNumber)));return formatValue;}}
}`,}),vue3: (options: IFormValue) => ({html: Array.from({ length: options.inputNumber }).map((_, i) => options.inputContent[i]).map((_) => `<input type="text" :value="onFormatValue('${_}')" />\n`).join(""),js: `
const spaceRule = {digit: ${options.digit},rule: '${options.rule}',symbolNumber: ${options.symbolNumber},symbol: '${options.symbol}'
};
const onFormatValue = computed(() => (item) => {const { symbolNumber,symbol,rule } = spaceRule;const regExp = new RegExp(\`\${rule.split('+').map(item => \`(\\\\d{\$\{Number(item)\},})\`).reduce((res, item) => (res += item, res), '')}\`, 'g');const formatValue = item.replace(regExp, (...args) => args?.slice(1, args.length - 2)?.join(symbol.repeat(symbolNumber)));return formatValue;
})`,}),react: (options: IFormValue) => ({html: "",js: `
const spaceRule = {digit: ${options.digit},rule: '${options.rule}',symbolNumber: ${options.symbolNumber},symbol: '${options.symbol}'
};
const FormatInput = () => {const onFormatValue = React.useCallback((value) => {const { symbolNumber,symbol,rule } = spaceRule;const regExp = new RegExp(\`\${rule.split('+').map(item => \`(\\\\d{\$\{Number(item)\},})\`).reduce((res, item) => (res += item, res), '')}\`, 'g');const formatValue = value.replace(regExp, (...args) => args?.slice(1, args.length - 2)?.join(symbol.repeat(symbolNumber)));return formatValue;},[])return (${Array.from({ length: options.inputNumber }).map((_, i) => options.inputContent[i]).map((_) => `<input type="text" value={onFormatValue('${_}')} />`).join("")})
}
export default FormatInput;`,}),
};export const demoCodeTemplate = {js: (options: IFormValue) => ({html: Array.from({ length: options.inputNumber }).map((_, i) => options.inputContent[i]).map((item) => `<input type="text" value="${item}"/>\n`).join(""),js: `
const spaceRule = {digit: ${options.digit},rule: /${options.rule.split("+").map((item) => `(\\d{${Number(item)},})`).reduce((res, item) => ((res += item), res), "")}/g,symbolNumber: ${options.symbolNumber},symbol: '${options.symbol}'
};
const allInputs = document.querySelectorAll('input');
allInputs.forEach(item => {const v = item.value;const { symbolNumber, symbol, rule } = spaceRule;item.value = v.replace(rule, (...args) => args?.slice(1, args.length - 2)?.join(symbol.repeat(symbolNumber)));
})`,}),vue2: (options: IFormValue) => ({html: Array.from({ length: options.inputNumber }).map((_, i) => options.inputContent[i]).map((_) => `<input type="text" v-model="onFormatValue('${_}')" />\n`).join(""),js: `
const spaceRule = {digit: ${options.digit},rule: '${options.rule}',symbolNumber: ${options.symbolNumber},symbol: '${options.symbol}'
};
new Vue({el:"#app",methods:{onFormatValue(item){const { symbolNumber,symbol,rule } = spaceRule;const regExp = new RegExp(\`\${rule.split('+').map(item => \`(\\\\d{\$\{Number(item)\},})\`).reduce((res, item) => (res += item, res), '')}\`, 'g');const formatValue = item.replace(regExp, (...args) => args?.slice(1, args.length - 2)?.join(symbol.repeat(symbolNumber)));return formatValue;}}
});`,}),vue3: (options: IFormValue) => ({html: Array.from({ length: options.inputNumber }).map((_, i) => options.inputContent[i]).map((_) => `<input type="text" :value="onFormatValue('${_}')" />\n`).join(""),js: `
const spaceRule = {digit: ${options.digit},rule: '${options.rule}',symbolNumber: ${options.symbolNumber},symbol: '${options.symbol}'
};
Vue.createApp({setup() {const onFormatValue = Vue.computed(() => (item) => {const { symbolNumber,symbol,rule } = spaceRule;const regExp = new RegExp(\`\${rule.split('+').map(item => \`(\\\\d{\$\{Number(item)\},})\`).reduce((res, item) => (res += item, res), '')}\`, 'g');const formatValue = item.replace(regExp, (...args) => args?.slice(1, args.length - 2)?.join(symbol.repeat(symbolNumber)));return formatValue;})return {onFormatValue}}}).mount('#app')`,}),react: (options: IFormValue) => ({html: "",js: `
const spaceRule = {digit: ${options.digit},rule: '${options.rule}',symbolNumber: ${options.symbolNumber},symbol: '${options.symbol}'
};
const FormatInput = () => {const onFormatValue = React.useCallback((value) => {const { symbolNumber,symbol,rule } = spaceRule;const regExp = new RegExp(\`\${rule.split('+').map(item => \`(\\\\d{\$\{Number(item)\},})\`).reduce((res, item) => (res += item, res), '')}\`, 'g');const formatValue = value.replace(regExp, (...args) => args?.slice(1, args.length - 2)?.join(symbol.repeat(symbolNumber)));return formatValue;},[])return (${Array.from({ length: options.inputNumber }).map((_, i) => options.inputContent[i]).map((_) => `<input type="text" value={onFormatValue('${_}')} />`).join("")})
}
const root = ReactDOM.createRoot(document.querySelector('#app'));
root.render(<FormatInput />);`,}),
};export type CodeTemplateKey = keyof typeof codeTemplate;// 代码key列表
export const codeTypeList = Object.keys(codeTemplate) as CodeTemplateKey[];// 代码版本下拉列表
export const selectCodeTypeList = codeTypeList.map((item) => ({label: item,value: item,
}));

然后就是我们的 copy 复制代码功能函数的实现,原理就是利用了 navigator.clipboard api,如果浏览器不支持,我们就使用 document.execCommand api,工具函数代码如下所示:

export const copyHandler = (str: string, dialog?: DialogApi) => {const confirm = (title = "温馨提示", content = "已复制到剪切板") => {dialog?.success({title: title,content: content,positiveText: "确定",});};const baseCopy = (copyText: string) =>new Promise<void>((resolve, reject) => {// 判断是否存在clipboard并且是安全的协议if (navigator.clipboard && window.isSecureContext) {navigator.clipboard.writeText(copyText).then(() => {resolve();}).catch(() => {reject(new Error("复制失败"));});} else {// 否则使用被废弃的execCommandconst input = document.createElement("input") as HTMLInputElement;input.value = copyText;// 使input不在viewport,同时设置不可见input.style.position = "absolute";input.style.left = "-9999px";input.style.top = "-9999px";document.body.append(input);input.focus();input.select();// 执行复制命令并移除文本框if (document.execCommand) {document.execCommand("copy");resolve();} else {reject(new Error("复制失败"));}input.remove();}});baseCopy(str).then(() => confirm()).catch(() => confirm("温馨提示", "复制失败"));
};

遇到的有意思的问题分析

除此之外,其它都是一些很好理解的基础代码,因此不需要讲解,这里讲一个让我觉得有意思的问题,也是在源码当中有备注,那就是被代理的对象会被污染,可以看到我们的 config.ts 里面写了 2 个最基础的表单配置对象:

export const defaultFormValue = {digit: 15,rule: "6 + 6 + 3",symbol: " ",symbolNumber: 1,inputNumber: 1,inputContent: ["621848063680370"],
};
export const baseDefaultFormValue = {digit: 15,rule: "6 + 6 + 3",symbol: " ",symbolNumber: 1,inputNumber: 1,inputContent: ["621848063680370"],
};

用来设置表单的初始值对象,我在监听用户修改输入框值之后去改变绑定的初始值,发现绑定的初始值被修改污染了,哪怕我采用了复制对象副本(使用 JSON 和展开运算符来复制),都会修改原始配置对象。我们的表单配置对象是这样的:

const formValue = ref({ ...defaultFormValue });

也就是说我对 formValue 的修改会影响到 defaultFormValue,这就让我感觉很奇怪,所以我想创建一个 baseDefaultFormValue 的方式去解决这个问题,这样我在重置表单数据的时候,就能够重置为最初始的数据,如下:

const handleResetClick = () => {formRef.value?.restoreValidation();// 不重新写一个defaultFormValue已经被污染了formValue.value = {...baseDefaultFormValue,};emit("on-submit", formValue.value);
};

这个问题,目前我还没有分析出原因来,如果有感兴趣的大佬,可以通过参考源码调试看看问题,我就没有时间去研究这个问题呢。

这些点是我觉得值得分析的地方,其它就没啥了,感谢阅读到这里,如果觉得有帮助可以点赞收藏,顺带可以帮我的项目点个 star,感激不尽。

另外给大家整理一部分大厂的面经和一些真题加上一些项目

转发本文+关注+私信【学习】或添加下方下助理即可领取更多资料!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/195377.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

关于开展人工智能专业人员“计算机视觉处理设计开发工程师”专项培训的通知

“人工智能技术与咨询”发布 工业与信息化部电子工业标准化研究院于2022年7月1日发布《人工智能从业技术人员要求》&#xff0c;现针对已发布标准于1月3日至7日在北京举办《自然语言与语音处理设计开发工程师》中级人才培养&#xff0c;下边是具体文件通知请大家查阅。行业人才…

对一个多维随机变量作为线性变换以后的协方差矩阵

假设是一个n维的随机变量&#xff0c;它的协方差矩阵 对做线性变换&#xff0c;其中是一个矩阵&#xff08;当然也可以是一个标量&#xff09;&#xff0c;的协方差矩阵 证明如下&#xff1a; 将代入&#xff0c;得

游戏配置表的导入使用

游戏配置表是游戏策划的标配&#xff0c;如下图&#xff1a; 那么程序怎么把把这张配置表导入使用&#xff1f; 1.首先&#xff0c;利用命令行把Excel格式的文件转化成Json格式&#xff1a; json-excel\json-excel json Tables\ Data\copy Data\CharacterDefine.txt ..\Cli…

构建满足流批数据质量监控用火山引擎DataLeap

更多技术交流、求职机会&#xff0c;欢迎关注字节跳动数据平台微信公众号&#xff0c;回复【1】进入官方交流群 面对今日头条、抖音等不同产品线的复杂数据质量场景&#xff0c;火山引擎 DataLeap 数据质量平台如何满足多样的需求&#xff1f;本文将介绍我们在弥合大数据场景下…

Apache Flink(六):Apache Flink快速入门 - Flink案例实现

🏡 个人主页:IT贫道_大数据OLAP体系技术栈,Apache Doris,Clickhouse 技术-CSDN博客 🚩 私聊博主:加入大数据技术讨论群聊,获取更多大数据资料。 🔔 博主个人B栈地址:豹哥教你大数据的个人空间-豹哥教你大数据个人主页-哔哩哔哩视频 目录

uniapp自定义进度条组件

目标效果 原型设计为这样的样式&#xff0c;但是现有的进度条都无法满足需求&#xff0c;于是编写组件实现。 设计引用格式为 <zLineProgress :total"15" :val"7" title"你好吗" />定义组件 <template><view style"hei…

Mars3d标绘的时候通过绑定单击事件,查询点击落点的图层类型

需求期望&#xff1a; 期望可以判断标绘点落下的位置是什么图层类型&#xff0c;例如是否是3dtitles模型&#xff0c;或者是gltf模型&#xff0c;或者是其他数据图层。 需求来源&#xff1a; 标绘点时&#xff0c;无法知道点落下的地方的图层类型 解决方案&#xff1a; ma…

C++ string类(1)—初始化、容量操作、迭代器

目录 前言 一、string类 二、初始化 1、无参或带参 2、用字符串变量初始化 3、用字符串初始化 4、指定数量字符 三、容量操作 1、size 2、push_back 3、append​编辑 4、运算符 5、reserve 6、resize 四、迭代器 1、正向迭代器 2、反向迭代器 3、const迭代器…

排序算法介绍(四)快速排序

0. 简介 快速排序&#xff08;Quick Sort&#xff09;是一种高效的排序算法&#xff0c;采用了分治的思想。它选择一个基准元素&#xff0c;通过一趟排序将待排序序列分割成独立的两部分&#xff0c;其中一部分的所有元素都比基准元素小&#xff0c;另一部分的所有元素都比基准…

iOS代码混淆工具

目录 引言 混淆效果 字符串加密 代码插入 其他混淆选项说明 总结 参考资料 &#x1f512; 这是一篇介绍iOS代码混淆工具的技术博客&#xff0c;旨在帮助开发者提高代码安全性。本工具来自于Github的混淆词库和代码&#xff0c;通过差异化处理和代码合并生成数亿种用于混淆…

【备忘干货】c/c++ (wasm)和js互相调用记录

c/c&#xff08;wasm&#xff09;和js互相调用记录 废话 :)准备工作&#xff1a;安装Emscripten初探&#xff1a;C(wasm)之hello world进一步探究&#xff1a;接口调用1.js调用c&#xff0c;一些基本类型的传递&#xff08;char*&#xff0c;int&#xff0c;float&#xff09;以…

安装Python以及pycharm

Pycharm是编辑器。相当于Word对文字进行编辑。 Python是解释器。讲代码翻译为计算机可以理解的指令。 1、安装Python 官网&#xff1a;Welcome to Python.org 打开的时候有点慢等待一会就好&#xff0c;点击下载&#xff0c;选择Windows版本 等待一会&#xff0c;可以看到如…

docker内容整理

docker内容整理 docker的安装 检查之前是否安装过docker&#xff0c;如果有使用yum remove docker卸载 [rootwoniu ~]# yum remove docker \ > docker-client \ > docker-client-latest \ > docker-common \ > docker-latest \ > docker-latest-logrotate \ &g…

行业分析:轻轨行业发展现状及市场投资前景

轻轨是城市轨道建设的一种重要形式&#xff0c;也是当今世界上发展最为迅猛的轨道交通形式。轻轨的机车重量和载客量要比一般列车小&#xff0c;因此叫做“轻轨”。 城市轻轨具有运量大、速度快、污染小、能耗少、准点运行、安全性高等优点。城市轻轨与地下铁道、城市铁路及其…

ICC2:如何创建多个core区,分别做power plan

我正在「拾陆楼」和朋友们讨论有趣的话题,你⼀起来吧? 拾陆楼知识星球入口 如下图,core区域(core row)仅需要存在两个地方,右上大的core区,以及ram上下。 这里需要进行两步操作,分别是create site array创建指定位置的core row,上图所示部分,第二步是创建pg region…

深入理解GMP模型

1、GMP模型的设计思想 1&#xff09;、GMP模型 GMP分别代表&#xff1a; G&#xff1a;goroutine&#xff0c;Go协程&#xff0c;是参与调度与执行的最小单位M&#xff1a;machine&#xff0c;系统级线程P&#xff1a;processor&#xff0c;包含了运行goroutine的资源&#…

Centos系列:Centos7下部署nginx(三种方式安装部署,图文结合超详细,适合初学者)

Centos7下部署nginx&#xff08;三种方式安装部署&#xff0c;图文结合超详细&#xff0c;适合初学者&#xff09; Centos7下部署nginx一. ngxin是什么二. nginx的作用正向代理和反向代理的区别 三. 安装部署安装环境1. yum安装配置nginx源启动nginx浏览器访问&#xff0c; IP:…

打印菱形图案C语言

C代码实现&#xff1a; #include <stdio.h> void printDiamond(int n) { int i, j, space n - 1; // 打印上半部分包括中间行 for (i 0; i < n; i) { // 打印空格 for (j 0; j < space; j) printf(" "); // 打印星号 for (j 1; j < 2 *…

Canvas鼠标画线

鼠标按下开始画线,鼠标移动根据鼠标的轨迹去画,鼠标抬起停止画线 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0">…

备忘录怎么传到电脑?备忘录手机电脑互传方法

对于那些记性不好的人来说&#xff0c;手机上的备忘录简直是个不可或缺的好帮手。可是有时候&#xff0c;我们在手机上记录的内容需要在电脑上查看&#xff0c;这时候该怎么办呢&#xff1f; 曾经&#xff0c;我也为备忘录的手机电脑互传问题头疼不已。手机上记录的事项&#…