首页

centOS7杀死进程命令

前端达人

查看当前所有正在运行的进程,可以看到80端口被httpd占用了(80端口希望分配给nginx使用,而不是httpd)

netstat -tpnul

 

这里以杀死httpd进程为例:

先查看 httpd 进程 

flaskApi) [root@67 flaskDemo]# ps aux |grep httpd  root      6732  0.0  0.0 230488  5252 ?        Ss   8月06   2:27 /usr/sbin/httpd -DFOREGROUND
apache 22570  0.0  0.0 232572  3888 ?        S    9月15   0:00 /usr/sbin/httpd -DFOREGROUND
apache 22571  0.0  0.0 232572  3888 ?        S    9月15   0:00 /usr/sbin/httpd -DFOREGROUND
apache 22572  0.0  0.0 232572  3904 ?        S    9月15   0:00 /usr/sbin/httpd -DFOREGROUND
apache 22573  0.0  0.0 232572  3904 ?        S    9月15   0:00 /usr/sbin/httpd -DFOREGROUND
apache 22574  0.0  0.0 232572  3900 ?        S    9月15   0:00 /usr/sbin/httpd -DFOREGROUND
apache 27544  0.0  0.0 232572  3896 ?        S    15:41   0:00 /usr/sbin/httpd -DFOREGROUND
apache 27546  0.0  0.0 232572  3900 ?        S    15:41   0:00 /usr/sbin/httpd -DFOREGROUND
apache 27548  0.0  0.0 232572  3172 ?        S    15:41   0:00 /usr/sbin/httpd -DFOREGROUND
apache 27550  0.0  0.0 232572  3172 ?        S    15:41   0:00 /usr/sbin/httpd -DFOREGROUND
apache 27552  0.0  0.0 232572  3172 ?        S    15:41   0:00 /usr/sbin/httpd -DFOREGROUND
root 27665  0.0  0.0 112728   988 pts/0    S+   15:43   0:00 grep --color=auto httpd

这个就是 apache 的所有进程 

我们可以用  kill -9 加进程ID   如下

kill -9 6732 kill -9 22570 kill -9 22571 kill -9 22572 kill -9 22573 kill -9 22574 kill -9 27544 kill -9 27546 kill -9 27548 kill -9 27550 kill -9 27552 kill -9 27665

再次查看一下httpd正在运行的进程:

(flaskApi) [root@67 flaskDemo]# ps aux |grep httpd root     27835  0.0  0.0 112724   988 pts/0    S+   15:46   0:00 grep --color=auto httpd

全部杀完了... 杀死进程方法有很多种...我这个 只是其中的一种

 

通过netstat确认一下,httpd已经不再占用80端口了

(flaskApi) [root@67 flaskDemo]# netstat -tpnul

 

另如果不想杀死进程,而想修改端口号,

操作方法参照:centos7 ngxin启动失败:Job for nginx.service failed(80端口被占用的解决办法)

 

 

参照文档:

centos杀死进程命令

 

转载于:https://www.cnblogs.com/kaerxifa/p/11534539.html


蓝蓝设计www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 平面设计服务

超详细教程教你们如何将node项目部署在云服务器上

前端达人

引言

因为自己学习了前端大部分知识,然后想自己做网站,于是学习了node.js,可不知道如何将项目发布到网上,所以花了很多天的时间,搜集了很多的资料,才将项目部署到服务器上,这里给大家分享一下我的部署过程,以免大家走弯路。

  • 公众号:前端印象
  • 不定时有送书活动,记得关注~
  • 关注后回复对应文字领取:【面试题】、【前端必看电子书】、【数据结构与算法完整代码】、【前端技术交流群】

正文

一、购买服务器

这里我们就用腾讯云的服务器吧,因为优惠感觉还是比较大的,性价比也高。

先进入学生页面,购买优惠的服务器套餐,每个月才10元,学生服务器优惠套餐链接 。也可以参与限时的秒杀活动,一年才99,用来学习再合适不过了,服务器显示秒杀链接。 如果需求大的话,也可以直接买那些高配的服务器其他服务器链接
在这里插入图片描述
购买中,所有都默认选项。

购买完成后, 进入控制台
在这里插入图片描述
在这里插入图片描述
然后重置一下密码,一定要记住
在这里插入图片描述
我们鼠标移到这看一下服务器的系统是不是CentOS, 因为我们要用到这个版本
在这里插入图片描述
如果不是的话,就可以点击重装系统, 自己选择一下CentOS这个系统即可,并且重装时设置的密码也一定要记住哦。
在这里插入图片描述

这样一台服务器也就购买成功了。

二、登录服务器

  1. 网上下载一个xshell5, 用于我们登录我们的服务器
    Xshell5下载地址

  2. 下载好以后,打开Xshell5, 点击新建
    在这里插入图片描述

  3. 去复制一下我们的公网ip
    在这里插入图片描述

  4. 然后按以下提示输入

在这里插入图片描述
以下配置完成后直接点确定
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

三、给服务器安装宝塔面板

在下图输入框中,输入以下代码,并按回车

yum install -y wget && wget -O install.sh http://download.bt.cn/install/install_6.0.sh && sh install.sh 
  • 1

在这里插入图片描述
遇到该命令,直接输入y 然后回车,就他自动安装吧,时间就点长,耐心等待一下
在这里插入图片描述
安装好后,会出现这个图示界面

  • Bt-Panel:是我们即将访问的网页地址
  • username: 该网页的登录账号
  • password: 该网页的登录密码

在这里插入图片描述
访问该页面, 并输入相应的账号密码进行登录
在这里插入图片描述
登录了以后点击 直接安装
在这里插入图片描述
这时候别闲着,去软件商店里,找到这两个软件安装一下
在这里插入图片描述

四、配置服务器、网站

先回到我们的腾讯云控制台
在这里插入图片描述
在这里插入图片描述
按下图输入,并点完成
在这里插入图片描述
接下来就可以将我们的项目放到压缩文件中,然后上传到宝塔面板中了
,上传好后直接点解压就可以了在这里插入图片描述
找到我们的pm2, 开始设置我们的项目
在这里插入图片描述
在这里插入图片描述
然后点击映射,将我们的公网ip 映射一下
在这里插入图片描述
如果这里的端口是3000,我们需要将入口文件中的端口号改一下,我这里是改为5000了
在这里插入图片描述
入口文件的端口号修改好后,我们需要放行一下我们项目网站的端口号,即做以下两个步骤
在这里插入图片描述
在这里插入图片描述
然后重启一下项目
在这里插入图片描述
这样一个node.js项目就部署完成啦,接下来就通过公网ip + 端口号的方式进行访问
在这里插入图片描述
可以看到访问成功了。

结束语

这是我查阅了大量资料,才部署上去的node.js 项目,因为我是做前端的,所以不太懂运维这些的,只能做这样一个简单的部署, 不过对于新手学习已经完全足够了,希望这篇文章能帮助到你们。


转自:csdn 作者:「零一」

蓝蓝设计www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 平面设计服务

接口测试之(在Linux上搭建Tomcat环境)

前端达人

接口测试:

   接口:是传递数据的通道。接口测试主要用于检测外部系统与系统之间以及内部各个子系统之间的交互点。

   测试的重点是要检测数据的交换,传递和控制管理过程,以及系统间的相互逻辑依赖关系等。

接口的分类:

  外部接口:调用第三方平台的接口

  内部接口:登陆和注册这种单独的内部接口


1、首先下载好tomcat软件包

2、通过Xftp软件传输到我们Linux虚拟机的  /opt目录下

3、通过Xshell我们可以在/opt目录下看到tomcat软件包(如下图红色框内)

4、我们解压tomcat是用:tar -xzvf apache-tomcat-8.0.30.tar.gz    命令进行解压,可以看到解压后的文件(如下图绿色框内)因为我已经解压过了,就不给大家示范了(这里要注意的是因为我在opt目录下的,所以用这个解压命令,如果你没在你要解压的目录下就要在后面加 -c 这个参数)


5、接下来我们下载JDK(注意JDK的位数和系统区别):我是在64位Linux系统部署的

6、上传和解压和tomact一样都是tar.gz格式的,解压命令都一样,也是放在opt目录下

7、验证JDK是否安装好(java -version)


8、在其他目录下执行(java -version)是不成功的,所以要配置JDK环境变量,通过编辑 vi etc/profile  在最后段加上

JAVA_HOME=/opt/jdk1.8.0_141     -----》改成自己的jdk路径

JAVA_BIN=$JAVA_HOME/bin

JRE_HOME=$JAVA_HOME/jre

JRE_BIN=$JRE_HOME/bin

PATH=$JAVA_BIN:$JRE_BIN:$PATH

CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar:$JRE_HOME/lib

export JAVA_HOME JRE_HOME PATH CLASSPATH


9、然后输入  source /etc/profile命令,使环境变量生效,现在使用Java -version目录下验证JDK是否已经全局生效  

10、在bin目录启动tomcat,查看tomcat环境是否能可以启动(  ./startup.sh  启动       ./startup.sh 关闭 )


11、访问地址出现如下图证明tomcat环境搭建好了(你自己虚拟机的IP+tomcat的端口号)

12、修改tomcat的端口号,目录:在/opt/apache-tomcat-8.0.30/conf,用vi server.xml 修改端口号

13、注意:启动tomcat要关闭防火墙,最后养成打开日志文件习惯

转自:csdn 作者:寒門子弟


蓝蓝设计www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 平面设计服务

JavaScript实现七种排序:冒泡、简单选择、快速排序

前端达人

冒泡

n 次比较相邻两数并交换找到最值,然后 n-1 次比较找到次值……较小的数字像气泡一样浮出。
这里我引入flag排除,已经有序却一直遍历

function bubbleSort(arr){ const n=arr.length; let flag=1,i,j; for(i=0;i<n-1&&flag;i++){ //最坏的情况需要依次比较出最小值、次小值、次次小值 flag=0;//如果交换了就变 for(j=0;j<n-i-1;j++){ if(arr[j]>arr[j+1]){ const swap=arr[j]; arr[j]=arr[j+1]; arr[j+1]=swap; flag=1; } } } return arr; } 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

简单选择排序

和冒泡原理相似,但是少了很多交换,多了一个暂存最值的空间。
n 次比较相邻两数后最多只交换一次将最值放到位置上,然后 n-1 次比较找到次值
冒泡更适合基本有序的序列

function selectSort(arr) { const n=arr.length; let i,j,minIndex; for(i=0;i<n-1;i++){ minIndex=i;//先决定谁最小 for(j=i+1;j<n;j++){ if(arr[j]<arr[minIndex]){ minIndex=j; } } if(minIndex!=i){ const swap=arr[i]; arr[i]=arr[minIndex]; arr[minIndex]=swap; } } return arr; } 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

快速排序

平均时间复杂度=O(n logn)

在这里插入图片描述

function quick_part(arr,left,right){ //留下left和right后面递归 var l = left; var r = right; var basic= arr[left]; //arr[left]即basic的原位置 if(left >= right){ //如果数组只有一个元素 return; } while(l!=r){//两者相遇,意味着一直到找到basic的位置 while(arr[r] > basic && l < r){ //l<r随时注意严格控制哨兵不能错过,从右边向左找第一个比key小的数,找到或者两个哨兵相碰,跳出循环 r--; } while(arr[l] <= basic && l < r){ //这里的=号保证在本轮循环结束前,key的位置不变,否则的话跳出循环,交换l和left的位置的时候,left位置的上元素有可能不是key l++; } //1、两个哨兵到找到了目标值。2、j哨兵找到了目标值。3、两个哨兵都没找到(key是当前数组最小值) if(l!=r){ //交换两个元素的位置 const swap = arr[l]; arr[l] = arr[r]; arr[r] = swap; } } arr[left] = arr[l] //arr[left]即basic的原位置 arr[l] = basic; quick_part(arr,left,l-1); quick_part(arr,l+1,right); } function quickSort(arr){ quick_part(arr,0,arr.length-1); }



    

转自:csdn 作者:tututu333


蓝蓝设计www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 平面设计服务


Java程序的逻辑控制和方法

前端达人

一、顺序结构

从上往下执行,非常简单,不做过多赘述。

二、分支结构

1.if语句

与c语言不同的是,java的if(布尔表达式)必须是布尔表达式
eg:判断某一年是否是闰年

 public static void main(String[] args) { Scanner scan = new Scanner(System.in); int year = scan.nextInt(); if((year%4==0 && year%100 !=10)||(year%400==0)) System.out.println("闰年!"); else{ System.out.println("不是闰年!"); } } 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

2.switch语句

基础语法:

switch(整数|枚举|字符|字符串){ case 内容1 : { 内容满足时执行语句; [break;] } case 内容2 : { 内容满足时执行语句; [break;] } ... default:{ 内容都不满足时执行语句; [break;] } } 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

面试问题:
不能做switch参数的类型有哪些?
long float double boolean

三、循环结构

1.while循环

注意事项:

  1. 和 if 类似, while 下面的语句可以不写 { } , 但是不写的时候只能支持一条语句.,建议还是加上 { }
  2. 和 if 类似, while 后面的 { 建议和 while 写在同一行。
  3. 和 if 类似, while 后面不要多写 分号, 否则可能导致循环不能正确执行。
    eg:
 public static void main(String[] args) { int i=1; int ret=1; while(i<=5) { ret *= i; i++; } System.out.println(ret); 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

2.for循环

  1. 和 if 类似, for 下面的语句可以不写 { } , 但是不写的时候只能支持一条语句,建议还是加上 { }
  2. 和 if 类似, for 后面的 { 建议和 while 写在同一行。
  3. 和 if 类似, for 后面不要多写 分号, 否则可能导致循环不能正确执行。
    求阶乘的和
 public static void main(String[] args) { Scanner scan = new Scanner(System.in); int num = scan.nextInt(); int sum=0; for(int j=1;j<=num;j++){ int ret=1; for(int i=1;i <= j; i++){ ret*=1; } sum+=ret; } } } 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

3.do-while循环

基本语法:
do{
循环语句;
}while(循环条件)
先执行语句再判断循环条件。
注意事项:

  1. do while 循环最后的分号不要忘记
  2. 一般 do while 很少用到, 更推荐使用 for 和 while.

四、Java的方法

方法就是一个代码片段. 类似于 C 语言中的 "函数“。
方法:功能
public static 返回值 方法名(形式参数列表){
方法体;
}
方法名:要采用小驼峰的形式,maxNum
public static:因为当前所有的方法写完之后会在Main方法中调用。
方法体:就是具体方法的实现。

public static void main(String[] args) { int a = 10; int b = 20; // 方法的调用 int ret = add(a, b); System.out.println("ret = " + ret); } // 方法的定义 public static int add(int x, int y) { return x + y; } 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

五、方法的重载

方法的重载:
1.方法名相同
2.返回值可以不同
3.参数列表不同(参数的个数和参数的类型不同)
4.必须要在同一个类当中。
eg:

public static void main(String[] args) { int a = 10; int b = 20; int ret = add(a, b); System.out.println("ret = " + ret); double a2 = 10.5; double b2 = 20.5; double ret2 = add(a2, b2); System.out.println("ret2 = " + ret2); double a3 = 10.5; double b3 = 10.5; double c3 = 20.5; double ret3 = add(a3, b3, c3); System.out.println("ret3 = " + ret3); } public static int add(int x, int y) { return x + y; } public static double add(double x, double y) { return x + y; } public static double add(double x, double y, double z) { return x + y + z; } } 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25

方法的名字都叫 add. 但是有的 add 是计算 int 相加, 有的是 double 相加; 有的计算两个数字相加, 有的是计算三个数字相加.
同一个方法名字, 提供不同版本的实现, 称为方法重载

六、方法的递归

一个方法在执行过程中调用自身, 就称为 “递归”。
递归相当于数学上的 “数学归纳法”, 有一个起始条件, 然后有一个递推公式。
递归:
1.要调用自己本身。
2.要有一个趋近于终止的条件。
3.推导出递归的公式。
eg:求N的阶乘

public static void main(String[] args) { int n = 5; int ret = factor(n); System.out.println("ret = " + ret); } public static int factor(int n) { if (n == 1) { return 1; } return n * factor(n - 1); // factor 调用函数自身 }





    

转自:csdn 作者:flyyyya


蓝蓝设计www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 平面设计服务


vue中处理后台返回的 html 特殊标签(‘\&lt; p style=“xxx“ \&gt;‘)或(\<p>)的三种情况

前端达人

在平时获取后台数据渲染页面的时候可能会出现后台返回的数据是带有 html 特殊标签的
需求是附带的样式也不要, 意思就是直接删掉那些内容
但是在网上找挺久都没有找到现成的方法 最后是自己找了两个方法拼接出来的 所以在这里总结一下 方便以后直接 cv

// 返回数据:  ret : { list: { "introduct": '&lt;p style="color: lightcoral;"&gt;就&nbsp;当文字就是内容吧。&lt;/p&gt;', } } // 或者 ret : { list: { "introduct": '<span style="color: skyblue">就当文字就是内容吧。&nbsp;</p>', } } 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

返回数据带有html特殊字符(’&nbsp;/&le;p&gt;’) -> 转成 html标签(<p>)

// 返回数据带有html特殊字符的话直接用 v-html 在页面上显示的是 html标签 <body> <div id="app"> <div class="fd"> {{message}} // 如果需要数据中的样式的可以直接 v-html 指令渲染这个字段就能渲染出来了 <div class="box" v-html="'v-html: ' + message"></div> <button class="btn" @click="click1">dianwo</button> </div> </div> </body> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> <script> var app = new Vue({ el: '#app', data: { message: '&lt;p style="color: lightcoral;"&gt;就&nbsp;当文字就是内容吧。&lt;/p&gt;' }, methods: { click1() { this.message = this.escapeHtml(this.message) }, // 处理方法 escapeHtml(str) { var arrEntities = { 'lt': '<', 'gt': '>', 'nbsp': ' ', 'amp': '&', 'quot': '"' }; return str.replace(/&(lt|gt|nbsp|amp|quot);/ig, function(all, t) { return arrEntities[t]; }); }, } }) </script> 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39

在这里插入图片描述

上面这个方法来自:https://blog.csdn.net/weixin_49186680/article/details/108746341

返回数据带有 html标签(<span>) -> 把 html标签 去掉

// 如果不想要后台返回在数据终的样式的话可以这样处理 <body> <div id="app"> <div class="fd"> {{message}} <div class="box" v-html="'v-html: ' + message"></div> <button class="btn" @click="click1">dianwo</button> </div> </div> </body> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> <script> var app = new Vue({ el: '#app', data: { message: '<span style="color: skyblue">就当文字就是内容吧。&nbsp;</span>' }, methods: { click1() { this.message = this.delHtmlTag(this.message) }, // 处理方法 delHtmlTag(str) { return str.replace(/<[^>]+>/g, '').replace(/&nbsp;/ig, "") } } }) </script> 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29

在这里插入图片描述

上面的方法来自:https://blog.csdn.net/weixin_44565191/article/details/109716908

返回数据带有html特殊字符(’&nbsp;/&le;p&gt;’) -> 去掉特殊字符

// 如果返回的带有 html特殊字符 都不要 结合上面两个方法 改吧改吧 就能瞒住要求了 <body> <div id="app"> <div class="fd"> {{message}} <div class="box" v-html="'v-html: ' + message"></div> <button class="btn" @click="click1">dianwo</button> </div> </div> </body> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> <script> var app = new Vue({ el: '#app', data: { message: '<span style="color: skyblue">就当文字就是&nbsp;内&nbsp;容吧</span>' }, methods: { click1() { this.message = this.escapeHtml(this.message) }, // 终极 处理方法 escapeHtml(str) { var arrEntities = { 'lt': '<', 'gt': '>', 'amp': '&', 'quot': '"' }; let htmlTag = str.replace(/&(lt|gt|amp|quot);/ig, function(all, t) { return arrEntities[t]; }); // console.log(htmlTag); return htmlTag.replace(/<[^>]+>/g, '').replace(/&nbsp;/ig, "") }, } }) </script> 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39

在这里插入图片描述

感谢一下引用的这些大佬的内容
还有附上 样式 要想亲自试试效果的我把样式放这里

.fd { margin: 100px auto; display: flex; flex-direction: column; justify-content: center; align-items: center; } .box { margin: 30px 0; display: flex; align-items: center; } .btn { width: 100px; }





    

转自:csdn 作者小王几pl


蓝蓝设计www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 平面设计服务


VueRouter的实现原理——封装简易功能的VueRouter

前端达人

Hash模式和History模式的区别

不管哪种模式,前端路由都是客户端路由的实现方式,也就是当路径发生变化时,不会向服务器发送请求,是利用js监视路径的变化。然后根据不同的地址渲染不同的内容,如果需要服务器内容,会发送Ajax请求来获取。

表现形式的区别

  • hash 模式
    https://music.163.com/#/discover/toplist 地址中会存在 # 号
  • history 模式
    https://music.163.com/discover/toplist 地址中没有# 类似于普通的地址,但是需要服务端配置支持

原理的区别

  • hash 模式是基于锚点, 以及onhashchange 事件
  • history 模式是基于 HTML5 中的 History API
    • history.pushState() IE10 以后才支持
    • history.replaceState() \

History 模式的使用

  • History 需要服务器的支持
  • 单页应用中,如果刷新页面,会向服务器发起请求,而服务器不存在这样的地址就会返回找不到该页面从而出现404
  • 在服务端应该除了静态资源外都返回单页应用的 index.html

node 环境下支持 history

在 node 环境下,启用对history模式的支持可以通过 connect-history-api-fallback 这个中间件来完成

// 导入处理 history 模式的模块 const history = require('connect-history-api-fallback') // 导入 express const express = require('express') const app = express() // 注册处理 history 模式的中间件 app.use(history()) 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

Nginx 下支持 history

  • 从官网下载 nginx 的压缩包
  • 把压缩包解压到 c 盘根目录,c:\nginx-1.18.0 文件夹
  • 修改 conf\nginx.conf 文件

运行nginx服务器基本指令

启动
start nginx
重启
nginx -s reload
停止
nginx -s stop

  • 修改 conf\nginx.conf 文件
location / { root  html; index  index.html index.htm; #新添加内容
     #尝试读取$uri(当前请求的路径),如果读取不到读取$uri/这个文件夹下的首页
     #如果都获取不到返回根目录中的 index.html
     try_files $uri $uri/ /index.html; } 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

VueRouter 两种模式的实现原理

Hash 模式

  • URL 中 # 后面的内容作为路径地址
  • 监听 hashchange 事件
  • 根据当前路由地址找到对应组件重新渲染

History 模式

  • 通过 history.pushState() 方法改变地址栏
  • 监听 popstate 事件
  • 根据当前路由地址找到对应组件重新渲染

实现思路

在这里插入图片描述
从上图,可以大致了解一下 VueRouter 这个类中的结构:
上半部分是属性,下半部分是方法,其中+ 是实例方法,- 是静态方法。
install 是用来实现Vue.use 插件机制的方法。

VueRouter-install 方法实现

要实现install方法,首先先分析一下该方法要做的事情:

  1. 判断当前插件是否已经被安装
  2. 把Vue构造函数记录到全局变量
  3. 把创建Vue实例时候传入的router对象注入到所有的Vue实例上
 let _Vue; export default class VueRouter { static install(Vue) { // 1. 判断当前插件是否已经被安装 if(VueRouter.install.installed) return VueRouter.install.installed = true // 2. 把Vue构造函数记录到全局变量 _Vue = Vue // 3. 把创建Vue实例时候传入的router对象注入到所有的Vue实例上 // 利用混入让所有的vue实例加载router _Vue.mixin({ beforeCreate(){ // this.$options.name用来获取vue实例 data以外的属性 // new Vue( { router } ) if(this.$options.router) { _Vue.prototype.$router = this.$options.router } } }) } } 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

添加 VueRouter 的constructor

VueRouter 的构造函数要初始化三个属性,分别是: options、data、routeMap。

  • options 是路由的构造配置对象
  • data 应该是一个响应式的对象,其中有一个属性 current 用来记录当前我们的路由地址,这里我们该如何才能创建一个响应式的对象呢?可以使用Vue的observable方法
  • routeMap 中记录了 options里的rules,rules解析出来 会以键值对的形式存在 routeMap中 ,key 就是路由地址,value 就是路由组件
constructor(options){ this.options = options this.data = _Vue.observable({ current:'/' }) this.routeMap = {} } 
  • 1
  • 2
  • 3
  • 4
  • 5

createRouterMap

接下来我们来实现VueRouter类中 createRouterMap 这个方法,它的作用就是把 options 中rules 路由规则解析出来以键值对的形式存储在routeMap上。

 createRouterMap() { this.options.rules.forEach(route => this.routeMap[route.path] = route.component) } 
  • 1
  • 2
  • 3

initComponents

下一步,来创建initComponents 方法,这个方法里我们要创建两个组件。分别是:RouterLink 和 RouterView

创建RouterLink 组件

let _Vue; export default class VueRouter { static install(Vue) { // 1. 判断当前插件是否已经被安装 if (VueRouter.install.installed) return VueRouter.install.installed = true // 2. 把Vue构造函数记录到全局变量 _Vue = Vue // 3. 把创建Vue实例时候传入的router对象注入到所有的Vue实例上 // 利用混入让所有的vue实例加载router _Vue.mixin({ beforeCreate() { // this.$options.name用来获取vue实例 data以外的属性 // new Vue( { router } ) if (this.$options.router) { _Vue.prototype.$router = this.$options.router this.$options.router.init() } } }) } constructor(options) { this.options = options this.routeMap = {} this.data = _Vue.observable({ current: '/' }) } createRouterMap() { this.options.routes.forEach(route => this.routeMap[route.path] = route.component) } initComponents(Vue) { // 创建RouterLink组件 Vue.component('router-link', { props: { 'to': { type: String } }, template: `<a :href="to"><slot></slot></a>` }) } init() { this.createRouterMap() this.initComponents(_Vue) } } 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46

用自己的VueRouter 替换掉官方的运行后,发现报错
在这里插入图片描述
报错的意思是,运行时版本的Vue 不支持 tempalte 模板,需要打包的时候提前编译。
如果要让我们的template被支持可以使用完整版的Vue,完整包包含运行时和编译器,体积比运行时版本大10k左右,程序运行的时候把模板转换成render函数
@vue/cli 自动安装的就是 运行时版本

报错的解决

第一种方案——引入完整版Vue,可以在vue.config.js中 加入配置

module.exports = { runtimeCompiler: true } 
  • 1
  • 2
  • 3

第二种方案——使用render函数替换掉tempalte

 render(h) { return h('a', { attrs: { href: this.to } }, [this.$slots.default]) } // template: `<a :href="to"><slot></slot></a>` 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

创建RouterView组件

 // 记录一下this let self = this Vue.component('router-view',{ render(h){ // routeMap以key value形式记录了path和component // data.current 记录了当前页面的path return h(self.routeMap[self.data.current]) } }) 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

在routerlink中添加点击事件,修改地址

为了能够让链接成功完成跳转展示组件,我们需要对routerlink中的a标签添加点击事件

并且要在点击的时候,把最新的path更新到router实例的current上.

我们借助于history的pushState方法 该方法会修改浏览器地址栏中的地址,但不会向服务器发起请求,并且还可以将新地址记录在历史中

 Vue.component('router-link', { props: { 'to': { type: String } }, render(h) { return h('a', { attrs: { href: this.to }, on: { click: this.clickHandle } }, [this.$slots.default]) }, methods: { clickHandle(e) { history.pushState({}, "", this.to) // 把点击的链接地址 更新到 current 上 this.$router.data.current = this.to
                    e.preventDefault() } } // template: `<a :href="to"><slot></slot></a>` }) 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

initEvent

现在功能基本上已经差不多了,但是还存在一个小问题,就是当我们点击浏览器的前进或者后退按钮的时候,组件不能实现切换展示,主要思路就是通过添加popstate监听地址变化,下面我们来完善该功能

 initEvent(){ // window.addEventListener("popstate",()=>{ this.data.current = window.location.pathname }) } 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

完整代码

let _Vue; export default class VueRouter { static install(Vue) { // 1. 判断当前插件是否已经被安装 if (VueRouter.install.installed) return VueRouter.install.installed = true // 2. 把Vue构造函数记录到全局变量 _Vue = Vue // 3. 把创建Vue实例时候传入的router对象注入到所有的Vue实例上 // 利用混入让所有的vue实例加载router _Vue.mixin({ beforeCreate() { // this.$options.name用来获取vue实例 data以外的属性 // new Vue( { router } ) if (this.$options.router) { _Vue.prototype.$router = this.$options.router
                    console.log(this.$options.router.init); this.$options.router.init() } } }) } constructor(options) { this.options = options this.routeMap = {} this.data = _Vue.observable({ current: '/' }) } createRouterMap() { this.options.routes.forEach(route => this.routeMap[route.path] = route.component) } initComponents(Vue) { // 创建RouterLink组件 Vue.component('router-link', { props: { 'to': { type: String } }, render(h) { return h('a', { attrs: { href: this.to }, on: { click: this.clickHandle } }, [this.$slots.default]) }, methods: { clickHandle(e) { history.pushState({}, "", this.to) // 把点击的链接地址 更新到 current 上 this.$router.data.current = this.to 

e.preventDefault() } } // template: `<a :href="to"><slot></slot></a>` }) let self = this Vue.component('router-view', { render(h) { // routeMap以key value形式记录了path和component // data.current 记录了当前页面的path return h(self.routeMap[self.data.current]) } }) } init() { this.createRouterMap() this.initComponents(_Vue) this.initEvent() } initEvent() { // window.addEventListener("popstate", () => { this.data.current = window.location.pathname }) } }

转自:csdn 作者:Holyforsaken_FHC


蓝蓝设计www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 平面设计服务

bs界面赏析分享 -- 北京蓝蓝设计

前端达人

jhk-1617329495749.jpgjhk-1617329712960.jpgjhk-1617329746696.jpgjhk-1619342875081.jpgjhk-1619343080605.jpgjhk-1619343085673.jpgjhk-1619343095622.jpgjhk-1619343164521.jpgjhk-1619343150526.jpgjhk-1619343131411.jpgjhk-1619343119804.jpgjhk-1619343108913.jpgjhk-1619343106553.jpgjhk-1619343096660.jpg


--手机appUI设计--

--bs界面设计--

蓝蓝设计www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 平面设计服

js 彻底理解回调函数

前端达人

一、前奏

在谈回调函数之前,先看下下面两段代码:
不妨猜测一下代码的结果。

function say (value) {
    alert(value);
} alert(say); alert(say('hi js.')); 
  • 1
  • 2
  • 3
  • 4
  • 5

如果你测试了,就会发现:

只写变量名 say 返回的将会是 say方法本身,以字符串的形式表现出来。
而在变量名后加()如say()返回的就会使say方法调用后的结果,这里是弹出value的值。 
  • 1
  • 2

二、js中函数可以作为参数传递

再看下面的两段代码:

function say (value) { alert(value);
} function execute (someFunction, value) { someFunction(value);
}
execute(say, 'hi js.'); 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

function execute (someFunction, value) { someFunction(value);
}
execute(function(value){alert(value);}, 'hi js.'); 
  • 1
  • 2
  • 3
  • 4

上面第一段代码是将say方法作为参数传递给execute方法
第二段代码则是直接将匿名函数作为参数传递给execute方法

实际上:

function say (value) { alert(value);
} // 注意看下面,直接写say方法的方法名与下面的匿名函数可以认为是一个东西 // 这样再看上面两段代码是不是对函数可以作为参数传递就更加清晰了 say; function (value) { alert(value);
} 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
这里的say或者匿名函数就被称为回调函数。  
  • 1

三、回调函数易混淆点——传参

如果回调函数需要传参,如何做到,这里介绍两种解决方案。

  • 将回调函数的参数作为与回调函数同等级的参数进行传递


  • 回调函数的参数在调用回调函数内部创建


四、写在最后

回调函数应用场景多用在使用 js 写组件时,尤其是组件的事件很多都需要回调函数的支持。

转自:csdn 作者:dkvirus


蓝蓝设计www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 平面设计服务


app界面赏析 ——— 北京蓝蓝设计 移动端UI设计资源分享(二十)

前端达人

移动互联网的迅速崛起,让移动网页,移动客户端越来越重要,客户端的页面设计也是一门很大的学问。科技迅速发展的今手机屏幕的尺寸越来越放大化,但却始终 很有限,因此,在APP的界面设计中,精简是一贯的准则。这里所说的精简并不是内容上尽可能的少量,而是要注重重点的表达。在视觉上也要遵循用户的视觉逻 辑,用户看着顺眼了,才会真正的喜欢。


接下来为大家分享精美的app UI设计案例:


jhk-1617329495749.jpgjhk-1617329712960.jpgjhk-1617329746696.jpgjhk-1618475057961.pngjhk-1618475082684.pngjhk-1618475178817.jpg



--手机appUI设计--

蓝蓝设计www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 平面设计服



  更多精彩文章:

       手机appUI界面设计赏析(一)

       手机appUI界面设计赏析(二)

       手机appUI界面设计赏析(三)

       手机appUI界面设计赏析(四)

       手机appUI界面设计赏析(五)

       手机appUI界面设计赏析(六)

       手机appUI界面设计赏析(七)

       手机appUI界面设计赏析(八)

       手机appUI界面设计赏析(九)

        手机appUI界面设计赏析(十)

       手机appUI界面设计赏析(十一)

       手机appUI界面设计赏析(十二)

        手机appUI界面设计赏析(十三)

       手机appUI界面设计赏析(十四)

       手机appUI界面设计赏析(十五)

       手机appUI界面设计赏析(十六)

       手机appUI界面设计赏析(十七)

      手机appUI界面设计赏析(十八)

      手机appUI界面设计赏析(十九)





日历

链接

个人资料

蓝蓝设计的小编 http://www.lanlanwork.com

存档