首页

nginx下部署vue项目概览

前端达人

今天要用到服务器nginx,还需要把自己的vue的项目部署到服务器上去所以就写一下记录下来。

首先要去nginx官网下下载nginx:
下载地址:https://nginx.org/en/download.html
这里写图片描述

下载下来会是一个解压包,解压到你想放的文件夹下

这里写图片描述

运行nginx.exe,然后打开浏览器输入localhost出来如下图片所示就说明成功了:

这里写图片描述

然后如果没有成功出来的话也不要慌不要怕,可能是你的端口被别的内容所占了这时你就打开你的nginx的目录下找到conf

这里写图片描述

点击进去然后找到一个nginx.conf的文件

这里写图片描述

然后把它用编辑器的方式打开,打开之后找到这里的sever的listen就是你的端口号,默认的是80端口,你可以根据自己没有被占用的端口进行改写,改写完成之后保存然后打开你的localhost:你改写的端口号就OK了

 server {
            listen       8088;
            server_name  localhost;

            #charset koi8-r;

            #access_log  logs/host.access.log  main;

            location / {
                root   html;
                index  index.html index.htm;
        } 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

这里写图片描述

上面是安装配置nginx服务器的方法,下面就是如何把自己的vue项目部署到你所安装配置的nginx服务器上的步骤了:

首先找到自己的vue的项目然后输入命令 npm run build 他会在你的vue目录下生成一个dist文件夹里面就是你的vue的项目

这里写图片描述

然后打开这个dist文件夹把里面的内容复制下来里面会有两个文件一个是index.html是主目录还有一个是static文件夹

这里写图片描述

把他们复制下来然后打开你的nginx的目录下的html文件里面会有两个默认文件直接删掉不要留,然后把你刚刚复制的文件粘贴进去

这里写图片描述

然后打开浏览器输入最开始改的端口号localhost:你所改的端口号回车;你就会看到自己的vue的项目跑起来了我的打开就是这样的咯:

这里写图片描述

这样就大功告成了~~~~~~~~~


转自:csdn 作者:前端的搬运工 

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

前端登录流程

前端达人

前端登录流程

初次登录的时候,前端调后调的登录接口,发送用户名和密码,后端收到请求,验证用户名和密码,验证成功,就给前端返回一个token,和一个用户信息的值,前端拿到token,将token储存到Vuex中,然后从Vuex中把token的值存入浏览器Cookies中。把用户信息存到Vuex然后再存储到LocalStroage中
Cookies
在这里插入图片描述
LocalStroage
在这里插入图片描述
在这里插入图片描述
然后跳转到下一个页面,根据后端接口的要求,只要不登录就不能访问的页面需要在前端每次跳转页面师判断Cookies中是否有token,没有就跳转到登录页,有就跳转到相应的页面,我们应该再每次发送post/get请求的时候应该加入token,常用方法再项目utils/service.js中添加全局拦截器,将token的值放入请求头中
在这里插入图片描述
后端判断请求头中有无token,有token,就拿到token并验证token是否过期,在这里过期会返回无效的token然后有个跳回登录页面重新登录并且清楚本地用户的信息在这里插入图片描述

再全局拦截器中加代码在这里插入图片描述

转自:csdn 作者:mslmhl

SSM框架实战-搭建自己的个人博客1-基础架构搭建

前端达人

前言

本系列文章主要通过从零开始搭建自己的个人博客,来加深对SSM框架的学习与使用,了解一个系统从提出到设计-到开发-到测试-部署运行的过程,并记录在搭建过程中的学习心得、遇见的错误及解决方式。

个人博客的主要功能有:

  1. 博客列表展示:文章按照时间顺序(时间倒序:最新最先展示)列表展示
  2. 博客文章详情展示:展示文章全部内容,包含:作者、创建时间、所属目录、标签、文章标题、内容
  3. 用户权限管理:游客只能浏览文章、管理员可以发布文章、文章下线处理
  4. 添加文章功能:支持富文本编辑。可以调整字体大小、样式、键入代码等功能

界面展示:

前台博客列表界面

前台博客列表页面.png

博客详情页面

博客详情页面.png

后台管理页面 

 

登录页面

 

后台管理页面.png

项目技术简介

系统实现的功能点

  1. 用户权限管理:普通的用户(游客)只能浏览文章、管理员用户可以发布文章、文章管理
  2. 博客列表展示:文章按照发布时间顺序(按照时间倒叙)展示 :博客类别、标签、博客名称、作者名、发布时间、阅读数量、博客的内容概括
  3. 博客详情页面:博客名称、作者、时间、博客内容、标签
  4. 博客后台列表:博客检索(类别、标签、博客名称)、博客列表(博客id、博客类别、标签、时间)、博客操作
  5. 新增博客功能:支持富文本编辑:可以调整大小、样式等

服务端技术

核心框架:Spring:5.2.8.RELEASE

web框架:SpringMVC:5.2.8.RELEASE

持久层框架:Mybatis 3.2.4

数据库连接池:阿里druid:0.2.6

数据库:MySQL5.XX

JSON数据处理:谷歌gson 2.3

前端技术

jsp

Ajax

前端框架:bootstrap

富文本编辑器:百度UEditor

数据库的设计

  • 用户表:账号id、账号名称、账号密码
  • 博客表:博客id、博客名称、博客内容、发布时间、阅读量、类别id、状态
  • 博客/标签对应表:博客id、标签的id
  • 标签表:标签id、标签名称(博客和标签:一对多:一个博客可以对应多个标签)
  • 类别表:类别ID、类别名称(博客和类别:一对一:一个博客对应一个类别)

创建SQL语句:

 
  1. DROP TABLE IF EXISTS `t_article`;
  2. CREATE TABLE `t_article` (
  3. `id` int(11) NOT NULL AUTO_INCREMENT,
  4. `categoryId` int(11) NOT NULL COMMENT '分类Id',
  5. `title` varchar(40) NOT NULL COMMENT '标题',
  6. `content` blob NOT NULL COMMENT '内容',
  7. `description` varchar(500) NOT NULL COMMENT '文章简介 用于列表显示',
  8. `statue` int(11) NOT NULL DEFAULT '0' COMMENT '状态 0:正常 1:不可用',
  9. `author` varchar(15) DEFAULT 'tulun' COMMENT '作者',
  10. `createTime` datetime NOT NULL COMMENT '发表时间',
  11. `showCount` int(11) NOT NULL DEFAULT '0' COMMENT '浏览量',
  12. PRIMARY KEY (`id`)
  13. ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='文章表';
  14. -- ----------------------------
  15. -- Table structure for t_article_image
  16. -- ----------------------------
  17. DROP TABLE IF EXISTS `t_article_image`;
  18. CREATE TABLE `t_article_image` (
  19. `id` int(11) NOT NULL AUTO_INCREMENT,
  20. `imageUrl` varchar(100) NOT NULL COMMENT '图片地址',
  21. `articleId` int(11) NOT NULL COMMENT '文章Id',
  22. PRIMARY KEY (`id`,`articleId`)
  23. ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='文章图 主要用于列表浏览';
  24. -- ----------------------------
  25. -- Table structure for t_tag
  26. -- ----------------------------
  27. DROP TABLE IF EXISTS `t_tag`;
  28. CREATE TABLE `t_tag` (
  29. `id` int(11) NOT NULL AUTO_INCREMENT,
  30. `tagName` varchar(25) NOT NULL COMMENT '标签名称 唯一',
  31. PRIMARY KEY (`id`),
  32. UNIQUE KEY `tagName_UNIQUE` (`tagName`)
  33. ) ENGINE=InnoDB AUTO_INCREMENT=23 DEFAULT CHARSET=utf8 COMMENT='标签表';
  34. -- ----------------------------
  35. -- Table structure for t_article_tag
  36. -- ----------------------------
  37. DROP TABLE IF EXISTS `t_article_tag`;
  38. CREATE TABLE `t_article_tag` (
  39. `articleId` int(11) NOT NULL COMMENT '文章Id',
  40. `tagId` int(11) NOT NULL COMMENT '标签Id',
  41. PRIMARY KEY (`articleId`,`tagId`)
  42. ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='文章标签中间表';
  43. -- ----------------------------
  44. -- Table structure for t_category
  45. -- ----------------------------
  46. DROP TABLE IF EXISTS `t_category`;
  47. CREATE TABLE `t_category` (
  48. `id` int(11) NOT NULL AUTO_INCREMENT,
  49. `categoryName` varchar(20) NOT NULL COMMENT '分类名称 唯一',
  50. `iconClass` varchar(45) NOT NULL COMMENT '图标样式',
  51. `aliasName` varchar(20) NOT NULL COMMENT '别名 唯一 比如新闻 就用News 代替 栏目Id不显示在url中',
  52. `sort` int(11) NOT NULL DEFAULT '0' COMMENT '排序 (0-10)',
  53. PRIMARY KEY (`id`),
  54. UNIQUE KEY `aliasName_UNIQUE` (`aliasName`),
  55. UNIQUE KEY `categoryName_UNIQUE` (`categoryName`)
  56. ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='分类表 只支持一级分类 如果需要分多个层次 用标签来协助实现';
  57. -- ----------------------------
  58. -- Table structure for t_manager
  59. -- ----------------------------
  60. DROP TABLE IF EXISTS `t_manager`;
  61. CREATE TABLE `t_manager` (
  62. `id` int(11) NOT NULL AUTO_INCREMENT,
  63. `userName` varchar(25) NOT NULL COMMENT '用户名',
  64. `password` varchar(45) NOT NULL,
  65. PRIMARY KEY (`id`)
  66. ) ENGINE=InnoDB DEFAULT CHARSET=utf8;

image.png

框架结构搭建

SSM项目脚手架搭建

搭建如下框架结构:

目录说明:

 
  1. 目录说明:
  2. |-src
  3. |--mian
  4. |---java JAVA源代码根目录
  5. |----com
  6. |-----tulun
  7. |------model 存放pogo类:基本基本的getter和setter方法
  8. |------controller 展示层类包路径:前端用户请求映射到该包路径下类的实现
  9. |------service 业务逻辑层包路径:业务逻辑实现,调用dao层服务
  10. |------dao 数据库操作层包路径:提供对数据库的操作类与方法
  11. |------util 工具类包路径
  12. |---resource 配置文件根目录
  13. |----myatis mybatis接口对应配置文件目录
  14. |----spring-XXX.xml SSM中mybatis、spring核心、springMVC的全局配置文件
  15. |--webapp 前端页面内容根目录
  16. |---WEB-INF
  17. |----web.xml 前端页面必要配置文件
  18. |-pom.xml maven的配置文件

测试Demo

主要完成各个层之间的连接映射,完成从t_manager表中读取数据并进行回显

 

POJO类

根据数据库表t_manager,创建User类

 
  1. package com.tulun.model;
  2. /**
  3. * Description :
  4. * Created by Resumebb
  5. * Date :2021/4/17
  6. */
  7. public class User {
  8. private Integer id;
  9. private String name;
  10. private String passwd;
  11. public Integer getId() {
  12. return id;
  13. }
  14. public void setId(Integer id) {
  15. this.id = id;
  16. }
  17. public String getName() {
  18. return name;
  19. }
  20. public void setName(String name) {
  21. this.name = name;
  22. }
  23. public String getPasswd() {
  24. return passwd;
  25. }
  26. public void setPasswd(String passwd) {
  27. this.passwd = passwd;
  28. }
  29. }

Spring核心配置文件

这里用到了阿里巴巴的druid连接池

 
  1. <beans xmlns="http://www.springframework.org/schema/beans"
  2. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  3. xmlns:context="http://www.springframework.org/schema/context"
  4. xsi:schemaLocation="http://www.springframework.org/schema/beans
  5. http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
  6. http://www.springframework.org/schema/context
  7. http://www.springframework.org/schema/context/spring-context-3.0.xsd">
  8. <!--开启注解-->
  9. <context:component-scan base-package="com.tulun"/>
  10. <!--配置数据源:借助连接池druid-->
  11. <bean id ="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
  12. <!--注入属性-->
  13. <property name="url" value="jdbc:mysql://localhost:3306/test"/>
  14. <property name="username" value="root"/>
  15. <property name="password" value="123456"/>
  16. </bean>
  17. <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
  18. <property name="dataSource" ref="dataSource"/>
  19. <!--注入mapper映射文件-->
  20. <property name="configLocation" value="classpath:spring-mybatis.xml"></property>
  21. <property name="mapperLocations" value="classpath:mapper/*.xml"/>
  22. </bean>
  23. <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
  24. <property name="basePackage" value="com.tulun.dao"/>
  25. <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
  26. </bean>
  27. </beans>

Spring-Mybatis配置文件

 
  1. <?xml version="1.0" encoding="UTF-8" ?>
  2. <!DOCTYPE configuration
  3. PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
  4. "http://mybatis.org/dtd/mybatis-3-config.dtd">
  5. <!--根标签-->
  6. <configuration>
  7. </configuration>

SpringMVC配置文件

 
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <beans xmlns="http://www.springframework.org/schema/beans"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xmlns:context="http://www.springframework.org/schema/context"
  5. xmlns:mvc="http://www.springframework.org/schema/mvc"
  6. xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
  7. http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.1.xsd
  8. http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.1.xsd">
  9. <!--扫描controller写注解-->
  10. <context:component-scan base-package="com.tulun.controller"/>
  11. <!--配置映射器-->
  12. <mvc:annotation-driven/>
  13. <!--配置视图解析器-->
  14. <!--视图解析器-->
  15. <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
  16. <!--jsp页面前缀-->
  17. <property name="prefix" value="/WEB-INF/jsp/"/>
  18. <!--jsp后缀-->
  19. <property name="suffix" value=".jsp"/>
  20. <property name="viewClass" value="org.springframework.web.servlet.view.freemarker.FreeMarkerView"/>
  21. </bean>
  22. </beans>

web配置文件

 
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
  5. http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
  6. <context-param>
  7. <param-name>contextConfigLocation</param-name>
  8. <param-value>classpath:spring-core.xml</param-value>
  9. </context-param>
  10. <listener>
  11. <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
  12. </listener>
  13. <!--前端控制器-->
  14. <servlet>
  15. <servlet-name>myBolg</servlet-name>
  16. <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
  17. <!--将springMVC的配置文件进行配置-->
  18. <init-param>
  19. <param-name>contextConfigLocation</param-name>
  20. <param-value>classpath:spring-mvc.xml</param-value>
  21. </init-param>
  22. </servlet>
  23. <servlet-mapping>
  24. <servlet-name>myBolg</servlet-name>
  25. <url-pattern>/</url-pattern>
  26. </servlet-mapping>
  27. </web-app>

pom依赖

 
  1. <dependencies>
  2. <dependency>
  3. <groupId>junit</groupId>
  4. <artifactId>junit</artifactId>
  5. <version>4.11</version>
  6. <scope>test</scope>
  7. </dependency>
  8. <!-- spring依赖-->
  9. <dependency>
  10. <groupId>org.springframework</groupId>
  11. <artifactId>spring-core</artifactId>
  12. <version>5.2.8.RELEASE</version>
  13. </dependency>
  14. <dependency>
  15. <groupId>org.springframework</groupId>
  16. <artifactId>spring-context</artifactId>
  17. <version>5.2.8.RELEASE</version>
  18. </dependency>
  19. <dependency>
  20. <groupId>org.springframework</groupId>
  21. <artifactId>spring-beans</artifactId>
  22. <version>5.2.8.RELEASE</version>
  23. </dependency>
  24. <dependency>
  25. <groupId>org.springframework</groupId>
  26. <artifactId>spring-expression</artifactId>
  27. <version>5.2.8.RELEASE</version>
  28. </dependency>
  29. <!--web依赖/spring mvc依赖-->
  30. <dependency>
  31. <groupId>org.springframework</groupId>
  32. <artifactId>spring-webmvc</artifactId>
  33. <version>5.2.8.RELEASE</version>
  34. </dependency>
  35. <dependency>
  36. <groupId>org.springframework</groupId>
  37. <artifactId>spring-web</artifactId>
  38. <version>5.2.8.RELEASE</version>
  39. </dependency>
  40. <dependency>
  41. <groupId>javax.servlet</groupId>
  42. <artifactId>javax.servlet-api</artifactId>
  43. <version>3.1.0</version>
  44. </dependency>
  45. <!--tomcat servlet api -->
  46. <dependency>
  47. <groupId>jstl</groupId>
  48. <artifactId>jstl</artifactId>
  49. <version>1.2</version>
  50. </dependency>
  51. <dependency>
  52. <groupId>taglibs</groupId>
  53. <artifactId>standard</artifactId>
  54. <version>1.1.2</version>
  55. </dependency>
  56. <!--mybatis依赖-->
  57. <dependency>
  58. <groupId>org.mybatis</groupId>
  59. <artifactId>mybatis</artifactId>
  60. <version>3.4.1</version>
  61. </dependency>
  62. <dependency>
  63. <groupId>mysql</groupId>
  64. <artifactId>mysql-connector-java</artifactId>
  65. <version>5.1.39</version>
  66. </dependency>
  67. <!-- 整合-->
  68. <dependency>
  69. <groupId>org.mybatis</groupId>
  70. <artifactId>mybatis-spring</artifactId>
  71. <version>1.3.0</version>
  72. </dependency>
  73. <!-- 连接池-->
  74. <dependency>
  75. <groupId>com.mchange</groupId>
  76. <artifactId>c3p0</artifactId>
  77. <version>0.9.5.2</version>
  78. </dependency>
  79. <dependency>
  80. <groupId>org.springframework</groupId>
  81. <artifactId>spring-tx</artifactId>
  82. <version>5.2.8.RELEASE</version>
  83. </dependency>
  84. <dependency>
  85. <groupId>org.springframework</groupId>
  86. <artifactId>spring-jdbc</artifactId>
  87. <version>5.2.8.RELEASE</version>
  88. </dependency>
  89. <dependency>
  90. <groupId>javax.servlet.jsp.jstl</groupId>
  91. <artifactId>jstl</artifactId>
  92. <version>1.2</version>
  93. </dependency>
  94. <dependency>
  95. <groupId>javax.servlet</groupId>
  96. <artifactId>servlet-api</artifactId>
  97. <version>2.5</version>
  98. </dependency>
  99. <dependency>
  100. <groupId>com.google.code.gson</groupId>
  101. <artifactId>gson</artifactId>
  102. <version>2.3</version>
  103. </dependency>
  104. <dependency>
  105. <groupId>com.alibaba</groupId>
  106. <artifactId>druid</artifactId>
  107. <version>0.2.6</version>
  108. </dependency>
  109. <dependency>
  110. <groupId>commons-logging</groupId>
  111. <artifactId>commons-logging</artifactId>
  112. <version>1.1.1</version>
  113. </dependency>
  114. <dependency>
  115. <groupId>commons-configuration</groupId>
  116. <artifactId>commons-configuration</artifactId>
  117. <version>1.9</version>
  118. </dependency>
  119. </dependencies>

UserMapper

 
  1. import com.tulun.model.User;
  2. /**
  3. * Description :
  4. * Created by Resumebb
  5. * Date :2021/4/22
  6. */
  7. public interface UserMapper {
  8. public User getUserById(Integer id);
  9. }

UserService

 
  1. package com.tulun.service;
  2. import com.tulun.model.User;
  3. import com.tulun.dao.UserMapper;
  4. import org.springframework.beans.factory.annotation.Autowired;
  5. import org.springframework.stereotype.Service;
  6. /**
  7. * Description :
  8. * Created by Resumebb
  9. * Date :2021/4/19
  10. */
  11. @Service
  12. public class UserService {
  13. @Autowired
  14. private UserMapper userMapper;
  15. public User getUserById(Integer id){
  16. if(id < 0)
  17. return new User();
  18. return userMapper.getUserById(id);
  19. }
  20. }

UserController

查询t_manager中的id为1的数据进行显示

 
  1. package com.tulun.controller;
  2. import com.tulun.model.User;
  3. import com.tulun.service.UserService;
  4. import org.springframework.beans.factory.annotation.Autowired;
  5. import org.springframework.stereotype.Controller;
  6. import org.springframework.web.bind.annotation.RequestMapping;
  7. import org.springframework.web.bind.annotation.ResponseBody;
  8. /**
  9. * Description :
  10. * Created by Resumebb
  11. * Date :2021/4/22
  12. */
  13. @Controller
  14. public class UserController {
  15. @Autowired
  16. private UserService userService;
  17. @RequestMapping("/testUser")
  18. @ResponseBody
  19. public User testUser(){
  20. User user = userService.getUserById(1);
  21. return user;
  22. }
  23. }

UserMapper.xml

 
  1. <?xml version="1.0" encoding="UTF-8" ?>
  2. <!DOCTYPE mapper
  3. PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  4. "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
  5. <mapper namespace="com.tulun.dao.UserMapper">
  6. <resultMap id="UserMap" type="com.tulun.model.User">
  7. <result property="id" column="id"></result>
  8. <result property="name" column="userName"></result>
  9. <result property="passwd" column="password"></result>
  10. </resultMap>
  11. <select id="getUserById" parameterType="int" resultMap="UserMap">
  12. select * from t_manager where id=#{id}
  13. </select>
  14. </mapper>

运行结果

 

错误记录

运行的界面显示unkown the request

 原因是因为端口被占用了,更改服务器的端口号就可以了。

出现这个错误就要检查SQL查询语句,数据源的配置是否正确,经检查我报这个错是因为SQL查询语句manager写成了manger,用户名密码不对也会报这个错。

类似这种错,一是检查@Service有没有加上,二是检查映射文件有没有顶行写,第一行不能有空行。

转自:csdn。作者:resumebb

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

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界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 平面设计服务

日历

链接

个人资料

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

存档