首页
归档
关于
友人帐
Search
1
Mac OS 终端利器 iTerm2 + Oh My Zsh
13,380 阅读
2
前端 History 路由及 API 反向代理的 Nginx 配置
10,470 阅读
3
解决 Xcode Command Line Tools 错误或无法安装问题
5,695 阅读
4
Mac下右键使用VSCode打开项目
3,842 阅读
5
BrowserHistory刷新页面404问题
3,177 阅读
码上世界
内容分享
生活印记
其他
登录
Search
小小孩
累计撰写
93
篇文章
累计收到
179
条评论
首页
栏目
码上世界
内容分享
生活印记
其他
页面
归档
关于
友人帐
搜索到
93
篇与
小小孩
的结果
2020-08-28
H5 移动端开发经常遇到的问题
搜罗了一些 H5 移动端开发经常遇到的问题,来方便以后查阅!还会继续添加!1. 弹出数字键盘<!-- 有"#" "*"符号输入 --> <input type="tel" /> <!-- 纯数字 --> <input pattern="\d*" />安卓跟 IOS 的表现形式应该不一样,大家可以自己试试。当运用了正则 pattern 后,就不用关注 input 的类型了2. 调用系统的某些功能<!-- 拨号 --> <a href="tel:10086">打电话给: 10086</a> <!-- 发送短信 --> <a href="sms:10086">发短信给: 10086</a> <!-- 发送邮件 --> <a href="mailto:839626987@qq.com">发邮件给:839626987@qq.com</a> <!-- 选择照片或者拍摄照片 --> <input type="file" accept="image/*" /> <!-- 选择视频或者拍摄视频 --> <input type="file" accept="video/*" /> <!-- 多选 --> <input type="file" multiple />3. 打开原生应用<a href="weixin://">打开微信</a> <a href="alipays://">打开支付宝</a> <a href="alipays://platformapi/startapp?saId=10000007" >打开支付宝的扫一扫功能</a > <a href="alipays://platformapi/startapp?appId=60000002">打开支付宝的蚂蚁森林</a>这种方式叫做 URL Scheme,是一种协议,一般用来访问 APP 或者 APP 中的某个功能/页面(如唤醒 APP 后打开指定页面或者使用某些功能)😒URL Scheme 的基本格式如下:行为(应用的某个功能/页面) | scheme://[path][?query] | | 应用标识 功能需要的参数一般是由 APP 开发者自己定义,比如规定一些参数或者路径让其他开发者来访问,就像上面的例子 🍤注意事项唤醒 APP 的条件是你的手机已经安装了该 APP某些浏览器会禁用此协议,比如微信内部浏览器(除非开了白名单)4. 解决 active 伪类失效<body ontouchstart></body>给 body 注册一个空事件即可 😂5. 忽略自动识别<!-- 忽略浏览器自动识别数字为电话号码 --> <meta name="format-detection" content="telephone=no" /> <!-- 忽略浏览器自动识别邮箱账号 --> <meta name="format-detection" content="email=no" />当页面上的内容包含了手机号/邮箱等,会自动转换成可点击的链接 😁比如你有如下代码:但是有些浏览器会识别为手机,并且可以点击拨号。6. 解决 input 失焦后页面没有回弹一般出现在 IOS 设备中的微信内部浏览器,出现的条件为:页面高度过小聚焦时,页面需要往上移动的时候所以一般 input 在页面上方或者顶部都不会出现无法回弹 🤣解决办法为,在聚焦时,获取当前滚动条高度,然后失焦时,赋值之前获取的高度:<template> <input type="text" @focus="focus" @blur="blur" /> </template> <script> export default { data() { return { scrollTop: 0 }; }, methods: { focus() { this.scrollTop = document.scrollingElement.scrollTop; }, blur() { document.scrollingElement.scrollTo(0, this.scrollTop); } } }; </script>6. 禁止长按以上行为可以总结成这几个(每个手机以及浏览器的表现形式不一样):长按图片保存、长按选择文字、长按链接/手机号/邮箱时呼出菜单。想要禁止这些浏览器的默认行为,可以使用以下 CSS:// 禁止长按图片保存 img { -webkit-touch-callout: none; pointer-events: none; // 像微信浏览器还是无法禁止,加上这行样式即可 } // 禁止长按选择文字 div { -webkit-user-select: none; } // 禁止长按呼出菜单 div { -webkit-touch-callout: none; }7. 滑动不顺畅,粘手一般出现在 IOS 设备中,自定义盒子使用了 overflow: auto || scroll 后出现的情况。优化代码:div { -webkit-overflow-scrolling: touch; }8. 屏幕旋转为横屏时,字体大小会变具体出现的情况不明 😒,有时候有有时候没有,欢迎指出。优化代码:* { -webkit-text-size-adjust: 100%; }9. 最简单的 rem 自适应大家都知道,rem 的值是根据根元素的字体大小相对计算的,但是我们每个设备的大小不一样,所以根元素的字体大小要动态设置 😂html { font-size: calc(100vw / 3.75); } body { font-size: .14rem; }这是最简单的,稍微复杂的可以使用我正在使用的 rem.js10. 滑动穿透当你想在出现遮罩的时候,锁住用户的滚动行为,你可以这么做。假设 HTML 结构如下: 我是弹框 CSS 样式如下:.mask { position: fixed; top: 0; left: 0; display: flex; justify-content: center; align-items: center; width: 100%; height: 100%; background-color: rgba($color: #333, $alpha: 0.6); .content { padding: 20px; background-color: #fff; width: 300px; } }可以看到,当在遮罩上滑动的时候,是会穿透到父节点的,最简单的办法就是阻住默认行为:document.querySelector(".mask").addEventListener("touchmove", event => { event.preventDefault(); });如果在 vue 中,你可以这么写:<div class="mask" @touchumove.prevent></div> 如果.content 也有滚动条,那么只要阻止遮罩本身就行:document.querySelector(".mask").addEventListener("touchmove", event => { if (event.target.classList.contains("mask")) event.preventDefault(); });或者:<div class="mask" @touchumove.self.prevent></div> 这样,当出现遮罩的时候用户的滑动就会被锁住啦 👌
2020年08月28日
655 阅读
0 评论
1 点赞
2020-07-16
动图展示10大Git命令
作者: Lydia Hallie可视化
2020年07月16日
1,610 阅读
0 评论
0 点赞
2020-07-16
前端 History 路由及 API 反向代理的 Nginx 配置
underscores_in_headers on; location ~ ^/prod-api { rewrite ^/prod-api/(.*)$ /$1 break; proxy_pass http://*****.com; } location ^/file { proxy_pass http://*****.com; } location ~ / { try_files $uri $uri/ /index.html; } #if (!-e $request_filename) { # rewrite ^/(.*) /index.html last; # break; #}
2020年07月16日
10,470 阅读
0 评论
1 点赞
2020-06-01
DockerHub国内镜像设置加速服务
哪些 docker hub 镜像加速目前有许多镜像地址https://docker.mirrors.ustc.edu.cn/ (中国科学技术大学(LUG@USTC)的开源镜像)https://registry.docker-cn.com (docker 官方中国镜像)阿里云的容器镜像服务里也有专属加速器地址 可进 https://cr.console.aliyun.com/cn-hangzhou/instances/mirrors 查看,大致是 https://xxxxxxxx.mirror.aliyuncs.com我用的当中 属 中国科学技术大学(LUG@USTC)的开源镜像最快配置镜像加速Linux 新版的 Docker 使用镜像配置地址是 /etc/docker/daemon.json 但可能文件不存在sudo mkdir -p /etc/docker sudo tee /etc/docker/daemon.json <<-'EOF' { "registry-mirrors": ["https://docker.mirrors.ustc.edu.cn","https://registry.docker-cn.com"] } EOF sudo systemctl daemon-reload sudo systemctl restart docker这时再下 就快多了
2020年06月01日
931 阅读
0 评论
0 点赞
2020-05-29
号天扣地,无自律
说好的晚上少吃点减肥,可在意志在美食面前瞬间土崩瓦解。说好的晚上早睡,一趟床上就刷刷抖音熬到了无人的深夜。说好的周末在家好好学习,可时间就在游戏电影中悄然流逝。说好的要完成几个小目标,可都如同成了被拍死的蚊子尸横遍野。殊不知自己已经成了一个思想上的巨人,行动上的矮子,竟然可笑的为自己那么点努力沾沾自喜,自己依然不知天高地厚。显然已掉入自己给自己编制的陷阱,只会告诉自己“你很好,不怪你”。现在面临难题不是想着怎么解决,而是如何逃避。逃避小人,逃避尔虞我诈,逃避一切。曾经也曾昂扬斗志,激扬愤慨,立下很多 Flag ,现在却好像没有真正的努力奋斗过。正如法国古典文学作家佛朗哥所说:“我们所犯的过错,几乎都比用来掩饰的方法,更值得原谅。”,培养自律的生活方式,首要的功课之一就是破除找借口的倾向!自律并不仅对我们现在的身体有益,在几年后,我们会发现它对于我们在社会上的工作和生活也有很大的影响。因为当我们还是年轻时,犯了错误我们还有再来一次,从头开始的机会,可是在社会上我们就必须为自己的每一次失误或者错误负责而承担后果。时刻提醒自己,做一个自律的人。唯有自律方能践行,唯有践行方能立己。
2020年05月29日
1,036 阅读
2 评论
0 点赞
2020-05-01
Vue3 中的 Proxy API
Object.defineProperty 的一些弊端Vue2.x 中,实现数据的可响应,需要对 Object 和 Array 两种类型采用不同的处理方式。 Object 类型通过 Object.defineProperty 将属性转换成 getter/setter ,这个过程需要递归侦测所有的对象 key,来实现深度的侦测。为了感知 Array 的变化,对 Array 原型上几个改变数组自身的内容的方法做了拦截,虽然实现了对数组的可响应,但也存在一些问题。 同时,defineProperty 通过递归实现 getter/setter 也有一定的性能问题。更好的实现方式是通过 ES6 提供的 Proxy 。Proxy 的一些坑Proxy 具有更加强大的功能, 相比旧的 defineProperty ,Proxy 可以代理数组,并且提供了多个 traps(主要是 get 、 set ) ,可以实现诸多功能。但其中的一些比较容易被忽略的细节。trap 默认行为let data = { info: "info" }; let p = new Proxy(data, { get(target, key, receiver) { return target[key]; }, set(target, key, value, receiver) { console.log("set value"); target[key] = value; // ? } }); p.info = 123;通过 proxy 返回的对象 p 代理了对原始数据的操作,当对 p 设置时,便可以侦测到变化。但是这么写实际上是有问题, 当代理的对象数据是数组时,就会报错。let data = [1, 2]; let p = new Proxy(data, { get(target, key, receiver) { return target[key]; }, set(target, key, value, receiver) { console.log("set value"); target[key] = value; } }); p.push(3); // 报错将代码更改为:let data = [1, 2]; let p = new Proxy(data, { get(target, key, receiver) { return target[key]; }, set(target, key, value, receiver) { console.log("set value"); target[key] = value; return true; } }); p.push(3); // set value 打印 2 次实际上,当代理对象是数组,通过 push 操作,并不只是操作当前数据,push 操作还触发数组本身其他属性更改。let data = [1, 2]; let p = new Proxy(data, { get(target, key, receiver) { console.log("get value:", key); return target[key]; }, set(target, key, value, receiver) { console.log("set value:", key, value); target[key] = value; return true; } }); p.push(3); // get value: push // get value: length // set value: 2 3 // set value: length 3先看 set 操作,从打印输出可以看出,push 操作除了给数组的第 2 位下标设置值 3 ,还给数组的 length 值更改为 3。 同时这个操作还触发了 get 去获取 push 和 length 两个属性。我们可以通过 Reflect 来返回 trap 相应的默认行为,对于 set 操作相对简单,但是一些比较复杂的默认行为处理起来相对繁琐得多,Reflect 的作用就显现出来了。let data = [1, 2]; let p = new Proxy(data, { get(target, key, receiver) { console.log("get value:", key); return Reflect.get(target, key, receiver); }, set(target, key, value, receiver) { console.log("set value:", key, value); return Reflect.set(target, key, value, receiver); } }); p.push(3); // get value: push // get value: length // set value: 2 3 // set value: length 3相比自己处理 set 的默认行为,Reflect 就方便得多。多次触发 set / get当代理对象是数组时,push 操作会触发多次 set 执行,同时,也引发 get 操作,这点非常重要,vue3 就很好的使用了这点。 我们可以从另一个例子来看这个操作:let data = [1, 2, 3]; let p = new Proxy(data, { get(target, key, receiver) { console.log("get value:", key); return Reflect.get(target, key, receiver); }, set(target, key, value, receiver) { console.log("set value:", key, value); return Reflect.set(target, key, value, receiver); } }); p.unshift("a"); // get value: unshift // get value: length // get value: 2 // set value: 3 3 // get value: 1 // set value: 2 2 // get value: 0 // set value: 1 1 // set value: 0 a // set value: length 4可以看到,在对数组做 unshift 操作时,会多次触发 get 和 set 。 仔细观察输出,不难看出,get 先拿数组最末位下标,开辟新的下标 3 存放原有的末位数值,然后再将原数值都往后挪,将 0 下标设置为了 unshift 的值 a ,由此引发了多次 set 操作。而这对于 通知外部操作 显然是不利,我们假设 set 中的 console 是触发外界渲染的 render 函数,那么这个 unshift 操作会引发 多次 render 。我们后面会讲述如何解决相应的这个问题,继续。proxy 只能代理一层let data = { foo: "foo", bar: { key: 1 }, ary: ["a", "b"] }; let p = new Proxy(data, { get(target, key, receiver) { console.log("get value:", key); return Reflect.get(target, key, receiver); }, set(target, key, value, receiver) { console.log("set value:", key, value); return Reflect.set(target, key, value, receiver); } }); p.bar.key = 2; // get value: bar执行代码,可以看到并没有触发 set 的输出,反而是触发了 get ,因为 set 的过程中访问了 bar 这个属性。 由此可见,proxy 代理的对象只能代理到第一层,而对象内部的深度侦测,是需要开发者自己实现的。同样的,对于对象内部的数组也是一样。p.ary.push("c"); // get value: ary同样只走了 get 操作,set 并不能感知到。我们注意到 get/set 还有一个参数:receiver ,对于 receiver ,其实接收的是一个代理对象:let data = { a: { b: { c: 1 } } }; let p = new Proxy(data, { get(target, key, receiver) { console.log(receiver); const res = Reflect.get(target, key, receiver); return res; }, set(target, key, value, receiver) { return Reflect.set(target, key, value, receiver); } }); // Proxy {a: {…}}这里 receiver 输出的是当前代理对象,注意,这是一个已经代理后的对象。let data = { a: { b: { c: 1 } } }; let p = new Proxy(data, { get(target, key, receiver) { const res = Reflect.get(target, key, receiver); console.log(res); return res; }, set(target, key, value, receiver) { return Reflect.set(target, key, value, receiver); } }); // {b: {c: 1} }当我们尝试输出 Reflect.get 返回的值,会发现,当代理的对象是多层结构时,Reflect.get 会返回对象的内层结构。Vue3 如何解决 proxy 中的细节问题Vue3 项目结构采用了 lerna 做 monorepo 风格的代码管理,目前比较多的开源项目切换到了 monorepo 的模式, 比较显著的特征是项目中会有个 packages/ 的文件夹。Vue3 对功能做了很好的模块划分,同时使用 TS 。我们直接在 packages 中找到响应式数据的模块:Vue3 中的 reactivity其中,reactive.ts 文件提供了 reactive 函数,该函数是实现响应式的核心。 同时这个函数也挂载在了全局的 Vue 对象上。这里对源代码做一点程度的简化:const rawToReactive = new WeakMap(); const reactiveToRaw = new WeakMap(); // utils function isObject(val) { return typeof val === "object"; } function hasOwn(val, key) { const hasOwnProperty = Object.prototype.hasOwnProperty; return hasOwnProperty.call(val, key); } // traps function createGetter() { return function get(target, key, receiver) { const res = Reflect.get(target, key, receiver); return isObject(res) ? reactive(res) : res; }; } function set(target, key, val, receiver) { const hadKey = hasOwn(target, key); val = reactiveToRaw.get(val) || val; const result = Reflect.set(target, key, val, receiver); const oldValue = target[key]; if (!hadKey) { console.log("trigger ..."); } else if (val !== oldValue) { console.log("trigger ..."); } return result; } // handler const mutableHandlers = { get: createGetter(), set: set }; // entry function reactive(target) { return createReactiveObject( target, rawToReactive, reactiveToRaw, mutableHandlers ); } function createReactiveObject(target, toProxy, toRaw, baseHandlers) { let observed = toProxy.get(target); // 原数据已经有相应的可响应数据, 返回可响应数据 if (observed !== void 0) { return observed; } // 原数据已经是可响应数据 if (toRaw.has(target)) { return target; } observed = new Proxy(target, baseHandlers); toProxy.set(target, observed); toRaw.set(observed, target); return observed; }rawToReactive 和 reactiveToRaw 是两个弱引用的 Map 结构,这两个 Map 用来保存 原始数据 和 可响应数据 ,在函数 createReactiveObject 中,toProxy和 toRaw 传入的便是这两个 Map 。我们可以通过它们,找到任何代理过的数据是否存在,以及通过代理数据找到原始的数据。除了保存了代理的数据和原始数据,createReactiveObject 函数仅仅是返回了 new Proxy 代理后的对象。 重点在 new Proxy中传入的 handler 参数 baseHandlers。还记得前面提到的 Proxy 实现数据侦测的细节问题吧,我们尝试输入:let data = { foo: "foo", ary: [1, 2] }; let r = reactive(data); r.ary.push(3);打印结果:可以看到打印输出了一次 trigger ...问题一:如何做到深度的侦测数据的 ?深度侦测数据是通过 createGetter 函数实现的,前面提到,当对多层级的对象操作时,set 并不能感知到,但是 get 会触发, 于此同时,利用 Reflect.get() 返回的“多层级对象中内层” ,再对“内层数据”做一次代理。function createGetter() { return function get(target, key, receiver) { const res = Reflect.get(target, key, receiver); return isObject(res) ? reactive(res) : res; }; }可以看到这里判断了 Reflect 返回的数据是否还是对象,如果是对象,则再走一次 proxy,从而获得了对对象内部的侦测。并且,每一次的 proxy 数据,都会保存在 Map 中,访问时会直接从中查找,从而提高性能。当我们打印代理后的对象时:可以看到这个代理后的对象内层并没有代理的标志,这里仅仅是代理外层对象。输出其中一个存储代理数据的 rawToReactiv :对于内层 ary: [1, 2] 的代理,已经被存储在了 rawToReactive 中。由此实现了深度的数据侦测。问题二:如何避免多次 trigger ?function hasOwn(val, key) { const hasOwnProperty = Object.prototype.hasOwnProperty; return hasOwnProperty.call(val, key); } function set(target, key, val, receiver) { console.log(target, key, val); const hadKey = hasOwn(target, key); val = reactiveToRaw.get(val) || val; const result = Reflect.set(target, key, val, receiver); const oldValue = target[key]; if (!hadKey) { console.log("trigger ... is a add OperationType"); } else if (val !== oldValue) { console.log("trigger ... is a set OperationType"); } return result; }关于多次trigger 的问题,vue 处理得很巧妙。在 set 函数中 hasOwn 前打印 console.log(target, key, val) 。let data = ["a", "b"]; let r = reactive(data); r.push("c");r.push('c') 会触发 set 执行两次,一次是值本身 'c' ,一次是 length 属性设置设置值 'c' 时,传入的新增索引 key 为 2,target 是原始的代理对象 ['a', 'c'] ,hasOwn(target, key) 显然返回 false ,这是一个新增的操作,此时可以执行 trigger ... is a add OperationType当传入 key 为 length 时,hasOwn(target, key) ,length 是自身属性,返回 true,此时判断 val !== oldValue, val 是 3, 而 oldValue 即为 target['length'] 也是 3,此时不执行 trigger 输出语句。所以通过 判断 key 是否为 target 自身属性,以及设置 val 是否跟 target[key]相等 可以确定 trigger 的类型,并且避免多余的 trigger总结Vue3 并非简单的通过 Proxy 来递归侦测数据, 而是通过 get 操作来实现内部数据的代理,并且结合 WeakMap 来对数据保存,这将大大提高响应式数据的性能。
2020年05月01日
751 阅读
0 评论
0 点赞
2020-04-04
深切哀悼
为表达全国各族人民对抗击新冠肺炎疫情斗争牺牲烈士和逝世同胞的深切哀悼,国务院今天发布公告,决定2020年4月4日举行全国性哀悼活动。在此期间,全国和驻外使领馆下半旗志哀,全国停止公共娱乐活动。4月4日10时起,全国人民默哀3分钟,汽车、火车、舰船鸣笛,防空警报鸣响。据此,本网站在2020-04-04 这天,所有页面也将变灰来响应哀吊。
2020年04月04日
954 阅读
0 评论
0 点赞
2020-04-01
腾讯Ubuntu云服务器环境初始配置
一、配置 root 登陆腾讯 Ubuntu 云服务器默认用户ubuntu ,又懒得 每次都输 sudo ,所以加上 root 用户1. 设置 root 密码先使用 ubuntu 用户 ssh 登录腾讯云,然后执行命令sudo passwd root2. 修改 ssh 登录的配置/etc/ssh/sshd_config文件,修改为允许 root 登录,可以执行命令sudo vim /etc/ssh/sshd_config注意:这里的 sudo 前缀不可少,否则接下来的修改无法保存。进入 vim 编辑,用方向键向下滚动找到 PermitRootLogin 这项按下 insert 键进入插入模式,将 PermitRootLogin 后面的 prohibit-password 改为 yes,再按下 Esc 键,然后依次按下:键(英文冒号键)、w 键和 q 键,最后按下回车键,保存修改成功。3. 重启 ssh 服务sudo service ssh restart使刚才的 ssh 配置的修改生效,执行命令使用 root 用户登录使用root用户登录 必要的话 可以删除ubuntu 用户删除命令:userdel -r ubuntu二、安装 docker 及 docker-composedocker最方便的方法是使用官方脚本并使用阿里云镜像安装curl -fsSL https://get.docker.com | bash -s docker --mirror Aliyun如果您想将 Docker 用作非 root 用户,您现在应该考虑将您的用户添加到“docker”组,例如:可以自行添加用户 (尽量避免使用docker作为用户名)useradd your-usersudo usermod -aG docker your-user请记得注销并重新登录才能生效!docker-compose1. 运行脚本sudo curl -L "https://github.com/docker/compose/releases/download/1.24.0/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose其中 1.24.0 可以切换你想安装的版本2. 对二进制文件应用可执行权限:sudo chmod +x /usr/local/bin/docker-compose注意:如果 docker-compose 安装后命令失败,请检查您的路径。您还可以创建/usr/bin 路径中的符号链接或任何其他目录。 例如:sudo ln -s /usr/local/bin/docker-compose /usr/bin/docker-compose3. 测试安装。docker-compose --version4. 卸载:sudo rm /usr/local/bin/docker-compose三、安装 Nginx因为是ubuntu 系统 不像 centos ,ubuntu 的包都比较新 所以直接用包管理器安装apt-get update apt-get install nginx完成之后 nginx -v 打印出版本号就说明安装成功了四、安装 Node.js因为每个项目可能依赖的 Node 版本不同 这里选用了 nvm 来作为 node 的包管理器 ,它可以方便的在同一台设备上进行多个 node 版本之间切换curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.34.0/install.sh | bash注意:在 Linux 上,运行安装脚本后,如果 nvm: command not found 在键入后收到或看不到终端的反馈:command -v nvm只需关闭当前终端,打开新终端,然后再次尝试 nvm -v验证。验证成功后就可以安装node.js了nvm 用法要下载,编译和安装最新版本的节点,请执行以下操作:nvm install node # node是最新版本的别名要安装特定版本的节点:nvm install 6.14.4 # 10.10.0,8.9.1 等您可以使用 ls-remote 列出可用版本:nvm ls-remote然后在任何新的 shell 中只使用已安装的版本:五、安装 MongoDB既然我们安装了 docker 我们就用 docker 安装 MongoDB1. 拉取镜像 docker pull mongo # 直接拉去默认tag 为latest 的mongo:latest 镜像2. 使用 mongo 镜像docker run --name mongo -p 27017:27017 -v /mongo/db:/data/db -d mongo命令说明:--name 命名容器名字-p 27017:27017 :将容器的 27017 端口映射到主机的 27017 端口-v /mongo/db:/data/db :将主机中/mongo/db 挂载到容器的/data/db,作为 mongo 数据存储目录3. 查看容器启动情况docker ps可看到 已经运行成功了使用 mongo 镜像执行 mongo 命令连接到刚启动的容器docker run -it mongo:latest mongo六、安装 MongoDB跟安装 MongoDB 一样docker pull mysql:5.6 mkdir -p /mysql/data /mysql/logs /mysql/conf docker run -p 3306:3306 --name mymysql \ -v /mysql/conf:/etc/mysql/conf.d \ -v /mysql/logs:/logs \ -v /mysql/data:/var/lib/mysql \ -e MYSQL_ROOT_PASSWORD=123456 \ -d mysql:5.6命令说明:-p 3306:3306 #将容器的 3306 端口映射到主机的 3306 端口。-v /mysql/conf:/etc/mysql/conf.d #将主机当前目录下的 conf/my.cnf 挂载到容器的 /etc/mysql/my.cnf。-v /mysql/logs:/logs #将主机当前目录下的 logs 目录挂载到容器的 /logs。-v /mysql/data:/var/lib/mysql #将主机当前目录下的 data 目录挂载到容器的 /var/lib/mysql 。-e MYSQL_ROOT_PASSWORD=123456 #初始化 root 用户的密码。查看容器启动情况docker ps 注意 : mysql 5.7 及以上版本 映射的配置文件目录可能有所不同 详细可取 Docker Hub 查看
2020年04月01日
483 阅读
0 评论
0 点赞
2020-03-25
JS判断是否是真实移动设备
要想判断真实的移动设备打开,而不是电脑模拟的移动设备打开,肯定不能通过userAgent判断,因为电脑开发工具可修改。 想到了Navigator的只读属性maxTouchPoints是返回当前设备支持的最大同时触摸接触点数。 一般电脑没有触摸接触点数,而电脑模拟的移动设备也只有一个,而真实的移动设备却是 3-4个,以此来判断是否是真实的移动设备。直接上代码const checkPhone = () => navigator.platform.indexOf('Mac') === navigator.platform.indexOf('Win') && navigator.maxTouchPoints && 2 < navigator.maxTouchPoints
2020年03月25日
2,005 阅读
4 评论
0 点赞
2020-03-19
惊雷?我惊了!!!
2020-04-15 更新哈哈 惊雷被 Diss 了,歌词抄袭小说,伴奏也抄袭,果然大部分人的三观还是好的!最近喊麦好像又火了,一首惊雷,我给惊了!!!抖音刷到直接长按不喜欢一直不明白,喊麦咋火起来的,一直没弄懂。 看看《惊雷》歌词惊雷这通天修为天塌地陷我紫金锤紫电说玄真火焰九天悬剑惊天变 在我的印象中 喊麦就全是惊天变,斗帝王,已成仙,饮酒醉,成双对,再加双击评论666 能不能有点实际的记得有个朋友笑称喊麦就是快板儿清唱加了bgm ,我只想说 无论是快板还是RAP歌词都会有我一个明显的主题,或地区传统文化或咏情颂爱,而这个喊麦的主题是玄幻修仙小说?抽烟只抽炫赫门? 我也不是排斥这种所谓的音乐形式,可是通篇歌词看完 我是这个表情 我就想问这喊麦到底是什么玩意儿,要说这词吧,除了押韵还有啥亮点,什么玄真火焰,紫金锤 还有之前的一人饮酒醉?幻想着自己当英雄当神仙呢?能不能不要活在自己世界里,出去走走,看看祖国大好河山,认清现实社会!我感觉,喊麦和直播有很大关系,是不是YY直播火了,但是直播没有代表的东西,那么缺少这个东西就得整一个,好了记得YY直播喊麦的还挺多! 这么一说突然想起以前看到直播中的一句兄弟赴汤蹈火,战沙场!为兄弟倾家荡产在所不辞!算了,我还是笑笑走开吧!
2020年03月19日
1,095 阅读
0 评论
0 点赞
1
...
5
6
7
...
10