程志辉博客 - 一个伪文艺青年
贵在坚持,难在坚持,成在坚持!
程志辉

功能

禁止IP直接访问、防止域名恶意解析

简单点:不设置这个通过IP可以直接访问,同时当别人的域名解析到你的域名时可以通过他的域名看到你服务器配置了网站的内容

老早就知道这个问题,但是由于不是专业运维不大懂专业术语叫啥,最近公司碰到这个问题,能肯定是nginx配置问题,最后查阅后了解这个叫空主机头

实现

#关闭未绑定的域名-http
    server {
        listen 80 default_server;
        server_name _ ;
        return 301 https://www.qqzmly.com/;
    }

    #关闭未绑定的域名-https
    server {
        listen 443 default_server;
        server_name _ ;
        ssl on;
        ssl_certificate cert/1_www.qqzmly.com_bundle.crt;
        ssl_certificate_key cert/2_www.qqzmly.com.key;
        return 301 https://www.qqzmly.com/;
    }

实现过程中发现 443https这块配置 需要带上ssl上面代码演示的三条

Nginx下 return 和 rewrite在 301重定向上的区别

唯一区别:正则匹配的性能区别

rewrite ^/(.*)$ https://example.com/$1;
rewrite ^ https://example.com$request_uri? permanent;
return 301 https://example.com$request_uri;

第一种 rewrite 写法是抓取所有的 URI 再减去开头第一个 / (反斜线)。

第二种写法用了$request_uri 省去了减去开头第一个反斜线的过程,正则匹配上性能更优。但仍不如第三种写法,因为 rewrite 有很多写法和规则,执行到最后 nginx 才知道这是一个 301 永久重定向。

第三种则直接 return 301 + $request_uri,直接告诉 nginx 这是个 301重定向,直接抓取指定URI。

Nginx下 return 和 rewrite在 301重定向上的区别 301更优雅

引用: https://blog.csdn.net/lijun_work/article/details/108257956

2022年02月17日
  • evve 学到了~ 感谢分享
  • inkss 可以这样写: ```conf server { server_name _; listen 80 default_server; listen 443 ssl http2 default_server; ssl_reject_handshake on; return 444; } ```
  • quange 回复 inkss 感谢分享
  • 姜辰Jcs.Moe 我在想你会怎么弄,结果最后发现是直接301到自己站点了,这样也挺好的。 我一般也是301到www的梦幻辰风。
程志辉

展示效果

解决方法的原理:监听屏幕视口大小如果'resize',发生改变了,就获取图片的高度height,然后渲染到页面

ElementUI 地址: https://element.eleme.cn/#/zh-CN/component/carousel

方法解析

1.窗口第一次打开的时候加载执行 imgLoad()方法,第一次加载时获取图片在窗口中的高度,然后渲染到页面中去。

2.接着通过addEventListenner()方法监听视口是否发生改变,如果发生改变,重新调用imgLoad()方法渲染数据到页面,这样图片高度就可以随视口改变发生改变,适应各种大小屏幕。

完整代码


<!DOCTYPE html>
<html>
 
<head>
    <meta charset="UTF-8">
    <!-- 引入ElementUI  CDN -->
    <link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css">
    <title>ElementUI 走马灯自适应</title>
</head>
<style type="text/css">
  
</style>
 
<body>
    <div id="app">
        <el-carousel :height="bannerHeight+'px'">
            <el-carousel-item v-for="item in banner" :key="item">
                <el-row :gutter="12">
                    <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" style="height:340px;margin-bottom: 20px;">
                            <img  ref="bannerHeight" :src="item" alt="" @load="imgLoad" style="width: 100%">
                    </el-col>
                </el-row>
            </el-carousel-item>
        </el-carousel>
 
        <div id="test-div" style="border: 5px solid red;background-color: antiquewhite;">当前宽度:{{bannerwidth}}<br/>当前高度:{{bannerHeight}}</div>
 
    </div>
 
</body>
<!-- 引入vue组件库 -->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.min.js"></script>
<!-- 引入ElementUI组件库 -->
<script src="https://unpkg.com/element-ui/lib/index.js"></script>
<script>
    //注册使用vue
    var Vue = window.Vue;
    var app = new Vue({
        el: '#app',
        data() {
            return {
                bannerHeight:"",
                bannerwidth:"",
                banner:[
                        "https://cdn1.qqzmly.com/usr/uploads/2022/01/2888890086.jpg",
                        "https://cdn1.qqzmly.com/usr/uploads/2022/01/1900941580.jpg",
                        "https://cdn1.qqzmly.com/usr/uploads/2022/01/1639849891.jpg"
                    ]
            }
        },
        mounted(){
            this.imgLoad();
            window.addEventListener('resize',() => {
                this.bannerHeight=this.$refs.bannerHeight[0].height;
                this.imgLoad();
            },false)
        },
        methods: {
            imgLoad(){
                this.$nextTick(()=>{
                    this.bannerHeight=this.$refs.bannerHeight[0].height;
                    console.log(this.$refs.bannerHeight[0].height);
                     // document.getElementsByClassName拿到的是数组并非某一个对象
                    var testH=document.getElementById("test-div");
                    testH.style.height= this.bannerHeight+"px";

                    this.bannerwidth = document.body.clientWidth
                })
            }
        }
 
    })
 
</script>
 
</html>

原文链接:https://blog.csdn.net/qq_40976321/article/details/104513316

2022年01月14日
  • 远山笔记 清晰明了,学到了
  • test 测试一下评论
  • Lvtu 在下雪天更新了一篇,真不容易!哈哈~~
  • 程志辉 作者 回复 Lvtu 刚好工作碰到的问题,就记录了一下(好久都没更新博客了,感谢来访
程志辉

方法一

[...new Set(test)];

方法二

Array.from()
  
const test = ['q', 'w', 'e', 'q', 'u', 'p']
Array.from(new Set(test))

方法三

function unique(arr) {
    const res = new Map();
    return arr.filter((a) => !res.has(a) && res.set(a, 1))
}

ES5

  1. 创建一个新的空数组,用来存放去重后的新数组.
  2. 利用for循环循环遍历需要去重的数组.
  3. 利用indexOf()方法查询遍历出的数组在新数组中是否出现,如果出现:则继续遍历数组,如未出现:则利用push方法添加到新数组中.
  4. 原数组循环遍历完成后,组建一个已经去除重复的新数组.
var arr = [1,3,4,5,6,7,4,3,2,4,5,6,7,3,2];
  function find(){
    var newArr = [];
    for (var i = 0; i < arr.length; i++) {
      if (newArr.indexOf(arr[i]) == -1 ) {
        newArr.push(arr[i]);
      }
    }
    document.write(newArr);
  }
  find(arr);

上面是最近面试碰到的一些问题,写在博客记录一下。

过阵子就入职了,但是还不会小程序,这几天在恶补,免得难堪。

小程序单行/多行 文本溢出解决方案。

display: block;
/* 单行文本溢出, 省略号代替 */
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;


/* 多行文本溢出 省略号代替 */
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;

diff 算法

diff 算法是一种通过同层的树节点进行比较的高效算法,避免了对树进行逐层搜索遍历,所以时间复杂度只有 O(n)。diff 算法的在很多场景下都有应用,例如在 vue 虚拟 dom 渲染成真实 dom 的新旧 VNode 节点比较更新时,就用到了该算法。diff 算法有两个比较显著的特点:

比较只会在同层级进行, 不会跨层级比较。

在 diff 比较的过程中,循环从两边向中间收拢。

参照:https://www.infoq.cn/article/udlcpkh4iqb0cr5wgy7f

封装

1.封装功能函数
1)功能点要明确
2)函数内部保留固定的代码(静态代码)
3)将动态的代码抽取出来,由使用者提供最终的数据,以形参的形式提取
4)一个良好的功能函数应该要设置形参的默认值 (ES6直接设置形参里 ES5函数体IF判断
2.封装功能组件
1)功能点要明确
2)组件内部应该保留静态代码
3)将动态的数据提取成props,由使用者提供最终的数据
4)一个良好的组件应该设置组件props数据的必要性以及数据类型

2021年11月14日
程志辉

大家好,好久没写博客了,今天兴致不错,就来说说JQuery中eq()与get()方法的区别!

下来我们就开门见山吧,相信大家在工作中经常会用到这两个方法吧,那么他们的区别是什么了?

众所周知,eq()方法返回的是一个JQuery对象,也就是[object Object];

​ get()方法返回的是DOM对象组成的数组,也就是[object HTMLLIElement];

我们用一个例子说明一下:

首先引入JQuery库文件,

html

<body>
<ul id="ul">
        <li>item1</li>
        <li>item2</li>
        <li>item3</li>
    </ul>
<input type="button" value="click" id="b1">
</body>

  js

<script>
$("#b1").on("click",function(){
     var $obj  =  $("#ul li");
     $obj.eq(1).css("color","yellow");
     $obj.get(2).css("color","red");
})
</script>

  此时,点击按钮第二个li,即item2字体变为黄色,但是item3没有变为红色,且报如下错误:

报错的意思是,$obj没有get()方法,因为它是一个DOM对象组成的数组,它是没有get()方法,那么我们怎样把它变为JQuery对象了?

只需将$obj.get(2)改为$($obj.get(2))即可,

<script>
$("#b1").on("click",function(){
     var $obj  =  $("#ul li");
     $obj.eq(1).css("color","yellow");
     $($obj.get(2)).css("color","red");
})
</script>

  

关于JQuery对象与DOM对象的转换可以参考http://blog.csdn.net/jueshengtianya/article/details/8823091

再次点击按钮时,就会呈现如下的画面:

验证完毕,经过这个例子相信大家对于eq()与get()方法会有所了解了。

最后在来个扩展吧,还是基于上面的html

<script>
$("#b1").on("click",function(){
      var $obj = $("#ul li");
      var obj1 = $obj.get(1);
      var obj2 = $obj[1];
      if(obj===obj1){
            alert(111);
        }else{
            alert(222);
        }
})
</script>

  

大家可以猜猜看,弹出那个了?

经过本人验证弹出的是111,那么可以得出一个结论:$obj.get(1)和$obj[1],在这里可以互相替换使用。

以上是个人见解,有不到之处还望大家指正。

原链接:http://www.cnblogs.com/sheshou/p/5430381.html

2021年11月14日
程志辉

Git 仓库中的提交记录保存的是你的目录下所有文件的快照,就像是把整个目录复制,然后再粘贴一样,但比复制粘贴优雅许多!

Git 希望提交记录尽可能地轻量,因此在你每次进行提交时,它并不会盲目地复制整个目录。条件允许的情况下,它会将当前版本与仓库中的上一个版本进行对比,并把所有的差异打包到一起作为一个提交记录。

  快照技术主要是在操作系统以及存储技术上实现的一种记录某一时间系统状态的技术。近来,Oracle等数据库厂家以及Vmware等虚拟化产品也把这种技术引入各自的数据保护当中。

四个工作区域

工作目录(Working Directory)、暂存区(Stage/Index)、资源库(Repository或Git Directory)、git仓库(Remote Directory)。文件在这四个区域之间的转换关系如下:

Workspace: 工作区,就是你平时存放项目代码的地方

Index / Stage: 暂存区,用于临时存放你的改动,事实上它只是一个文件,保存即将提交到文件列表信息

Repository: 仓库区(或版本库),就是安全存放数据的位置,这里面有你提交到所有版本的数据。其中HEAD指向最新放入仓库的版本

Remote: 远程仓库,托管代码的服务器,可以简单的认为是你项目组中的一台电脑用于远程数据交换

常见使用

提交到版本库 git commit

创建分支 git branch newBranch

切换分支 git checkout newBranch

创建并切换分支 git checkout -b newBranch

多分支合并 git merge XXX 当前分支与XXX分支合并

第二种合并分支的方法是 git rebase。Rebase 实际上就是取出一系列的提交记录,“复制”它们,然后在另外一个地方逐个的放下去。

Rebase 的优势就是可以创造更线性的提交历史,这听上去有些难以理解。如果只允许使用 Rebase 的话,代码库的提交历史将会变得异常清晰。

合并分支 git rebase XXX

如果想看 HEAD 指向,可以通过 cat .git/HEAD

切换到父节点 git check HEAD^

如果你想在提交树中向上移动很多步的话,敲那么多 ^ 貌似也挺烦人的,Git 当然也考虑到了这一点,于是又引入了操作符 ~。

该操作符后面可以跟一个数字(可选,不跟数字时与 ^ 相同,向上移动一次),指定向上移动多少次。咱们还是通过实际操作看一下吧

我使用相对引用最多的就是移动分支。可以直接使用 -f 选项让分支指向另一个提交。例如:

git branch -f main HEAD~3

虽然在你的本地分支中使用 git reset 很方便,但是这种“改写历史”的方法对大家一起使用的远程分支是无效的哦!

为了撤销更改并分享给别人,我们需要使用 git revert。

git revert HEAD 撤销前一次 commit

git revert HEAD^ 撤销前前一次 commit

git远程仓库

克隆一个远程仓库 git clone

git fetch 做了些什么

git fetch 完成了仅有的但是很重要的两步:

从远程仓库下载本地仓库中缺失的提交记录
更新远程分支指针(如 o/main)
git fetch 实际上将本地仓库中的远程分支更新成了远程仓库相应分支最新的状态。

如果你还记得上一节课程中我们说过的,远程分支反映了远程仓库在你最后一次与它通信时的状态,git fetch 就是你与远程仓库通信的方式了!希望我说的够明白了,你已经了解 git fetch 与远程分支之间的关系了吧。

git fetch 通常通过互联网(使用 http:// 或 git:// 协议) 与远程仓库通信。

git pull 就是 git fetch 和 git merge 的缩写!

下载 git pull

上传 git push

git push 不带任何参数时的行为与 Git 的一个名为 push.default 的配置有关。它的默认值取决于你正使用的 Git 的版本,但是在教程中我们使用的是 upstream。 这没什么太大的影响,但是在你的项目中进行推送之前,最好检查一下这个配置。

还没写完

推荐一个网站https://learngitbranching.js.org/?locale=zh_CN

2021年11月13日
程志辉

人人学急救,急救为人人

下面这个是错误示范哈,一看就会,一学就废。

最后多练习+老师批评指正 才勉勉强强合格

很多地方都得多加练习,比如上面捏鼻子,结果都没注意到别人的眼睛

所以也算是勉勉强强入个门,日常生活中得多加练习!!!

赠人玫瑰,手有余香!

2021年11月04日
程志辉

组了把机械键盘,第一次用机械键盘~CIY68+Box红轴+光头反马里奥键帽≈220¥

喜欢的配色,喜欢的布局,拿出去应该也很轻便满足了~(感觉还挺便宜

她考研,我就业,周末附近溜达溜达

手机前摄拍照总会自动美颜,不过我还是喜欢没P过的

国庆到处转了转,走了趟武汉长江大桥好像也不是那么长

看到自己的大肚子,胖的让人心疼

孩子路上慢点走~
你一定要吃三餐啊!!!

每次回家都一定要去看看外婆,因为这是唯一的长辈了。

想了想还缺一张我和她的合影,下次回去补上~~

没啥钱,每次带的都是能力范围内外婆喜欢的东西,上次带瓜子,后来发现几个月的时间外婆的牙齿掉光了,吃不了瓜子。这次带的麦片,外婆早上或者饿的时候可以泡着垫垫肚子。

跑了场接力马拉松,女朋友说是第一次看这种比赛。不过这次的赛事组织方一般般,跑步不能丢。

想跑汉马,但是连续几年都没中签。

记记流水账,博客总不能丢吧?前几天参加校招面试,有家公司培养Java和C++方向的工程师,看样子是对我这5年的博客和国家奖学金感兴趣,不过后来想了下我还是想从事前端。

菜鸡的技术,还是得继续练练,最近学了thinkphp后端也算是有一门语言做支撑了。

2021年10月21日
  • 学心论文查重 郎才女貌,祝永结同心,白头偕老!
  • Mr.Chou 这键盘晚上敲打起来会声音大不?
  • 程志辉 作者 回复 Mr.Chou 我用的box红,算是入门感觉线性轴声音还好。段落轴会大一些。晚上还好,不过机械键盘多少还是有些声音的。介意声音可以试试box静音红还有金粉轴啊快银轴啊等等,可以买一两个敲击试试
  • wys 领证没有啊?看得人好羡慕~~ 我那个CRM就是用thinkphp框架做的,只是当时的PHP版本有点老了,还没更新。
  • 程志辉 作者 回复 wys 哈哈,谢谢来访,还在读书早着呢~tp我暂时就想停留在用的层面。
  • 大致 瓦里奥与有荣焉。
  • 程志辉 作者 回复 大致 哈哈,谢谢来访,感觉这个配色蛮好看的~
  • 肖小帅 卧槽 这玩意还可以组装 还这么好看
  • 程志辉 作者 回复 肖小帅 嘻嘻,小帅也可以耍耍感觉价格不贵确实好看
  • 查看更多...
程志辉

在 CORS 机制中,客户端将请求分为了两种:简单请求和非简单请求;当请求为非简单请求时,就会触发浏览器发送预检请求,这是浏览器的行为。

预检请求会向服务器确认跨域是否允许,服务返回的响应头里有对应字段Access-Control-Allow-Origin来给浏览器判断:如果允许,浏览器紧接着发送实际请求;不允许,报错并禁止客户端脚本读取响应相关的任何东西。

入口文件index.php

//处理跨域预检请求
if($_SERVER['REQUEST_METHOD'] == 'OPTIONS'){
    //允许的源域名
    header("Access-Control-Allow-Origin: *");
    //允许的请求头信息
    header("Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept, Authorization,token");
    //允许的请求类型
    header('Access-Control-Allow-Methods: GET, POST, PUT,DELETE,OPTIONS,PATCH');
    exit;
}

控制器方法需要继承的 控制器方法

//允许的源域名
header("Access-Control-Allow-Origin: *");
//允许的请求头信息
header("Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept, Authorization,token");
//允许的请求类型
header('Access-Control-Allow-Methods: GET, POST, PUT,DELETE,OPTIONS,PATCH');

前后端分离常见方法验证使用token,前端在header头里携带token。

后端写好后用Postman测试可以正常获取数据,跨域也是正常的,但在写前端vue项目的时候,发现携带token报错

解决方案:最开始写跨域没有带token字段,只写了Authorization,所以前端把token放在Authorization解决问题。但是改为将token信息放到header里的token字段就不行。

了解了上面预检就能解决。前端如果需要在header里携带token字段后端跨域就得加上去。简单点说,header携带什么,在后端允许放行就行。同时预检和接收请求的方法都得写跨域。预检不通过,后面的请求也不会通过

前端vue跨域

axios.interceptors.request.use(
  config => {
    if (localStorage.getItem("token")) {
      config.headers.token  = localStorage.getItem("token");
    }
    return config;
  },
  error => {
    return Promise.reject(error);
  }
)

postman在测试阶段可以拿到数据,估计是因为使用了代理,当然前端vue也可以通过代理的方式拿到数据,这里不作讲解。

引用:https://www.cnblogs.com/books-long/p/14013254.html

2021年10月21日
  • 范德萨 感谢,看了这么多,就你这个是有用的
  • 西枫里博客 你肯定没有仔细看手册,请翻到完全开发手册,路由章节--》跨域请求,不用修改框架本身的文件,也不建议修改框架本身文件
  • 程志辉 作者 回复 西枫里博客 谢谢大佬指点,学习到了。刚才看了下,thinkphp6文档里有跨域请求这块介绍,不过老版本里没有。谢谢批评,确实文档这块看的少,暂时只停留在用的层面。
Icefox Theme . 鄂ICP备16001608号-1