首页 > 其他分享 >全部的笔记

全部的笔记

时间:2023-02-15 09:55:55浏览次数:49  
标签:function console log 笔记 全部 let user 组件

JDBC

  • JDBC是Java提供的连接数据库的一套接口。

使用JDBC访问数据库的过程

  1. 将数据库的驱动文件导入到项目中

    • JavaSE项目:将jar文件复制到项目的包中-->jar右键-->Build Path-->Add to Build Path
  2. 加载数据库驱动

    • Class.forName("包名.类名"):创建类的对象,并将对象加载到内存中。

      try {
          Class.forName("com.mysql.cj.jdbc.Driver");
          System.out.println("数据库驱动加载成功!!!");
      } catch (ClassNotFoundException e) {
          System.out.println("数据库驱动加载失败!!!");
      }
      
    • DriverManager.registerDriver(new 数据库驱动()):注册数据库驱动。

      try {
      	DriverManager.registerDriver(new Driver());
      } catch (SQLException e) {
      	System.out.println("数据库异常!!!");
      }
      
  3. 创建java.sql.Connection接口的实例,连接数据库。

    // 连接对象
    Connection conn = null;
    try {
        Class.forName("com.mysql.cj.jdbc.Driver");
        // DriverManager.getConnection("url","用户名","密码")
        conn = DriverManager.getConnection(
            "jdbc:mysql://127.0.0.1:3306/test?characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai&nullCatalogMeansCurrent=true&allowPublicKeyRetrieval=true",
            "root", "123456");
    } catch (ClassNotFoundException e) {
        System.out.println("数据库驱动加载失败!!!");
    } catch (SQLException e) {
        System.out.println("数据库异常,请稍候再试!!!");
    }
    
  4. 创建java.sql.Statementjava.sql.PreparedStatement接口的实例。将Java的字符串编译为数据库可以解析的SQL语句。

    • 当执行SELECT语句时,需要使用语句对象的executeQuery()方法,此方法的返回类型为java.sql.ResultSet接口类型的实例,用于保存查询的结果
    // 连接对象
    Connection conn = null;
    // 语句对象
    Statement stat = null;
    // 结果集
    ResultSet rs = null;
    try {
        Class.forName("com.mysql.cj.jdbc.Driver");
        // DriverManager.getConnection("url","用户名","密码")
        conn = DriverManager.getConnection(
            "jdbc:mysql://127.0.0.1:3306/test?characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai&nullCatalogMeansCurrent=true&allowPublicKeyRetrieval=true",
            "root", "123456");
        String sql = "select user_id,user_name,user_password,user_salary,user_birthday from user_message";
        // 使用连接对象,创建语句对象
        stat = conn.createStatement();
        // 使用语句对象执行SELECT语句,并将查询的结果存入到结果集中
        rs = stat.executeQuery(sql);
    } catch (ClassNotFoundException e) {
        System.out.println("数据库驱动加载失败!!!");
    } catch (SQLException e) {
        System.out.println("数据库异常,请稍候再试!!!");
        e.printStackTrace();
    }
    
    • 当执行INSERT/DELETE/UPDATE语句时,需要使用语句对象的executeUpdate()方法,此方法返回类型为int类型,表示INSERT/DELETE/UPDATE语句执行后影响表中数据的行数
  5. 处理结果

    • ResultSet的next()方法:将结果集的游标向下移动一行,游标移动后找到了数据返回true,否则返回false。

      // 连接对象
      Connection conn = null;
      // 语句对象
      Statement stat = null;
      // 结果集
      ResultSet rs = null;
      try {
          Class.forName("com.mysql.cj.jdbc.Driver");
          // DriverManager.getConnection("url","用户名","密码")
          conn = DriverManager.getConnection(
              "jdbc:mysql://127.0.0.1:3306/test?characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai&nullCatalogMeansCurrent=true&allowPublicKeyRetrieval=true",
              "root", "123456");
          String sql = "select user_id,user_name,user_password,user_salary,user_birthday from user_message";
          // 使用连接对象,创建语句对象
          stat = conn.createStatement();
          // 使用语句对象执行SELECT语句,并将查询的结果存入到结果集中
          rs = stat.executeQuery(sql);
          // 使用循环遍历结果集
          while(rs.next()) {
              System.out.print(rs.getInt("user_id") + "\t");
              System.out.print(rs.getString("user_name") + "\t");
              System.out.print(rs.getString("user_password") + "\t");
              System.out.print(rs.getDouble("user_salary") + "\t");
              System.out.println(rs.getDate("user_birthday"));
          }
      } catch (ClassNotFoundException e) {
          System.out.println("数据库驱动加载失败!!!");
      } catch (SQLException e) {
          System.out.println("数据库异常,请稍候再试!!!");
          e.printStackTrace();
      }
      
    • ResultSet的getXXXX(参数):获得结果集当前行指定列的数据。参数的类型可以为String,也可以是int类型

  6. 关闭与数据库相关的对象,否则垃圾回收器不会释放相关的内存。

    // 连接对象
    Connection conn = null;
    // 语句对象
    Statement stat = null;
    // 结果集
    ResultSet rs = null;
    try {
        Class.forName("com.mysql.cj.jdbc.Driver");
        // DriverManager.getConnection("url","用户名","密码")
        conn = DriverManager.getConnection(
            "jdbc:mysql://127.0.0.1:3306/test?characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai&nullCatalogMeansCurrent=true&allowPublicKeyRetrieval=true",
            "root", "123456");
        String sql = "select user_id,user_name,user_password,user_salary,user_birthday from user_message";
        // 使用连接对象,创建语句对象
        stat = conn.createStatement();
        // 使用语句对象执行SELECT语句,并将查询的结果存入到结果集中
        rs = stat.executeQuery(sql);
        // 使用循环遍历结果集
        while(rs.next()) {
            System.out.print(rs.getInt("user_id") + "\t");
            System.out.print(rs.getString("user_name") + "\t");
            System.out.print(rs.getString("user_password") + "\t");
            System.out.print(rs.getDouble("user_salary") + "\t");
            System.out.println(rs.getDate(0));
        }
    } catch (ClassNotFoundException e) {
        System.out.println("数据库驱动加载失败!!!");
    } catch (SQLException e) {
        System.out.println("数据库异常,请稍候再试!!!");
        e.printStackTrace();
    } finally {
        if(rs != null) {
            try {
                rs.close();
            } catch (SQLException e) {
            }
        }
        if(stat != null) {
            try {
                stat.close();
            } catch (SQLException e) {
            }
        }
        if(conn != null) {
            try {
                conn.close();
            } catch (SQLException e) {
            }
        }
    }
    
  7. java.sql.Statement接口与java.sql.PreparedStatement接口的关系与区别

    • 关系:PreparedStatement是Statement的子接口。
    • 区别:
      • 安全性:
        • Statement无法防止SQL注入,安全性低。
        • PreparedStaterment可以防止SQL注入,安全性高
      • 效率:当需要批量执行同一条SQL语句时。
        • Statement每次执行语句时,都需要先编译语句,再执行语句,效率低。
        • PreparedStatement只在第一次执行语句时编译语句,再执行。从第二次执行开始,不再编译语句,而直接执行,效率高

添加数据

/**
 * 向USER_MESSAGE表中添加新的用户信息
 * 
 * @param userName     用户名
 * @param userPassword 用户密码
 * @param userSalary   用户工资
 * @param userBirthday 出生日期
 * @return 添加成功返回大于0的整数,否则返回0
 */
public int save(String userName, String userPassword, Double userSalary, Date userBirthday) {
	Connection conn = null;
	PreparedStatement ps = null;
	try {
		Class.forName("com.mysql.cj.jdbc.Driver");
		conn = DriverManager.getConnection(
				"jdbc:mysql://127.0.0.1:3306/test?characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai&nullCatalogMeansCurrent=true&allowPublicKeyRetrieval=true",
				"root", "123456");
		String sql = "insert into user_message(user_name,user_password,user_salary,user_birthday) values(?,?,?,?)";
		// 关闭数据库自动提交功能,只有insert/delete/update语句需要,select语句不需要
		conn.setAutoCommit(false);
		// 创建准备语句对象,并设置准备语句对象将要执行的insert语句
		ps = conn.prepareStatement(sql);
		// 替换准备语句对象中的问号
		ps.setString(1, userName);
		ps.setString(2, userPassword);
		ps.setDouble(3, userSalary);
		// 将java.util.Date转换为java.sql.Date
		ps.setDate(4, new java.sql.Date(userBirthday.getTime()));
		// 使用准备语句对象执行insert语句,并获得insert语句执行后影响表中数据的行数
		int rows = ps.executeUpdate();
		if (rows > 0) {
			// 添加成功,提交事务
			conn.commit();
			return rows;
		}
		// 添加失败,回退事务
		conn.rollback();
	} catch (ClassNotFoundException e) {
		e.printStackTrace();
	} catch (SQLException e) {
		e.printStackTrace();
	} finally {
		if (ps != null) {
			try {
				ps.close();
			} catch (SQLException e) {
			}
		}
		if (conn != null) {
			try {
				conn.close();
			} catch (SQLException e) {
			}
		}
	}
	return 0;
}

修改数据

/**
 * 修改USER_MESSAGE表中指定用户的USER_PASSWORD
 * 
 * @param userId       用户编号
 * @param userPassword 新密码
 * @return 修改成功返回大于0的整数,否则返回0
 */
public int updateUserPasswordByUserId(Integer userId, String userPassword) {
	Connection conn = null;
	PreparedStatement ps = null;
	try {
		// 加载数据库驱动
		Class.forName("com.mysql.cj.jdbc.Driver");
		// 创建连接对象,连接数据库
		conn = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/test?characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai&nullCatalogMeansCurrent=true&allowPublicKeyRetrieval=true","root","123456");
		// 创建UPDATE语句
		String sql = "update user_message set user_password=? where user_id=?";
		// 关闭数据库自动提交的功能
		conn.setAutoCommit(false);
		// 创建准备语句对象,并设置准备语句对象将要执行的UPDATE语句
		ps = conn.prepareStatement(sql);
		// 替换准备语句对象中的问号
		ps.setString(1, userPassword);
		ps.setInt(2, userId);
		// 使用准备语句对象执行UPDATE语句,并获得UPDATE语句执行后影响表中数据的行数
		int rows = ps.executeUpdate();
		// 如果修改成功,提交事务,返回UPDATE影响数据的行数
		if(rows > 0) {
			conn.commit();
			return rows;
		}
		// 如果修改失败,回退事务
		conn.rollback();
	} catch (ClassNotFoundException e) {
		e.printStackTrace();
	} catch (SQLException e) {
		e.printStackTrace();
	} finally {
		// 关闭与数据库相关的对象
		if(ps != null) {
			try {
				ps.close();
			} catch (SQLException e) {
			}
		}
		if(conn != null) {
			try {
				conn.close();
			} catch (SQLException e) {
			}
		}
	}
	return 0;
}

封装查询结果

  • 创建实体类:实体类的对象可以封装表中的一行数据。

    package com.test.po;
    
    import java.util.Date;
    
    /**
     * 实体类:当前类的“一个”对象可以封装USER_MESSAGE表中的“一行”用户信息
     * 
     * @author M S I
     *
     */
    public class UserMessage {
    
    	private Integer userId;
    	private String userName;
    	private String userPassword;
    	private Double userSalary;
    	private Date userBirthday;
    
    	public Integer getUserId() {
    		return userId;
    	}
    
    	public void setUserId(Integer userId) {
    		this.userId = userId;
    	}
    
    	public String getUserName() {
    		return userName;
    	}
    
    	public void setUserName(String userName) {
    		this.userName = userName;
    	}
    
    	public String getUserPassword() {
    		return userPassword;
    	}
    
    	public void setUserPassword(String userPassword) {
    		this.userPassword = userPassword;
    	}
    
    	public Double getUserSalary() {
    		return userSalary;
    	}
    
    	public void setUserSalary(Double userSalary) {
    		this.userSalary = userSalary;
    	}
    
    	public Date getUserBirthday() {
    		return userBirthday;
    	}
    
    	public void setUserBirthday(Date userBirthday) {
    		this.userBirthday = userBirthday;
    	}
    
    	@Override
    	public String toString() {
    		return "UserMessage [userId=" + userId + ", userName=" + userName + ", userPassword=" + userPassword
    				+ ", userSalary=" + userSalary + ", userBirthday=" + userBirthday + "]";
    	}
    
    }
    
    
  • 封装查询的结果

    package com.test.dao;
    
    import java.sql.Connection;
    import java.sql.DriverManager;
    import java.sql.PreparedStatement;
    import java.sql.ResultSet;
    import java.sql.SQLException;
    import java.util.ArrayList;
    import java.util.List;
    
    import com.test.po.UserMessage;
    
    /**
     * 实现对USER_MESSAGE表进行操作的方法
     * 
     * @author M S I
     *
     */
    public class UserMessageDao {
    
    	/**
    	 * 查询USER_MESSAGE表中所有的用户信息
    	 * 
    	 * @return 查询成功返回java.util.List类型的实例,否则返回null
    	 */
    	public List<UserMessage> getAll() {
    		Connection conn = null;
    		PreparedStatement ps = null;
    		ResultSet rs = null;
    		try {
    			Class.forName("com.mysql.cj.jdbc.Driver");
    			conn = DriverManager.getConnection(
    					"jdbc:mysql://127.0.0.1:3306/test?characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai&nullCatalogMeansCurrent=true&allowPublicKeyRetrieval=true",
    					"root", "123456");
    			String sql = "select user_id,user_name,user_password,user_salary,user_birthday from user_message";
    			ps = conn.prepareStatement(sql);
    			rs = ps.executeQuery();
    			// 在关闭结果集之前将结果集中的数据备份到List集合中
    			// 1.创建List集合,用于保存结果集中所有的数据
    			List<UserMessage> list = new ArrayList<>();
    			// 2.声明实体类的变量,用于保存结果集中的一行数据
    			UserMessage user = null;
    			// 3.使用循环遍历结果集,将结果集中数据封装到List集合中
    			while(rs.next()) {
    				// 4.创建实体类的对象,可以保存结果集中的一行数据
    				user = new UserMessage();
    				// 5.将结果集当前行指定列的数据,添加到实体类对象对应的属性中
    				user.setUserId(rs.getInt("user_id"));
    				user.setUserName(rs.getString("user_name"));
    				user.setUserPassword(rs.getString("user_password"));
    				user.setUserSalary(rs.getDouble("user_salary"));
    				user.setUserBirthday(rs.getDate("user_birthday"));
    				// 6.将实体类的对象添加到List集合中
    				list.add(user);
    			}
    			// 7.循环结束后,返回List集合
    			return list;
    		} catch (ClassNotFoundException e) {
    			e.printStackTrace();
    		} catch (SQLException e) {
    			e.printStackTrace();
    		} finally {
    			if(rs != null) {
    				try {
    					rs.close();
    				} catch (SQLException e) {
    				}
    			}
    			if(ps != null) {
    				try {
    					ps.close();
    				} catch (SQLException e) {
    				}
    			}
    			if(conn != null) {
    				try {
    					conn.close();
    				} catch (SQLException e) {
    				}
    			}
    		}
    		return null;
    	}
    }
    

获得自增长主键

@Override
public int saveBusiness(String businessName) {
    try {
        // 获得数据库连接对象
        conn = DbUtil.getConnection();
        // 创建INSERT语句
        String sql = "insert into business(businessName,password) values(?,'123')";
        // 创建准备语句对象,并设置准备语句对象将要执行的INSERT语句,同时设置准备语句对象可以获得自增长主键的值
        ps = conn.prepareStatement(sql, PreparedStatement.RETURN_GENERATED_KEYS);
        // 替换准备语句对象中的问号
        ps.setString(1, businessName);
        // 使用准备语句对象执行INSERT语句,并获得INSERT语句执行后向表中添加数据的行数
        int rows = ps.executeUpdate();
        // 如果添加成功,提交事务
        if (rows > 0) {
            conn.commit();
            // 并通过准备语句对象获得自增长的主键,将主键存入结果集中(一行一列)
            rs = ps.getGeneratedKeys();
            // 从结果集中获得主键,并返回
            if (rs.next()) {
                return rs.getInt(1);
            }
        }
        // 如果添加失败,回退事务
        conn.rollback();
    } catch (ClassNotFoundException e) {
        e.printStackTrace();
    } catch (SQLException e) {
        e.printStackTrace();
    } finally {
        // 关闭与数据库相关的对象
        try {
            DbUtil.close(rs, ps, conn);
        } catch (SQLException e) {
        }
    }
    return 0;
}

动态拼接SQL语句

@Override
public List<Business> listBusiness(String businessName, String businessAddress) {
    try {
        // 获得数据库连接对象
        conn = DbUtil.getConnection();
        // 创建基本的SELECT语句
        StringBuilder sql = new StringBuilder(
            "select businessId,password,businessName,businessAddress,businessExplain,starPrice,deliveryPrice "
            + " from business where 1=1 ");
        // 根据用户输入的查询条件,拼接SELECT语句
        int num = 0;
        if (businessName != null && !businessName.trim().equals("")) {
            sql.append("and businessName like ? ");
            num = num + 1;
        }
        if (businessAddress != null && !businessAddress.trim().equals("")) {
            sql.append("and businessAddress like ?");
            num = num + 2;
        }
        // 创建准备语句对象,并设置准备语句对象将要执行的SELECT语句
        ps = conn.prepareStatement(sql.toString());
        // 根据用户输入的查询条件替换准备语句对象中的问号
        if (num == 1) {
            ps.setString(1, "%" + businessName + "%");
        } else if (num == 2) {
            ps.setString(1, "%" + businessAddress + "%");
        } else if (num == 3) {
            ps.setString(1, "%" + businessName + "%");
            ps.setString(2, "%" + businessAddress + "%");
        }
        // 使用准备语句对象执行SELECT语句,并将查询的结果存入到结果集中
        rs = ps.executeQuery();
        // 在关闭结果集之前,将结果集中的数据备份到List集合中
        // 创建List集合,用于保存结果集中的多行数据
        List<Business> list = new ArrayList<>();
        // 声明领域对象变量,用于保存结果集中的一行数据
        Business business = null;
        // 使用循环遍历结果集,将结果集的数据封装到List集合中
        while(rs.next()) {
            // 创建领域对象,可以保存结果集中的一行数据
            business = new Business();
            // 获得结果集当前行指定列的数据,并将数据存入领域对象对应的属性中
            business.setBusinessId(rs.getInt("businessId"));
            business.setBusinessAddress(rs.getString("businessAddress"));
            business.setBusinessExplain(rs.getString("businessExplain"));
            business.setBusinessName(rs.getString("businessName"));
            business.setDeliveryPrice(rs.getDouble("deliveryPrice"));
            business.setPassword(rs.getString("password"));
            business.setStarPrice(rs.getDouble("starPrice"));
            // 将封装数据后的领域对象添加到List中
            list.add(business);
        }
        // 循环结束后返回List集合
        return list;
    } catch (ClassNotFoundException e) {
        e.printStackTrace();
    } catch (SQLException e) {
        e.printStackTrace();
    } finally {
        // 关闭与数据库相关的对象
        try {
            DbUtil.close(rs, ps, conn);
        } catch (SQLException e) {				
        }
    }
    return null;
}

HTML

  • HTML(超文本标记语言)

  • HTML文件扩展名:.html/.htm

  • HTML文件的基本结构

    <html>
        <head>
            <!-- 通常用于放置页面的配置,引入的文件,大部分内容为用户不可见的元素 -->
        </head>
        <body>
            <!-- 通常用于存放用户可见的元素 -->
        </body>
    </html>
    
  • HTML标签:

    • <标签>....</标签>
    • <标签/>
  • HTML标签不区分大小写,建议小写。

  • HTML中常用的标签或属性:

    • <meta charset='字符集'>:设置当前页面的字符集。
    • <title>:设置页面的标题。
    • <link href='文件名路径' rel='文件类型'/>:将指定类型的文件导入到当前页面中。
    • bgcolor属性:设置元素的背景颜色。
    • background属性:设置元素的背景图片。背景图片会覆盖背景颜色。
    • <br>:换行。
    • <h1>-<h6>:标题,默认为左对齐。
    • align属性:设置水平对齐方式。left/center/reight
    • <p>:段落,段落不能嵌套段落。
    • &nbsp;:空格
    • <strong>:粗体
    • <em>:斜体
    • <a href='url'>文本</a>:超链接
    • title属性:当鼠标悬停在元素上时,显示的提示文本。
    • <img src="图片路径">:将指定的图片加载到页面中。
    • width属性:宽度。
    • height属性:高度。
    • border属性:设置元素的边框,默认为0.
    • <ol>:有序列表
    • <ul>:无序列表
    • <li>:列表项
    • <table>:表格
    • <thead>:用于存放表格中的第一行,列标题。
    • <tbody>:用于存放表格中的数据。
    • <tr>:表格中的行。
    • <th>:列标题,默认为居中对齐,默认为粗体。
    • <td>:表格中的数据,默认为左对齐。
    • valign属性:设置垂直对齐方式。
    • colspan属性:跨列。
    • 块级元素:独占一行。可以设置宽度与高度。可以包含其它的块级元素与行级元素。
    • 行级元素(行内元素,内联元素):不独占一行,从左到右依次排列,当页面宽度不足时自动换行。不能设置宽度与高度,不能包含其它的块级与行级元素
    • 块级行内元素(块级内联元素):不独占一行,但可以设置宽度与高度。
    • hidden属性:HTML5新出现,隐藏元素。
  • 表单与表单中的控件

    • <form>:不可见,可以收集用户输入的数据

    • action属性:设置表单收集数据后,提交给资源的名称。

    • method属性:设置表单提交数据的方式。只有get/post,默认为get。

    • get模式与post模式的区别

      • get模式:get模式提交的数据在浏览器地址栏中可以看到,get模式不能提交大数据。
      • post模式:post模式提交的数据在浏览器地址栏中看不到,post模式可以提交大数据。
    • <input>:根据type属性的值,呈现出不同的控件。

    • name属性:设置控件的名字,默认情况下如果控件没有设置name属性,表单收集数据时会忽略这些控件中的数据。

    • value属性:通常情况下用于设置控件的默认值。

    • placeholder属性:用于设置控件默认显示的提示信息。HTML5中出现。

    • autofocus属性:控件自动获得焦点。HTML5中出现。

    • maxlength属性:设置控件最多输入的字符数。

    • size属性:设置控件的宽度。

    • readonly属性:设置控件为只读的状态。

    • disabled属性:设置控件为不可用的状态,控件呈现灰色。

    • required属性:表单提交时,验证数据是否为空。如果数据为空,则阻止表单提交。

      <!DOCTYPE html>
      <html lang="en">
      <head>
          <meta charset="UTF-8">
          <meta http-equiv="X-UA-Compatible" content="IE=edge">
          <meta name="viewport" content="width=device-width, initial-scale=1.0">
          <title>Document</title>
      </head>
      <body>
          <form action="http://www.baidu.com" method="get">
              <!-- 隐藏表单域 -->
              <input type="hidden" name="userId" value="100"/>
              <table>
                  <tr>
                      <td>用户名:</td>
                      <td>
                          <!-- 单行文本框 -->
                          <input type="text" name="userName" autofocus="autofocus"/>
                      </td>
                  </tr>
                  <tr>
                      <td>用户密码:</td>
                      <td>
                          <!-- 密码框 -->
                          <input type="password" name="userPassword1" maxlength="20"/>
                      </td>
                  </tr>
                  <tr>
                      <td>确认密码:</td>
                      <td>
                          <input type="password" name="userPassword2" maxlength="20"/>
                      </td>
                  </tr>
                  <tr>
                      <td>用户性别:</td>
                      <td>
                          <!-- 单选按钮,name属性一致的为一组单选按钮,同组的单选按钮互斥的 -->
                          <input type="radio" name="userSex" value="0" checked="checked"/>男
                          <input type="radio" name="userSex" value="1"/>女
                      </td>
                  </tr>
                  <tr>
                      <td>城市:</td>
                      <td>
                          <!-- 复选按钮,name属性一致的为一组复选按钮 -->
                          <input type="checkbox" name="userCity" value="1"/>北京
                          <input type="checkbox" name="userCity" value="2"/>上海
                          <input type="checkbox" name="userCity" value="3" checked="checked"/>大连
                      </td>
                  </tr>
                  <tr>
                      <td>用户学历:</td>
                      <td>
                          <!-- 下拉列表/列表框:默认为下拉列表控件。添加了size属性时,控件会变为列表控件。 -->
                          <select name="userDegree">
                              <option value="1">小学</option>
                              <option value="2">中学</option>
                              <option value="3" selected="selected">大学</option>
                          </select>
                      </td>
                  </tr>
                  <tr>
                      <td>上传文件:</td>
                      <td>
                          <!-- 上传文件控件 -->
                          <input type="file"/>
                      </td>
                  </tr>
                  <tr>
                      <td>教育经历:</td>
                      <td>
                          <textarea rows="10" cols="20" placeholder="可以省略……" name="userEdu">abc</textarea>
                      </td>
                  </tr>
                  <tr>
                      <td colspan="2">
                          <!-- 点击提交按钮时,按钮所在的表单会收集用户在控件中输入的数据,并将数据提交到action属性指定的资源 -->
                          <button type="submit">提交按钮</button>
                          <!-- 将所有表单中控件的值还原为默认值 -->
                          <button type="reset">重置按钮</button>
                          <!-- 通常与JS代码配合使用 -->
                          <button type="button">普通按钮</button>
                      </td>
                  </tr>
              </table>
          </form>
      </body>
      </html>
      
    • HTML5中新出现的控件

      <!DOCTYPE html>
      <html lang="en">
      <head>
          <meta charset="UTF-8">
          <meta http-equiv="X-UA-Compatible" content="IE=edge">
          <meta name="viewport" content="width=device-width, initial-scale=1.0">
          <title>Document</title>
      </head>
      <body>
          <form action="html1.html" method="post">
              <table>
                  <tr>
                      <td>非空验证:</td>
                      <td>
                          <input type="text" name="notNull" required="required"/>
                      </td>
                  </tr>
                  <tr>
                      <td>输入数字:</td>
                      <td>
                          <input type="number" min="1" max="100" step="10" value="1" required="required" />
                      </td>
                  </tr>
                  <tr>
                      <td>输入邮箱:</td>
                      <td>
                          <input type="email" required="required"/>
                      </td>
                  </tr>
                  <tr>
                      <td>输入日期:</td>
                      <td>
                          <input type="date" required="required"/>
                      </td>
                  </tr>
                  <tr>
                      <td>输入时间:</td>
                      <td>
                          <input type="time" required="required"/>
                      </td>
                  </tr>
                  <tr>
                      <td>输入日期时间:</td>
                      <td>
                          <input type="datetime-local" required="required"/>
                      </td>
                  </tr>
                  <tr>
                      <td>输入周:</td>
                      <td>
                          <input type="week" required="required"/>
                      </td>
                  </tr>
                  <tr>
                      <td>查询条件:</td>
                      <td>
                          <input type="search" />
                      </td>
                  </tr>
                  <tr>
                      <td>DataList:</td>
                      <td>
                          <!-- 当下拉列表中数据多时,建议使用 -->
                          <!-- list属性设置DataList控件的id属性的值 -->
                          <input type="text" list="myDataList"/>
                          <!-- id属性在页面中是唯一的 -->
                          <datalist id="myDataList">
                              <option>AAA</option>
                              <option>AAB</option>
                              <option>AAC</option>
                              <option>BAA</option>
                              <option>BAB</option>
                              <option>BAC</option>
                              <option>CAA</option>
                              <option>CAB</option>
                              <option>CAC</option>
                              <option>DAA</option>
                          </datalist>
                      </td>
                  </tr>
                  <tr>
                      <td colspan="2">
                          <button type="submit">提交</button>
                      </td>
                  </tr>
              </table>
          </form>
      </body>
      </html>
      

CSS

  • CSS 指层叠样式表 (Cascading Style Sheets)

CSS的三种使用方式

  • 行内样式(内联样式):在标签中使用style属性设置当前标签的样式。此方式优先级最高

    • 格式:<标签 style="属性=值;属性=值;……">

      <!DOCTYPE html>
      <html lang="en">
      <head>
          <meta charset="UTF-8">
          <meta http-equiv="X-UA-Compatible" content="IE=edge">
          <meta name="viewport" content="width=device-width, initial-scale=1.0">
          <title>Document</title>
      </head>
      <body>
          <p style="color: red;">
              这是一个段落,这是一个段落,这是一个段落,这是一个段落,这是一个段落,这是一个段落。
          </p>
          <p style="color: red;">
              这是一个段落,这是一个段落,这是一个段落,这是一个段落,这是一个段落,这是一个段落。
          </p>
          <p style="color: red;">
              这是一个段落,这是一个段落,这是一个段落,这是一个段落,这是一个段落,这是一个段落。
          </p>
          <p style="color: red;">
              这是一个段落,这是一个段落,这是一个段落,这是一个段落,这是一个段落,这是一个段落。
          </p>
          <p style="color: red;">
              这是一个段落,这是一个段落,这是一个段落,这是一个段落,这是一个段落,这是一个段落。
          </p>
      </body>
      </html>
      
  • 内部样式:在HTML页面中使用style标签设置页面中指定元素的样式。

    • 格式:

      元素名{

      ​ 属性:值;

      ​ 属性:值;

      ​ ……

      }

      <!DOCTYPE html>
      <html lang="en">
      
      <head>
          <meta charset="UTF-8">
          <meta http-equiv="X-UA-Compatible" content="IE=edge">
          <meta name="viewport" content="width=device-width, initial-scale=1.0">
          <title>Document</title>
          <style>
              /* CSS中的注释 */
              p{
                  color:#0000AA;
                  font-size: 25px;
              }
          </style>
      </head>
      
      <body>
          <p>
              这是一个段落,这是一个段落,这是一个段落,这是一个段落,这是一个段落,这是一个段落。
          </p>
          <p>
              这是一个段落,这是一个段落,这是一个段落,这是一个段落,这是一个段落,这是一个段落。
          </p>
          <p>
              这是一个段落,这是一个段落,这是一个段落,这是一个段落,这是一个段落,这是一个段落。
          </p>
          <p>
              这是一个段落,这是一个段落,这是一个段落,这是一个段落,这是一个段落,这是一个段落。
          </p>
          <p style="color: #F00;">
              这是一个段落,这是一个段落,这是一个段落,这是一个段落,这是一个段落,这是一个段落。
          </p>
      </body>
      
      </html>
      
  • 外部样式:使用link标签导入外部的CSS文件。

CSS常用的选择器

  • 元素选择器(HTML选择器、标签选择器):设置指定元素(标签)的样式。

    <style>
        input{
            border-top: none;
            border-right: none;
            border-left: none;
            border-bottom-color: black;
        }
    </style>
    
  • 属性选择器:设置当前页面中指定属性元素的样式。

    • 格式:元素[属性=‘值’]
    • *:表示模糊查询。
    • ^:表示以指定的值开头。
    • $:表示以指定的值结尾。
    <style>
        input[type$='xt']{
            border-top: none;
            border-right: none;
            border-left: none;
            border-bottom-color: black;
        }
    </style>
    
  • ID选择器:使用#表示ID选择器。设置指定ID元素的样式。

    • 在HTML页面中id属性的值是唯一的。

    • ID选择器的效率最高的

      <style>
          #t1{
              border-top: none;
              border-right: none;
              border-left: none;
              border-bottom-color: black;
          }
          #t2{
              border-top: none;
              border-right: none;
              border-left: none;
              border-bottom-color: black;
          }
          #t3{
              border-top: none;
              border-right: none;
              border-left: none;
              border-bottom-color: black;
          }
      </style>
      
  • 群组选择器:同时设置多个元素的样式。

    • 语法:元素1,元素2,……

      <style>
          #t1,#t2,#t3{
              border-top: none;
              border-right: none;
              border-left: none;
              border-bottom-color: black;
          }
      </style>
      
  • 类选择器(Class选择器):元素中class的值可以重复的,并且class属性中可以同时出现多个值,值之间使用空格分隔。使用“.”表示类选择器。

    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
        <style>
            .t{
                border-top: none;
                border-right: none;
                border-left: none;
                border-bottom-color: black;
            }
            .t1{
                color: red;
            }
        </style>
    </head>
    <body>
        面向对象的特征:<input class="t" type="text"/>,<input class="t" type="text"/>,<input class="t t1" type="text"/>。
        <br>
        <input type="button" value="交卷">
    </body>
    </html>
    
  • 后代选择器:设置元素中的另一个元素的样式。

    • 语法:元素 元素

      <html lang="en">
      <head>
          <meta charset="UTF-8">
          <meta http-equiv="X-UA-Compatible" content="IE=edge">
          <meta name="viewport" content="width=device-width, initial-scale=1.0">
          <title>Document</title>
          <style>
              div a{
                  text-decoration: none;
              }
          </style>
      </head>
      <body>
          <div>
              <ul>
                  <li><a href="#">国内</a></li>
                  <li><a href="#">国际</a></li>
                  <li><a href="#">军事</a></li>
                  <li><a href="#">体育</a></li>
              </ul>
          </div>
          <a href="">游戏</a>
      </body>
      </html>
      
  • 子选择器:设置元素中指定第一级子元素的样式。

    • 语法:元素 > 子元素

      <!DOCTYPE html>
      <html lang="en">
      <head>
          <meta charset="UTF-8">
          <meta http-equiv="X-UA-Compatible" content="IE=edge">
          <meta name="viewport" content="width=device-width, initial-scale=1.0">
          <title>Document</title>
          <style>
              div > a{
                  color: red;
                  text-decoration: none;
              }
          </style>
      </head>
      <body>
          <div>
              <a href="">新闻</a>
              <ul>
                  <li><a href="#">国内</a></li>
                  <li><a href="#">国际</a></li>
                  <li><a href="#">军事</a></li>
                  <li><a href="#">体育</a></li>
              </ul>
              <a href="">游戏</a>
          </div>
      </body>
      </html>
      

CSS常用样式

背景样式

  • body{
        /* 背景颜色 */
        background-color: bisque;
        /* 背景图片 */
        background-image: url('images/2.png');
        /* 背景图片重复方式 */
        background-repeat: no-repeat;
        /* 背景出现的位置 */
        background-position:center;
    }
    

文本样式

  • div {
        width: 600px;
        height: 600px;
        background-color: aliceblue;
        background-image: url('./images/qq.ico');
        background-repeat: no-repeat;
        background-position: center;
        /* 设置水平对齐方式 */
        text-align: center;
    }
    
    div a {
        /* 设置超链接没有下划线 */
        text-decoration: none;
        /* 设置垂直对齐方式 */
        vertical-align: -30px;
    }
    
    div p {
        /* 为文本添加删除线 */
        text-decoration: line-through;
    }
    
    div li {
        /* 设置行高 */
        line-height: 50px;
    }
    p{
        /* 首行缩进 */
        text-indent: 25px;
    }
    

字体样式

<style>
    p{
        /* 设置字体 */
        font-family: '华文彩云1','楷体','宋体';
        /* 字体风格 */
        font-style: italic;
        /* 字体粗细 */
        font-weight: bolder;
        /* 字体大小 */
        font-size: small;
    }
</style>

尺寸样式

  • 只有块级元素才可以设置宽度与高度

    <style>
        html,body{
            height: 100%;
        }
        table{
            width: 50%;
            height: 30%;
        }
        a{
            /* 因为超链接是行级元素(内联元素),所以不能设置宽度与高度 */
            width:500px;
            height: 500px;
        }
    </style>
    

边框样式

  • table{
        width: 50%;
        height: 30%;
        /* 边框宽度 */
        /* border-width: 10px; */
        /* 边框风格 */
        /* border-style: solid; */
        /* 边框颜色 */
        /* border-color: blue; */
        /* 设置边框 */
        border: #000000 solid 2px;
    }
    

伪类样式

  • 元素名:样式

    tr:nth-child(odd){
        /* 设置奇数行背景颜色 */
        background-color: bisque;
    }
    tr:nth-child(even){
        /* 设置偶数行背景颜色 */
        background-color: azure;
    }
    tr:hover{
        /* 设置当鼠标经过元素时 */
        background-color: aquamarine;
    }  
    

鼠标样式

  • cursor:值。

    table{
        width: 50%;
        height: 30%;
        /* 设置边框 */
        border: #000000 solid 2px;
        /* 设置鼠标样式 */
        cursor: pointer;
    }
    

列表样式

  • <style>
        ul{
            /* 取消列表默认的样式 */
            list-style: none;
        }
    </style>
    

透明度样式

  • p{
        background-color: red;
        /* 设置透明度:可以使用百分比,也可以使用0-1之间的值 */
        opacity: 0.7;
    }
    

圆角样式

  • div{
        width: 600px;
        height: 600px;
        background-color: #5b5bc8;
        /* 圆角样式 */
        border-radius: 100px;
    }
    

盒子模型

外边框(margin)

  • 设置元素与其它元素之间的距离。

    div{
        width: 300px;
        height: 200px;
        background-color: red;
    
        border-width: 5px;
        border-style: solid;
    
        /* 4个值:根据顺时针设置外边框的大小 */
        /* 3个值:上,左右,下外边框的大小 */
        /* 2个值:上下,左右外边框的大小 */
        /* 1个值:设置所有外边框的大小 */
        /* margin: 10px; */
        /* 设置居中 */
        margin: 0 auto;
    }
    

内边框(padding)

  • padding的用法与margin是一致的。

  • 用于设置内容与边框之间的距离。

    <style>
        div{
            width: 300px;
            height: 200px;
            background-color: red;
    
            border-width: 5px;
            border-style: solid;
    
            /* 4个值:根据顺时针设置外边框的大小 */
            /* 3个值:上,左右,下外边框的大小 */
            /* 2个值:上下,左右外边框的大小 */
            /* 1个值:设置所有外边框的大小 */
            /* margin: 10px; */
            /* 设置居中 */
            margin: 0 auto;
    
            padding-top: 10px;
            padding-left: 50px;
        }
    </style>
    
  • 盒子模型中元素尺寸的大小:内容 + 内边距 + 边框

  • 盒子模型中元素占用空间:外边框 + 元素尺寸

元素默认的样式与CSS重置

  • /************************ css 重置 ************************/
    html,body,div,span,h1,h2,h3,h4,h5,h6,ul,li,p{
    	margin: 0;
    	padding: 0;
    }
    html,body{
    	width: 100%;
    	font-family: Helvetica Neue,Helvetica,Arial,Microsoft Yahei,Hiragino Sans GB,Heiti SC,WenQuanYi Micro Hei,sans-serif;
    }
    ul{
    	list-style: none;
    }
    a{
    	text-decoration: none;
    }
    

显示与隐藏

  • display样式

  • <style>
        div{
            border: 1px #000 solid;
            width: 100px;
            height: 100px;
            /* 将元素转换为行级元素 */
            display: inline;            
        }
    
        span{
            /* 将元素转换为块级元素 */
            display: block;
        }
        .testSpan{
            /* 隐藏元素并回收占用空间 */
            display: none;
        }
    </style>
    
  • overflow样式:当块级元素中的内容超过指定的宽度或高度时,如何处理溢出的内容。

    <style>
        div{
            width: 200px;
            height: 100px;
            border: 1px #000 solid;
            /* 默认值,不处理超出的内容 */
            /* overflow: visible; */
            /* 超出的内容隐藏 */
            /* overflow: hidden; */
            /* 超出的内容不可见,但会添加滚动条 */
            overflow: auto;
        }
    </style>
    

新盒子模型

  • 从CSS3开始出现了新盒子模型。新盒子模型以边框作为元素的大小,此时再设置内边框时,会向内扩展而不会影响元素的大小。

    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
        <style>
            div{
                width: 200px;
                height: 100px;
                border: 1px #000 solid;
                padding: 20px; 
                /* 设置使用新盒子模型 */
                box-sizing: border-box;   
            }
        </style>
    </head>
    <body>
        <div></div>
    </body>
    </html>
    

元素定位

  • 使用position样式设置元素的位置。

静态定位

  • position:static
  • 静态定位为默认的定位方式,也称为文档流定位。
  • 以页面左上角为基准,元素在页面中以从上到下,从左到右的方式进行排列。块级元素换行,行级元素不换行。

相对定位

  • position:rebative

  • 不会脱离文档流以自身在文档流中的位置为基准

  • 不回收元素占用的空间

    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
        <style>
            div{
                width: 200px;
                height: 100px;
                border: 1px #000 solid;
                padding: 20px; 
                /* 设置使用新盒子模型 */
                box-sizing: border-box; 
                /* 相对定位 */
                position: relative;  
                left: 50px;
                top: 50px;
            }
            a{
                display: block;
                text-decoration: none;
                color: #333;
                position: relative;
            }
            a:hover{
                color: #999;
                left: 1px;
                top: 1px;
            }
        </style>
    </head>
    <body>
        <p>这是一个段落</p>
        <p>这是一个段落</p>
        <div></div>
        <p>这是一个段落</p>
        <p>这是一个段落</p>
        <p>这是一个段落</p>
        <hr>
        <a href="">测试超链接</a>
        <a href="">测试超链接</a>
        <a href="">测试超链接</a>
        <a href="">测试超链接</a>
        <a href="">测试超链接</a>
    </body>
    </html>
    

绝对定位

  • position:absolute

  • 脱离文档流,不受其它元素的影响。

  • 定位后之前占用的空间会被回收。

  • 如果父元素不是rebative或absolute时,以body作为基准

  • 如果父元素是rebative或absolute时时,以父元素为基准

    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
        <style>
            .d1{
                /* 当父元素不是relative或absolute时,以body作为基准 */
                width: 600px;
                height: 600px;
                background-color: chocolate;
                position: relative;
            }
            .d2{
                width: 100px;
                height: 100px;
                background-color: red;
                position: absolute;
                left: 0px;
                top: 0px;
            }
        </style>
    </head>
    <body>
        <p>这是一个段落</p>
        <p>这是一个段落</p>
        <div class="d1">
            <div class="d2"></div>
        </div>
        <p>这是一个段落</p>
        <p>这是一个段落</p>
        <p>这是一个段落</p>
        
    </body>
    </html>
    

固定定位

  • position:fixed

  • 以浏览器窗口作为基准。

  • 脱离文档流,不受其它元素的影响。

    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
        <style>
            div{
                width: 100%;
                height: 80px;
                position: fixed;
                left: 0px;
                top: 0px;
                background-color: black;
                opacity: 0.5;
            }
        </style>
    </head>
    <body>
        <div></div>
        <p>这是一个段落</p>
        <p>这是一个段落</p>
        <!-- 省略N个段落-->
    </body>
    </html>
    

使用定位进行布局的示例

  • <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
        <link href="./css/reset.css" rel="stylesheet"/>
        <style>
            .header{
                width: 100%;
                height: 80px;
                background-color: red;
            }
            .main{
                width: 100%;
                min-height: 300px;
                background-color: green;
            }
            .footer{
                width: 100%;
                height: 50px;            
                background-color: blue;
            }
        </style>
    </head>
    <body>
        <div class="header"></div>
        <div class="main">
            <p>这是一个段落</p>
            <p>这是一个段落</p>
            <p>这是一个段落</p>
            <p>这是一个段落</p>
            <p>这是一个段落</p>
            <p>这是一个段落</p>
            <p>这是一个段落</p>
            <p>这是一个段落</p>
            <p>这是一个段落</p>
            <p>这是一个段落</p>
        </div>
        <div class="footer"></div>
    </body>
    </html>
    

z-index样式

  • 当元素的定位方式为绝对定位或固定定位时,这些元素都会脱离文档流。如果有多个元素都是此种定位方式,可能会出现相互覆盖的效果。可以使用z-index样式设置元素的等级,等级高的元素会覆盖等级低的元素。

  • <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
        <style>
            
            .one{
                width: 200px;
                height: 200px;
                background-color: red;
                position: absolute;
                left: 50px;
                top: 50px;
                z-index: 2;
            }
            .two{
                width: 200px;
                height: 200px;
                background-color: blue;
                position: absolute;
                left: 100px;
                top: 100px;
                z-index: 1;
            }
        </style>
    </head>
    <body>
        <div class="one"></div>
        <div class="two"></div>
    </body>
    </html>
    

弹性布局

  • display设置为flex,元素变为弹性布局。
  • 当元素变为弹性布局后,元素中的子元素会根据弹性布局的规则自动进行排序,块级与行级的特性将失效。

弹性布局的主轴与侧轴

  • 主轴:水平方向的轴。

  • 侧轴:垂直方向的轴。

  • 默认情况下,子元素根据主轴方向进行排列。

    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
        <style>
            body{
                /* 设置为弹性布局 */
                display: flex;
            }
            .item{
                width: 100px;
                height: 100px;
                box-sizing: border-box;
                background-color: orange;
                border: solid 1px black;
            }
        </style>
    </head>
    <body>    
        <div class="item">1</div>
        <div class="item">2</div>
        <div class="item">3</div>
        <div class="item">4</div>
        <div class="item">5</div>
    </body>
    </html>
    

flex-direction样式

  • 可以通过flex-direction样式修改弹性布局中子元素排列的方向。

  • row:水平方向排列,默认。

  • column:垂直方向排列。

    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
        <style>
            body{
                /* 设置为弹性布局 */
                display: flex;
                flex-direction: column;
            }
            .item{
                width: 100px;
                height: 100px;
                box-sizing: border-box;
                background-color: orange;
                border: solid 1px black;
            }
        </style>
    </head>
    <body>    
        <div class="item">1</div>
        <div class="item">2</div>
        <div class="item">3</div>
        <div class="item">4</div>
        <div class="item">5</div>
    </body>
    </html>
    

flex-wrap样式

  • 默认情况下,弹性布局中的子元素不会自动换行。

    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
        <style>
            body{
                /* 设置为弹性布局 */
                display: flex;
                /* 设置父元素宽度不足时,子元素自动换行 */
                flex-wrap: wrap;
            }
            .item{
                width: 100px;
                height: 100px;
                box-sizing: border-box;
                background-color: orange;
                border: solid 1px black;
            }
        </style>
    </head>
    <body>    
        <div class="item">1</div>
        <div class="item">2</div>
        <div class="item">3</div>
        <div class="item">4</div>
        <div class="item">5</div>
    </body>
    </html>
    

justify-content样式

  • 设置弹性布局中主轴方向对齐方式。

  • <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
        <style>
            body{
                /* 设置为弹性布局 */
                display: flex;
                /* 默认值,左对象 */
                /* justify-content: flex-start; */
                /* 右对齐 */
                /* justify-content: flex-end; */
                /* 居中对齐 */
                /* justify-content: center; */
                /* 两端对齐,最左与右的元素在父容器的边缘,其它子元素平均分布 */
                /* justify-content: space-between; */
                /* 平均分布,所以子元素两端的距离相等 */
                justify-content: space-around;
            }
            .item{
                width: 100px;
                height: 100px;
                box-sizing: border-box;
                background-color: orange;
                border: solid 1px black;
            }
        </style>
    </head>
    <body>    
        <div class="item">1</div>
        <div class="item">2</div>
        <div class="item">3</div>
        <div class="item">4</div>
        <div class="item">5</div>
    </body>
    </html>
    

align-items样式

  • 设置弹性布局中侧轴方向对齐的方式(单行)。

    body{
        /* 设置为弹性布局 */
        display: flex;
        /* 设置垂直对齐方式 */
        /* 
        flex-start: 上对齐
        center:居中对齐
        flex-end:下对齐
        */
        align-items:center;
        flex-wrap: wrap;
    }
    

align-content样式

  • 设置弹性布局中侧轴方向对齐的方式(多行)。

flex样式

  • <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
        <style>
            body{
                /* 设置为弹性布局 */
                display: flex;            
            }
            .item{
                width: 100px;
                height: 100px;
                box-sizing: border-box;
                background-color: orange;
                border: solid 1px black;
            }
        </style>
    </head>
    <body>
        <!-- 将父元素分为3份,每个子元素各占1份 -->
        <div class="item" style="flex:1;">1</div>
        <div class="item" style="flex:1;">2</div>
        <div class="item" style="flex:1;">3</div>
    </body>
    </html>
    
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
        <style>
            body{
                /* 设置为弹性布局 */
                display: flex;            
            }
            .item{
                width: 100px;
                height: 100px;
                box-sizing: border-box;
                background-color: orange;
                border: solid 1px black;
            }
        </style>
    </head>
    <body>
        <!-- 将父元素分为6份,每个子元素各占N份 -->
        <div class="item" style="flex:1;">1</div>
        <div class="item" style="flex:2;">2</div>
        <div class="item" style="flex:3;">3</div>
    </body>
    </html>
    

经典1-3-1布局 (HTML)

  • <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
    </head>
    <body>
        <!-- 总容器 -->
        <div class="container">
              <!-- 头部 -->
              <header></header>
              <!-- 导航 -->
              <nav></nav>
              <!-- 主体 -->
              <div class="main">
                <!-- 左侧边框 -->
                <aside></aside>
                <!-- 内容 -->
                <section></section>
                <!-- 右侧边框 -->
                <article></article>
              </div>
              <!-- 页脚 -->
              <footer></footer>
        </div>
    </body>
    </html>
    

经典1-3-1布局 (CSS)

  • <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
        <style>
            header,nav,aside,section,article,footer{
                background-color: #666;
            }
            /* 总容器,设置宽度但不设置高度 */
            .container{
                width: 1200px;
                margin: 0 auto;
            }
            /* 设置头部 */
            .container header{
                width: 100%;
                height: 60px;
                margin-bottom: 10px;
            }
            /* 设置导航 */
            .container nav{
                width: 100%;
                height: 60px;
                margin-bottom: 10px;
            }
            /* 设置主体样式 */
            .container .main{
                width: 100%;
                margin-bottom: 10px;
                display: flex;
            }
            .container .main aside,.container .main article {
                flex: 0 0 200px;
            }
            .container .main section{
                flex: 1;
                margin: 0 10px;
            }
           
            /* 设置页脚 */
            .container footer{
                width: 100%;
                height: 60px;
                margin-bottom: 10px;
            }
        </style>
    </head>
    <body>
        <!-- 总容器 -->
        <div class="container">
              <!-- 头部 -->
              <header></header>
              <!-- 导航 -->
              <nav></nav>
              <!-- 主体 -->
              <div class="main">
                <!-- 左侧边框 -->
                <aside>
                    <p>AAAAA AAAA AAAA AAA AAA</p>
                    <p>AAAAA AAAA AAAA AAA AAA</p>
                    <p>AAAAA AAAA AAAA AAA AAA</p>
                    <p>AAAAA AAAA AAAA AAA AAA</p>
                    <p>AAAAA AAAA AAAA AAA AAA</p>
                </aside>
                <!-- 内容 -->
                <section>
                    <p>BBBBBBBBBBBBBBBBBBB</p>
                    <p>BBBBBBBBBBBBBBBBBBB</p>
                    <p>BBBBBBBBBBBBBBBBBBB</p>
                    <p>BBBBBBBBBBBBBBBBBBB</p>
                    <p>BBBBBBBBBBBBBBBBBBB</p>
                    <p>BBBBBBBBBBBBBBBBBBB</p>
                    <p>BBBBBBBBBBBBBBBBBBB</p>
                    <p>BBBBBBBBBBBBBBBBBBB</p>
                    <p>BBBBBBBBBBBBBBBBBBB</p>
                    <p>BBBBBBBBBBBBBBBBBBB</p>
                    <p>BBBBBBBBBBBBBBBBBBB</p>
                    <p>BBBBBBBBBBBBBBBBBBB</p>
                    <p>BBBBBBBBBBBBBBBBBBB</p>
                    <p>BBBBBBBBBBBBBBBBBBB</p>
                    <p>BBBBBBBBBBBBBBBBBBB</p>
                    
                </section>
                <!-- 右侧边框 -->
                <article>
                    <p>AAAAA AAAA AAAA AAA AAA</p>
                    <p>AAAAA AAAA AAAA AAA AAA</p>
                    <p>AAAAA AAAA AAAA AAA AAA</p>
                    <p>AAAAA AAAA AAAA AAA AAA</p>
                    <p>AAAAA AAAA AAAA AAA AAA</p>
                </article>
              </div>
              <!-- 页脚 -->
              <footer></footer>
        </div>
    </body>
    </html>
    

自适应高度的后台管理布局(HTML)

  • <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
    </head>
    <body>
        <!-- 总容器 -->
        <div class="container">
            <!-- 头部 -->
            <header></header>
            <!-- 中部 -->
            <div class="main">
                <!-- 左侧侧边框 -->
                <aside></aside>
                <!-- 主体 -->
                <section></section>
            </div>
            <!-- 底部 -->
            <footer></footer>
        </div>
    </body>
    </html>
    

自适应高度的后台管理布局(CSS)

  • <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
        <style>
            html,body, .container{
                width: 100%;
                height: 100%;
                margin: 0px;
                padding: 0px;
            }
            /* 将总容器设置为弹性布局,将主轴设置为垂直方向 */
            .container{
                display: flex;
                flex-direction: column;
            }
            /* 设置头部 */
            .container header{
                flex: 0 0 60px;
                background-color: #B3C0DB;
            }
            /* 设置中部 */
            .container .main{
                flex: 1;
                display: flex;
            }
            /* 设置中部侧边框 */
            .container .main aside{
                flex: 0 0 200px;
                background-color: #D3DCE6;
            }
            /* 设置中部主体内容 */
            .container .main section{
                flex: 1;
                background-color: #E9EFF3;
            }
            /* 设置底部 */
            .container footer{
                flex: 0 0 60px;
                background-color: #B3C0DB;
            }
        </style>
    </head>
    <body>
        <!-- 总容器 -->
        <div class="container">
            <!-- 头部 -->
            <header></header>
            <!-- 中部 -->
            <div class="main">
                <!-- 左侧侧边框 -->
                <aside></aside>
                <!-- 主体 -->
                <section></section>
            </div>
            <!-- 底部 -->
            <footer></footer>
        </div>
    </body>
    </html>
    

JavaScript

  • JS是基于对象的语言。
  • JS可以使用对象,可以使用现有的对象。
  • JS在浏览器中解释运行。

引用JS的两种方式

  • 方式一:在HTML页面中使用script标签,在HTML页面中插入一段JS代码。

    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
        <script>
            document.write('<div style="color:red">这是一段测试的文本</div>');
        </script>
    </head>
    <body>
    </body>
    </html>
    
  • 方法二:使用script标签导入外部的.js文件。

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
        <script src="./js/common.js"></script>   
        
    </head>
    <body>
    </body>
    </html>
    

JS中的数据类型

  • undefined:未定义类型。当声明变量但没有赋值时,返回此值。
  • boolean:只有true/false。
  • number:数字类型。
  • string:字符串类型,值必须放在一对引号中。
  • object:对象类型。null,数组,Date()
  • function:函数类型。
  • 前4种类型也称为JS中的原始数据类型。

NaN与Infinity

  • NaN:表示非数值。

  • NaN是number类型的值。

    console.log(typeof parseInt('123'));
    console.log(parseInt('abc'));
    // 判断是否为非数字的数据
    console.log(isNaN(parseInt('abc')));
    
  • Infinity:表示除数为0,也是number类型的。

运算符

算术运算符:+,-,*,/,%,++,--

  • console.log(5 / 2); // 结果为2.5
    

比较运算符:<,<=,>,>=,== ,!= ,=,!

  • // 判断数据的内容是否相等
    console.log(1 == '1');
    // 判断数据与类型是否相等
    console.log(1 === '1');
    

逻辑运算符:&& ,|| ,!

赋值运算符:=,+=,-=,*=,/=,%=

类型转换

  • parseInt():转换为整数

  • parseFloat():转换为浮点数

    console.log(parseInt('100.25'));
    console.log(parseFloat('100.25'));
    
    console.log(1 + '2'); // 结果为12
    console.log(1 + parseInt('2'));
    

变量与常量

  • 使用var关键字声明变量。

  • JavaScript是弱类型的语言。

  • 新声明变量关键字:let

  • 一个变量可以接收不同类型的数据。

    let num;
    console.log(num);
    
    num = 100;
    console.log(num);
    console.log(typeof num);
    
    num = 'abc';
    console.log(num);
    console.log(typeof num);
    
    num = new Date();
    console.log(num);
    console.log(typeof num);
    
    num = false;
    console.log(num);
    console.log(typeof num);
    
  • 声明常量:const关键字。

    const num1 = 100;
    console.log(num1);
    
    num1 = 200; // 不能重新为常量赋值
    console.log(num1);
    

函数

  • 创建函数有两种方式。

  • 方式一:

    function 函数名([参数列表]){

    ​ 函数体;

    }

    • 在函数声明时,不需要设置函数返回数据的类型。
    • 函数中如果出现return语句,则函数会返回数据。反之函数不能返回数据。
    • 一个函数可以返回类型不同的数据。
  • 方法二:

    let 变量名 = function(){

    ​ 函数体;

    }

    <script>
        function f1(){
        console.log('调用了名为f1()的方法!!!');
    }
    
    function f2(num){
        console.log(num * 100);
    }
    
    function f3(num1,num2){
        return num1 + num2;
    }
    
    function f4(num1,num2){
        if(num1 < 100){
            return num1 + num2;
        }
    }
    
    let f5 = function(){
        console.log('调用了f5()的方法');
    }
    
    f1();
    f2('1000');
    console.log(f3(100,25));
    console.log(f4(1000,20));
    
    f5();
    console.log(typeof f5);
    </script>
    

JS的作用域

  • JS中只有函数作用域,没有块(if,for,while)作用域。

  • var声明的变量,在块的外面也可以直接使用。

    var num1 = 100;
    if(num1 < 200){
        // 在if的外面可以使用
        var num2 = 200;
    }
    
    function f1(){
        // 在函数的外面不能使用
        var num3 = 300;
    }
    
    for(var i = 0 ; i < 10 ; i++){
        // 变量i在循环的外面可以使用
        console.log(i);
    }
    
    f1();
    console.log(num1);
    console.log(num2);
    console.log(i);
    console.log(num3);
    
  • 为了解决var声明变量没有块作用域的问题,所以建议声明变量时尽量使用let关键字

  • 使用let关键字声明的变量,有函数作用域,也有块作用域

数组

  • // 声明没有长度的数组
    let arr = new Array();
    // 当数组长度不足时,数组会自动扩展长度
    arr[0] = 100;
    arr[1] = 200;
    arr[2] = 300;
    
    console.log(arr.length);
    for(let i = 0 ; i < arr.length ; i++){
        console.log(arr[i]);
    }
    
  • // 创建指定长度的数组
    let arr = new Array(10);
    // 当数组长度不足时,数组会自动扩展长度
    arr[0] = 100;
    arr[1] = 200;
    arr[2] = 300;
    arr[19] = 10000;
    
    console.log(arr.length);
    for(let i = 0 ; i < arr.length ; i++){
        console.log(arr[i]);
    }
    
  • let arr = new Array();
    // JS的数组中可以存放不同类型的数据
    arr[0] = 100;
    arr[1] = 'abc';
    arr[2] = true;
    arr[9] = new Date();
    
    console.log(arr.length);
    for(let i = 0 ; i < arr.length ; i++){
        console.log(arr[i]);
    }
    
  • let arr = new Array(10,20,30,'abc');
    
    console.log(arr.length);
    for(let i = 0 ; i < arr.length ; i++){
        console.log(arr[i]);
    }
    
  • let arr = [100,200,300,'abc','def'];
    
    console.log(arr.length);
    for(let i = 0 ; i < arr.length ; i++){
    console.log(arr[i]);
    }
    

常用内置对象的API

数组

  • let array = [];
    for(let i = 0 ; i < 10 ; i++){
        // 向数组的末尾追加数据
        array.push(i);
    }
    console.log(array);
    
  • let array = [];
    for(let i = 0 ; i < 10 ; i++){
        // 向数组的头部添加数据
        array.unshift(i);
    }
    console.log(array);
    // 移除并返回数组中最后一个值
    console.log(array.pop());
    // 移除并返回数组中的第一个值
    console.log(array.shift());
    console.log(array);
    
  • let array = [45,78,12,36,57,8];
    console.log(array);
    // 排序,根据字典顺序进行排序
    array.sort();
    console.log(array);
    
    // 自定义排序规则
    let order = function(num1,num2){
        return num1 - num2;
    }
    array.sort(order);
    console.log(array);
    
    // 自定义降序排序
    array.sort(function(num1,num2){
        return num2 - num1;
    });
    console.log(array);
    
  • let array = [45,78,12,36,57,8];
    // 倒置数组
    array.reverse();
    console.log(array);
    
    let array1 = [10,20,30,40];
    let array2 = ['abc','def'];
    let array3 = [true,false];
    // 连接数组
    let array4 = array1.concat(array2,array3);
    console.log(array4)
    
    let array5 = ['2022','07','27'];
    // 根据指定的标记,将数组拼接成一个字体串,并返回。
    console.log(array5.join('-'));
    
    let date = '2000-10-20';
    // 切割字符串,并返回字符串数组
    let array6 = date.split('-');
    console.log(array6);
    

字符串

  • let str = 'abcdef1234567890abc一二三';
    // 返回字符数
    console.log(str.length);
    // 返回指定位置的字符
    console.log(str.charAt(4));
    // 查找字符串首次出现的位置,没找到返回-1
    console.log(str.indexOf('c'));
    // 查找字符串最后出现的位置,没找到返回-1
    console.log(str.lastIndexOf('c'));
    // 从下标为2的位置开始截取字符串,直到下标为6的位置之前,第二个参数可以省略
    console.log(str.substring(2,6));
    // 截取后字符串的内容不变
    console.log(str);
    // 从指定的位置开始截取指定长度的字符串,第二个参数可以省略
    console.log(str.substr(2,5));
    // 大写
    console.log(str.toUpperCase());
    // 小写
    console.log(str.toLowerCase());
    

日期

  • let date = new Date();
    console.log(date);
    // 获得日
    console.log(date.getDate());
    // 返回0-11的月份
    console.log(date.getMonth() + 1);
    // 返回4位的年
    console.log(date.getFullYear());
    // 返回从1970-1-1到创建Date对象之间的毫秒数
    console.log(date.getTime());
    
    // 获得星期,0-6
    console.log(date.getDay());
    console.log(date.getHours());
    console.log(date.getMinutes());
    console.log(date.getSeconds());
    

数学

  • // 向上取整
    console.log(Math.ceil(12.1));
    // 向下取整
    console.log(Math.floor(12.9));
    // 四舍五入,只能返回整数
    console.log(Math.round(12.25));
    // 返回大于等于0一定小于1的随机数
    console.log(Math.random());
    console.log(Math.PI);
    

BOM模型与DOM模型

  • BOM:Browser Object Model,以浏览器中window对象作为根节点的模型。
  • DOM:Document Object Model,以document作为根节点的模型。
  • BOM包含了DOM。

BOM模型

window对象

  • // 弹出带一个确定按钮的对话框
    alert('测试alert()方法!!!');
    // 弹出带两个按钮的对话框,点击确定返回true,点击取消返回false。
    confirm('确定要删除数据吗?');
    // 弹出可以接收用户输入信息的对话框
    let input = prompt();
    console.log(input);
    
  • <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
    </head>
    <body>
        <button onclick="funOpen()">打开百度</button>
        <button onclick="funClose()">关闭百度</button>
        <script>
            let win = null;
            function funOpen(){
                win = open('https://www.baidu.com');
            }
    
            function funClose(){
                if(win != null){
                    win.close();
                }
            }
        </script>
    </body>
    </html>
    
  • // 定时器,只能调用一次
    setTimeout(function(){
    // 设置跳转的url
    window.location.href = "http://www.baidu.com";
    },5000);
    // 另一种写法
    let f1 = function(){
    window.location.href = 'http://www.baidu.com';
    }
    setTimeout(f1,1000);
    
  • <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
        <script src="./js/common.js"></script>
    </head>
    <body>
        <button onclick="stop()">停止</button>
        <script>
         
            // 定时器,可以多次调用
            // setInterval(function(){
            //     console.log(formatTime(new Date()));
            // },1000);
    
            let f1 = function(){
                console.log(formatTime(new Date));
            }
    
            let timer = setInterval(f1,1000);
    
            function stop(){
                if(timer != null){
                    // 关闭定时器
                    clearInterval(timer);
                }
            }
        </script>
    </body>
    </html>
    

history对象

  • back():后退,加载历史中上一个url。

  • forward():前进,加载历史中下一个url。

  • go():值为-1相当于back(),值为1相当于forward()。

    <a href="javascript:history.go(-1);">后退</a>
    <a href="http://www.baidu.com">百度</a>
    <a href="javascript:history.go(1)">前进</a>
    

DOM模型

获得DOM对象的方法

  • getElementsByTagName("标签名"):根据标签的名字,获得页面中指定标签的元素,返回类型为数组类型。

  • getElementById("ID"):获得页面中指定ID的元素,因为页面中ID是唯一的,所以此方法返回一个数据。

  • getElementsByClassName("class"):获得页面中指定class属性的元素。因为页面中class属性的值可以重复,所以此方法返回类型为数组

  • getElementsByName("name"):获得页面中指定name属性的元素。因为页面中元素name属性的值可以重复,所以此方法返回类型为数组

    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
        <style>
            div{
                width: 400px;
                height: 400px;
                border: solid 1px black;
                margin-bottom: 10px;
            }
        </style>
    </head>
    <body>
        <div></div>
        <button id="btn1">红色</button>
        <button class="btn2">绿色</button>
        <button name="btn3">蓝色</button>
    
        <script>
            // 根据标签的名字,获得页面中指定标签的元素,返回类型为数组类型
            let divObj = document.getElementsByTagName("div")[0];
    
            // 获得id属性为btn1的元素
            let btn1 = document.getElementById("btn1");
            // 设置红色按钮单击事件
            btn1.onclick = function(){
                divObj.style.backgroundColor = '#FF0000';
            }
            // 获得class属性为btn2的元素
            let btn2 = document.getElementsByClassName("btn2")[0];
            btn2.onclick = function(){
                divObj.style.backgroundColor = '#00FF00';
            }
    
            // 获得name属性为btn3的元素
            let btn3 = document.getElementsByName("btn3")[0];
            btn3.onclick = function(){
                divObj.style.backgroundColor = '#0000FF';
            }
        </script>
    </body>
    </html>
    
  • querySelector("选择器"):获得页面中指定选择器的元素,此方法只能返回一个数据。

  • querySelectorAll("选择器"):获得页面中指定选择器的一组元素,返回类型为数组类型。

    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
        <style>
            div{
                width: 400px;
                height: 400px;
                border: solid 1px black;
                margin-bottom: 10px;
            }
        </style>
    </head>
    <body>
        <div></div>
        <button id="btn1">红色</button>
        <button class="btn2">绿色</button>
        <button name="btn3">蓝色</button>
    
        <script>
            // 使用元素选择器,获得页面中唯一一个DIV
            let divObj = document.querySelector('div');
    
            // 获得id属性为btn1的元素
            let btn1 = document.querySelector("#btn1");
            // 设置红色按钮单击事件
            btn1.onclick = function(){
                divObj.style.backgroundColor = '#FF0000';
            }
            // 获得class属性为btn2的元素
            let btn2 = document.querySelectorAll('.btn2')[0];
            btn2.onclick = function(){
                divObj.style.backgroundColor = '#00FF00';
            }
    
            // 获得name属性为btn3的元素
            let btn3 = document.querySelector('button[name="btn3"]');
            btn3.onclick = function(){
                divObj.style.backgroundColor = '#0000FF';
            }
        </script>
    </body>
    </html>
    

操作元素属性

  • 方法一:静态调用。

    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
    </head>
    <body>
        <input type="text"/>
    
        <script>
            let txt = document.querySelector("input");
            // 设置元素属性
            txt.value = parseInt(Math.random() * 100);
            // 获得元素属性
            console.log(txt.value);
        </script>
    </body>
    </html>
    
  • 方法二:

    • setAttribute('属性名','值'):设置元素属性的值。
    • getAttribute('属性名'):获得元素属性的值。
    • removeAtrribute('属性名'):移除元素中的属性。
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
    </head>
    <body>
        <input type="text" disabled/>
    
        <script>
            let txt = document.querySelector("input");
            let attributeName = "value";
            txt.setAttribute(attributeName,Math.random());
            attributeName = "title";
            txt.setAttribute(attributeName,"这是一个单行文本框");
    
            console.log(txt.getAttribute('value'));
            
            txt.removeAttribute('disabled');
        </script>
    </body>
    </html>
    

操作DOM对象

  • <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
    </head>
    <body>
        <p>
            行:<input type="number" id="rows" min="1" max="9999"/>
        </p>
        <p>
            列:<input type="number" id="cols" min="1" max="9999"/>
        </p>
        <p>
            <button id="btn1">画表格</button>
            <button id="btn2">重置</button>
        </p>
        <hr>
        <table border="1" hidden="hidden"></table>
    
        <script>
            // 获得画表格的按钮
            let btn1 = document.getElementById("btn1");
            // 设置画表格按钮的单击事件
            btn1.onclick = function(){
                // 获得用户输入的行与列的值
                let rows = document.getElementById("rows").value;
                let cols = document.querySelector("#cols").value;
                // 获得页面中的table
                let table = document.querySelector("table");
                // 在table中找到所有的tr对象
                let trArray = table.getElementsByTagName("tr");
                // 如果获得到了tr对象
                if(trArray != null && trArray.length > 0){
                    // 在table中移除找到的tr
                    for(let i = trArray.length - 1 ; i >= 0 ; i--){
                        // 移除DOM对象
                        table.removeChild(trArray[i]);
                    }
                }
    
                // 根据用户输入的行与列在页面中画表格
                // 行
                for(let i = 1 ; i <= rows ; i++){
                    // 创建DOM对象
                    let tr = document.createElement('tr');
                    // 列
                    for(let j = 1 ; j <= cols ; j++){
                        let td = document.createElement('td');
                        td.innerHTML = "&nbsp;&nbsp;&nbsp;&nbsp;";
                        // 将创建td对象添加到tr中
                        tr.appendChild(td);
                    }
                    // 将创建tr对象添加到table中
                    table.appendChild(tr);
                }
                // 移除table中hidden属性
                table.removeAttribute('hidden');
            };
    
            // 获得id属性为btn2的按钮
            let btn2 = document.querySelector('#btn2');
            // 设置btn2按钮的单击事件
            btn2.onclick = function(){
                document.getElementById("rows").value = "";
                document.getElementById("cols").value = "";
                // 向页面中table元素添加hidden属性
                document.querySelector('table').setAttribute('hidden','hidden');
            }
        </script>
    </body>
    </html>
    

事件处理

  • 方法一

    <a href="http://www.baidu.com" onclick="return f1()">跳转到百度</a>
    
    <script>
        function f1(){
            alert("程序出错!!!");
            return false;
        }
    </script>
    
  • 方法二:HTML标签与JS代码完全分离。

    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
    </head>
    <body>
        <a href="http://www.baidu.com" onclick="return f1()">跳转到百度</a>
        <button class="btn">确定</button>
    
        <script>
            // 方法一
            function f1(){
                alert("程序出错!!!");
                return false;
            }
            // 方法二
            let btn = document.querySelector('.btn');
    
            btn.onclick = function(){
                alert('点击了按钮');
            }
        </script>
    </body>
    </html>
    
  • 方法三

    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
    </head>
    <body>
        <a href="http://www.baidu.com" onclick="return f1()">跳转到百度</a>
        <button class="btn">确定</button>
        <button class="btn1">按钮</button>
    
        <script>
            // 方法一
            function f1(){
                alert("程序出错!!!");
                return false;
            }
            // 方法二
            let btn = document.querySelector('.btn');
    
            btn.onclick = function(){
                alert('点击了按钮');
            }
            // 方法三
            let btn1 = document.querySelector('.btn1');
    
            btn1.addEventListener('click',function(){
                alert('又点击了按钮');
            });
        </script>
    </body>
    </html>
    

JS加载的时机

  • window.onload():文档就绪函数。当HTML文档所有的资源全部加载完毕之后,才开始调用。

    <!DOCTYPE html>
    <html lang="en">
    
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
        <style>
            span[class$='Error'] {
                color: #FF0000;
            }
        </style>
        <script>
            window.onload = function () {
                let loginBtn = document.getElementById("loginBtn");
                let error1 = document.querySelector('.userNameError');
                let error2 = document.querySelector('.userPasswordError');
    
                loginBtn.onclick = function () {
                    error1.innerHTML = '*';
                    error2.innerHTML = '*';
    
                    let userName = document.querySelector('.userName');
                    if (userName.value === "") {
                        //alert('用户名不能为空!!!');
                        error1.innerHTML = '用户名不能为空!!!';
                        // 使控件自动获得焦点
                        userName.focus();
                        return;
                    }
    
                    let userPassword = document.getElementsByClassName('userPassword')[0];
                    if (userPassword.value === '') {
                        // alert('用户密码不能为空!!!');
                        error2.innerHTML = '用户密码不能为空!!!';
                        userPassword.focus();
                        return;
                    }
    
                    if (userPassword.value.length < 6 || userPassword.value.length > 20) {
                        // alert('用户密码在6-20位之间!!!');
                        error2.innerHTML = '用户密码在6-20位之间!!!';
                        // 选中控件中的文本
                        userPassword.select();
                        return;
                    }
                }
            }
        </script>
    </head>
    
    <body>
        <table>
            <tr>
                <td>用户姓名:</td>
                <td>
                    <input type="text" class="userName" autofocus="autofocus" />
                </td>
                <td>
                    <span class="userNameError">*</span>
                </td>
            </tr>
            <tr>
                <td>用户密码:</td>
                <td>
                    <input type="password" class="userPassword" />
                </td>
                <td>
                    <span class="userPasswordError">*</span>
                </td>
            </tr>
            <tr>
                <td colspan="2">
                    <button id="loginBtn">登录</button>
                    <button id="resetBtn">重置</button>
                </td>
            </tr>
        </table>
    
    
    </body>
    
    </html>
    

事件对象-event

  • <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
        <style>
            img{
                width: 100px;
                height: 100px;
                position: absolute;
                cursor: none;
            }
            html,body{
                cursor: none;
            }
        </style>
    </head>
    <body>
        <img src="./img/2.png">
    
        <script>
            window.onload = function(){
                // 获得图片
                let img = document.getElementsByTagName('img')[0];
    
                document.onmousemove = function(event){
                    img.style.left = event.pageX + 'px';
                    img.style.top = event.pageY + 'px';
                }
            }
        </script>
    </body>
    </html>
    

事件的冒泡与事件的捕获

  • 事件冒泡:事件从子元素传递到父元素的过程,称为事件冒泡。

  • 事件捕获:事件从父元素传递到子元素的过程,称为事件捕获。

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
        <style>
            .div1{
                width: 400px;
                height: 400px;
                background-color: #F00;
            }
            .div2{
                width: 200px;
                height: 200px;
                background-color: #00F;
            }
        </style>
    </head>
    <body>
        <div class="div1">
            <div class="div2"></div>
        </div>
    
        <script>
            window.onload = function(){
                let div1 = document.querySelector('.div1');
                let div2 = document.querySelector('.div2');
    
                div1.onclick = function(){
                    alert('父元素的单击事件');
                }
    
                div2.onclick = function(event){
                    alert('子元素的单击事件');
                    // 阻止事件冒泡
                    event.cancelBubble = true;
                }
            };
        </script>
    </body>
    </html>
    

阻止浏览器默认行为

  • <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
    </head>
    <body>
        <script>
            window.onload = function(){
                // 右键事件
                document.oncontextmenu = function(e){
                    // 阻止浏览器默认的行为
                    e.preventDefault();
                }
            }
        </script>
    </body>
    </html>
    

示例

时钟

  • <!DOCTYPE html>
    <html lang="en">
    
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
        <!-- 导入自定义的JS文件 -->
        <script src="./js/common.js"></script>
        <style>
            div {
                width: 150px;
                height: 50px;
                border: solid 1px #00F;
                margin-bottom: 10px;
                font-size: 35px;
                text-align: center;
                line-height: 50px;
            }
        </style>
    </head>
    
    <body>
        <div></div>
        <button class="start">开始</button>
        <button class="stop">停止</button>
    
        <script>
            window.onload = function () {
                let clock = document.querySelector('div');
                let start = document.querySelector('.start');
                let stop = document.querySelector('.stop');
    
                // 创建定时器,显示当前的时间
                let showTime = function () {
                    clock.innerHTML = formatTime(new Date());
                }
                showTime();
                let timer = setInterval(showTime, 1000);
                // 开始按钮的单击事件
                start.onclick = function(){
                    if(timer == 0){
                        // setInterval()方法返回类型为number,表示第N个定时器
                        timer = setInterval(showTime, 1000);           
                    }
                }
    
                // 停止按钮的单击事件
                stop.onclick = function () { 
                    if(timer !== 0){
                        clearInterval(timer);
                        timer = 0; 
                    }             
                }
            }
        </script>
    </body>
    </html>
    

全选

  • <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
    </head>
    <body>
        <table>
            <tr>
                <td><input type="checkbox" class="isSelect"/></td>
                <td>XXXXXXXXXXXXX 第一集</td>
            </tr>
            <tr>
                <td><input type="checkbox" class="isSelect"/></td>
                <td>XXXXXXXXXXXXX 第二集</td>
            </tr>
            <tr>
                <td><input type="checkbox" class="isSelect"/></td>
                <td>XXXXXXXXXXXXX 第三集</td>
            </tr>
            <tr>
                <td><input type="checkbox" class="isSelect"/></td>
                <td>XXXXXXXXXXXXX 第四集</td>
            </tr>
            <tr>
                <td><input type="checkbox" class="isSelect"/></td>
                <td>XXXXXXXXXXXXX 第五集</td>
            </tr>
            <tr>
                <td colspan="2">
                    <button class="selectAll">全部选中</button>
                    <button class="unSelectAll">全部取消</button>
                </td>
            </tr>
        </table>
    
        <script>
            window.onload = function(){
                let selectAll = document.querySelector('.selectAll');
                let selectArray = document.getElementsByClassName('isSelect');
    
                // 设置全选按钮的单击事件
                selectAll.onclick = function(){
                    for(let i = 0 ; i < selectArray.length ; i++){
                        selectArray[i].checked = true;
                    }
                }
    
                let unSelectAll = document.querySelector('.unSelectAll');
                unSelectAll.onclick = function(){
                    for(let i = 0 ; i < selectArray.length ; i++){
                        selectArray[i].checked = false;
                    }
                }
            }
        </script>
    </body>
    </html>
    
  • <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
    </head>
    <body>
        <table>
            <tr>
                <td><input type="checkbox" class="isSelect"/></td>
                <td>XXXXXXXXXXXXX 第一集</td>
            </tr>
            <tr>
                <td><input type="checkbox" class="isSelect"/></td>
                <td>XXXXXXXXXXXXX 第二集</td>
            </tr>
            <tr>
                <td><input type="checkbox" class="isSelect"/></td>
                <td>XXXXXXXXXXXXX 第三集</td>
            </tr>
            <tr>
                <td><input type="checkbox" class="isSelect"/></td>
                <td>XXXXXXXXXXXXX 第四集</td>
            </tr>
            <tr>
                <td><input type="checkbox" class="isSelect"/></td>
                <td>XXXXXXXXXXXXX 第五集</td>
            </tr>
            <tr>
                <td colspan="2">
                    <button class="selectAll" onclick="fun(true)">全部选中</button>
                    <button class="unSelectAll" onclick="fun(false)">全部取消</button>
                </td>
            </tr>
        </table>
    
        <script>                
            let selectArray = document.getElementsByClassName('isSelect');
    
            function fun(val){
                for(let i = 0 ; i < selectArray.length ; i++){
                    selectArray[i].checked = val;
                }
            }
        </script>
    </body>
    </html>
    
  • <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
    </head>
    <body>
        <table>
            <tr>
                <td><input type="checkbox" class="isSelect"/></td>
                <td>XXXXXXXXXXXXX 第一集</td>
            </tr>
            <tr>
                <td><input type="checkbox" class="isSelect"/></td>
                <td>XXXXXXXXXXXXX 第二集</td>
            </tr>
            <tr>
                <td><input type="checkbox" class="isSelect"/></td>
                <td>XXXXXXXXXXXXX 第三集</td>
            </tr>
            <tr>
                <td><input type="checkbox" class="isSelect"/></td>
                <td>XXXXXXXXXXXXX 第四集</td>
            </tr>
            <tr>
                <td><input type="checkbox" class="isSelect"/></td>
                <td>XXXXXXXXXXXXX 第五集</td>
            </tr>
            <tr>
                <td><input type="checkbox" id="selectAll"/></td>
                <td>全选</td>
            </tr>
        </table>
    
        <script>                
            let selectArray = document.getElementsByClassName('isSelect');
            let selectAll = document.getElementById('selectAll');
    
            selectAll.onclick =  function(){
                for(let i = 0 ; i < selectArray.length ; i++){
                    selectArray[i].checked = this.checked;
                }
            }
    
            // 设置除全选复选按钮外,其它所有复选按钮的单击事件
            for(let i = 0 ; i < selectArray.length ; i++){
                selectArray[i].addEventListener('click',function(){
                    // 找到所有选中的并且class属性为isSelect的元素
                    let selectCount = document.querySelectorAll('.isSelect:checked').length;
                    selectAll.checked = (selectArray.length == selectCount);
                });
            }
        </script>
    </body>
    </html>
    

轮播

  • <!DOCTYPE html>
    <html lang="en">
    
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
        <style>
            .lunbo {
                width: 1226px;
                height: 460px;
                margin: 0 auto;
                position: relative;
            }
    
            .lunbo img {
                position: absolute;
                width: 100%;
                height: 100%;
                left: 0;
                top: 0;
                display: none;
            }
        </style>
    </head>
    
    <body>
        <div class="lunbo">
            <img src="./img/lunbo1.jpg" alt="">
            <img src="./img/lunbo2.jpg" alt="">
            <img src="./img/lunbo3.jpg" alt="">
            <img src="./img/lunbo4.jpg" alt="">
            <img src="./img/lunbo5.jpg" alt="">
        </div>
    
        <script>
            window.onload = function () {
                // 获得轮播DIV中所有的图片
                let imgArray = document.querySelectorAll('.lunbo img');
                // 获得轮播图片的总数
                let imgCount = imgArray.length;
                // 设置当前轮播图片的位置
                let index = 0;
                // 显示当前的轮播图片
                imgArray[index].style.display = 'block';
    
                // 使用定时器,实现轮播效果
                setInterval(function () {
                    // 重新设置当前轮播图片的位置
                    index++;
                    // 如果超出了轮播图片的范围,将当前轮播图片的位置重置为0
                    if (index > imgCount - 1) {
                        index = 0;
                    }
                    // 无条件隐藏图片
                    for (let i = 0; i < imgArray.length; i++) {
                        imgArray[i].style.display = 'none';
                    }
                    // 显示当前轮播图片
                    imgArray[index].style.display = 'block';
                }, 2000);
            }
        </script>
    </body>
    
    </html>
    

轮播2

  • <!DOCTYPE html>
    <html lang="en">
    
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
        <style>
            .lunbo {
                width: 1226px;
                height: 460px;
                margin: 0 auto;
                position: relative;
            }
    
            .lunbo img {
                position: absolute;
                width: 100%;
                height: 100%;
                left: 0;
                top: 0;
                opacity: 0;
            }
        </style>
    </head>
    
    <body>
        <div class="lunbo">
            <img src="./img/lunbo1.jpg" alt="">
            <img src="./img/lunbo2.jpg" alt="">
            <img src="./img/lunbo3.jpg" alt="">
            <img src="./img/lunbo4.jpg" alt="">
            <img src="./img/lunbo5.jpg" alt="">
        </div>
    
        <script>
            window.onload = function () {
                // 获得轮播DIV中所有的图片
                let imgArray = document.querySelectorAll('.lunbo img');
                // 获得轮播图片的总数
                let imgCount = imgArray.length;
                // 获得当前图片的位置
                let curIndex = 0;
                // 获得上一张图片的位置
                let preIndex = imgCount - 1;
                // 设置当前图片的透明度为透明状态
                let curOpacity = 0;
                // 设置上一张图片的透明度为不透明状态
                let preOpacity = 1;
                // 设置上一张图片的透明度
                imgArray[preIndex].style.opacity = preOpacity;
    
                // 在页面打开时,先执行一次淡入淡出的操作
                showImage();
                hideImage();
    
                // 使用定时器,实现轮播图片淡入淡出的效果
                setInterval(function(){   
                    // 淡出上一张图片
                    showImage();
                    // 淡入当前图片
                    hideImage();   
                    // 保存上一张图片的位置
                    preIndex = curIndex;
                    // 重新设置当前图片的位置
                    curIndex++;
                    // 判断当前图片的位置是否越界
                    if(curIndex > imgCount - 1){
                        curIndex = 0;
                    }
                    
                },3000);
    
                // 淡入图片
                function showImage(){
                    // 重新设置当前图片的透明度为0
                    curOpacity = 0;
                    let timer = setInterval(function(){
                        // 增加当前图片的透明度
                        curOpacity += 0.03;
                        // 判断透明度增加后是否大于1
                        if(curOpacity >= 1 ){
                            // 停止定时器
                            curOpacity = 1;
                            clearInterval(timer);
                        }
                        imgArray[curIndex].style.opacity = curOpacity;
                    },40);
                }
    
                // 淡出图片
                function hideImage(){
                    preOpacity = 1;
                    let timer = setInterval(function(){                    
                        preOpacity -= 0.03;                   
                        if(preOpacity <= 0 ){                       
                            preOpacity = 0;
                            clearInterval(timer);
                        }
                        imgArray[preIndex].style.opacity = preOpacity;
                    },40);
                }
            }
        </script>
    </body>
    
    </html>
    

JS中使用正则表达式

  • <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
    </head>
    <body>
        <input type="text" class="msg">
        <button class="btn">确定</button>
    
        <script>
            window.onload = function(){
                let btn = document.querySelector('.btn');
    
                btn.onclick = function(){
                    let val = document.getElementsByTagName('input')[0].value;
                    // JS中正则表达式必须放在一对斜杠中
                    // i:不区分大小写
                    let reg = /^[a-z]+$/i;
    
                    if( !reg.test(val) ){
                        alert('Error');
                    }
                }
    
                let temp = new Date().toLocaleDateString();
                console.log(temp);
                // g:表示所有或全局
                temp = temp.replace(/\//g,"-");
    
                console.log(temp);
            }
        </script>
    </body>
    </html>
    

JSON

JSON对象与数据

  • // 创建空的JSON对象,JSON对象中的内容放在一对大括号中
    let user = {};
    // JSON中数据的格式:key: value
    user = {
        'userId': 100
    }
    // 一个JSON对象中可以存在多个键值对,键值对之间逗号分隔
    user = {
        'userId': 100,
        'userName': '张三'
    }
    // 等价于
    user = {
        userId: 100,
        userName: '张三'
    }
    
  • <!DOCTYPE html>
    <html lang="en">
    
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
    </head>
    
    <body>
        <script>
            let user = {
                'userId': 100,
                'userName': '张三',
                'userSex': '男',
                'userRegDate': new Date(),
                'userVip': false,
                'userAddress': null
            };
            
            console.log(user);
            console.log(user.userId);
            console.log(user.userName);
            console.log(user.userSex);
            console.log(user.userRegDate);
            console.log(user.userVip);
            console.log(user.userAddress);
    
            user.userId = 200;
            user.userName = '李四';
            console.log(user);
    
            // 使用for-in循环获得JSON对象中所有的属性名
            for(k in user){
                console.log(k + "->" + user[k]);
            }
        </script>
    </body>
    
    </html>
    

JSON对象的嵌套

  • let emp = {
        'empId': 100,
        'empName': '张三',
        'empSalary': 5000.00,
        'dept': {
            'deptId': 1,
            'deptName': '培训部'
        }
    }
    
    console.log(emp);
    console.log(emp.dept.deptName);
    

删除JSON对象中的属性

  • let emp = {
        'empId': 100,
        'empName': '张三',
        'empSalary': 5000.00,
        'dept': {
            'deptId': 1,
            'deptName': '培训部'
        }
    }
    
    console.log(emp);
    console.log(emp.dept.deptName);
    // 删除JSON对象中指定的key
    delete emp.dept;
    console.log(emp);
    // 另一种方式:key必须放在引号中
    delete emp['dept'];
    console.log(emp);
    

JSON数组

  • let array = [{
        'userId': 100,
        'userName': '张三'
    }, {
        'userId': 200,
        'userName': '李四'
    }, {
        'userId': 300,
        'userName': '王五'
    }];
    
    for(let i = 0 ; i < array.length ; i++){
        console.log(array[i]);
        console.log(array[i].userId);
        console.log(array[i].userName);
    }
    

JSON的stringify()与parse()方法

  • stringify():将JSON的对象转换为JS的字符串。

  • parse():将JS的字符串转换为JSON对象。

    <!DOCTYPE html>
    <html lang="en">
    
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
    </head>
    
    <body>
        <script>
            let array = [{
                'userId': 100,
                'userName': '张三',
                'userMessage': function () {
                    console.log(this.userId + "," + this.userName);
                }
            }, {
                'userId': 200,
                'userName': '李四',
                'userMessage': function () {
                    console.log(this.userId + "," + this.userName);
                }
            }, {
                'userId': 300,
                'userName': '王五',
                'userMessage': function () {
                    console.log(this.userId + "," + this.userName);
                }
            }];
    
            for (let i = 0; i < array.length; i++) {
                array[i].userMessage();
            }
    
            console.log(array);
            let str = JSON.stringify(array);
            console.log(str);
    
            let array1 = JSON.parse(str);
            console.log(array1);
            console.log(array1[0]);
        </script>
    </body>
    
    </html>
    
  • <!DOCTYPE html>
    <html lang="en">
    
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
    </head>
    
    <body>
        <div id="test"></div>
        <script>
            window.onload = function(){
                let user = {
                    'userId': 100,
                    'userName': '张三'
                };
    
                let div = document.getElementById("test");
                div.setAttribute('name',JSON.stringify(user));
    
                console.log(div.getAttribute("name"));
                let user1 = JSON.parse(div.getAttribute("name"));
                console.log(user1);
            }
        </script>
    </body>
    
    </html>
    

ES6

let与const

  • let不会出现变量提升的问题。

    // 报错,不会出现变量提升的问题   
    console.log(num);
    let num = 100;
    

模板字符串

  • <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
    </head>
    <body>
        <ul>
    
        </ul>
        <script>     
            let user = {
                'userId': 100,
                'userName': '张三',
                'userAge': 20
            };
            let msg = `<li>用户编号:${user.userId}</li>
                       <li>用户姓名:${user.userName}</li>
                       <li>用户年龄:${user.userAge}</li>`
    
            document.getElementsByTagName('ul')[0].innerHTML = msg;
        </script>
    </body>
    </html>
    
  • 模板字符串使用``符号,其中可以使用${}编写JS代码。

函数参数的默认值

  • function sum(num1 = 10, num2 = 20) {
        return num1 + num2;
    }
    console.log(sum());
    console.log(sum(100));
    console.log(sum(100, 200));
    

rest与for..of循环

  • rest与Java中可变长参数功能一致。

  • rest的本质是一维数组。

  • rest可以使函数传递数据时,更灵活。

  • rest格式:...参数名

  • 如果函数有多个参数,rest的参数必须出现在最后。

  • for..of循环:与JavaforEach循环一致。

    function f1(...values){
        console.log(values);
        for(let v of values){
            console.log(v);
        }
    }
    f1();
    console.log("----------------------");
    f1(100);
    console.log("----------------------");
    f1(10,20,30,40,50,60,70,80,90,100);
    

ES6箭头函数

  • ES6中为集合提供了一个名为forEach()的函数,用于遍历集合。

    function fun(...numbers){            
        numbers.forEach(function(item){
            console.log(item + 20);
        });
    }
    fun(10,20,30,40,50,60);
    
  • 当箭头函数只有一个参数时,参数列表的小括号可以省略。

  • 如果函数体中只有一行代码时,大括号可以省略。如果大括号省略时,return关键字也必须省略。

    let f1 = function () {
        console.log("无参数无返回值");
    }
    
    let f2 = () => console.log("无参数无返回值");
    
    f1();
    f2();
    
    let f3 = function (num) {
        console.log(`一个参数无返回值,num:${num}`);
    }
    
    let f4 = num => console.log(`一个参数无返回值,num:${num}`);
    
    f3(10);
    f4(100);
    
    let f5 = function (num1, num2) {
        console.log(num1 + num2);
    }
    
    let f6 = (num1, num2) => console.log(num1 * num2);
    
    f5(10, 20);
    f6(10, 20);
    
    // 没有参数有返回值
    let f7 = function(){
        return Math.random();
    }
    
    // 没有参数有返回值
    let f8 = () => Math.random();
    
    
    console.log(f7());
    console.log(f8());
    
    // 一个参数有返回值
    let f9 = function(num){
        return num * Math.random();
    }
    
    // 一个参数有返回值
    let f10 = num => num * Math.random();
    
    console.log(f9(10));
    console.log(f10(100));
    
    // 两个参数有返回值
    let f11 = function(num1,num2){
        return num1 + num2;
    }
    
    let f12 = (num1,num2) => num1 * num2;
    
    console.log(f11(10,20));
    console.log(f12(10,20));
    
    function fun(...numbers) {
        numbers.forEach(function (item) {
            console.log(item + 20);
        });
    
        numbers.forEach(item => console.log(item * 10));
    }
    fun(10, 20, 30, 40, 50, 60);
    
  • 使用箭头函数返回JSON对象。

    let f1 = function(userId,userName){
        let user = {
            'userId': userId,
            'userName': userName
        }
        return user;
    }
    console.log(f1(100,'张三'));
    
    let f2 = (userId,userName) => ({'userId':userId,'userName':userName})
    console.log(f2(200,'李四'));
    
  • 示例

    let array = [10, 45, 67, 36, 78, 9];
    // 升序排序
    array.sort(function (num1, num2) {
        return num1 - num2;
    });
    console.log(array);
    // 降序排序
    array.sort((num1, num2) => num2 - num1);
    console.log(array);
    

箭头函数与普通函数的区别

  • 普通函数的this关键字,永远指向调用函数的对象。

  • 箭头函数的this关键字,永远指定其定义的环境(上下文),任何方法都不能改变其指向。

    <!DOCTYPE html>
    <html lang="en">
    
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
    </head>
    
    <body>
        <input type="text">
        <script>
            window.onload = () => {
                let input = document.getElementsByTagName("input")[0];
    
                // input.onchange = function(){
                //     console.log(this.value);
                //     console.log(this);
                // }
    
                input.onchange = ()=>{
                    console.log(this.value);
                    console.log(this);
                }
    
                let user = {
                    'userId': 100,
                    'userName': '张三',
                    'userMessage': function(){
                        console.log('调用了userMessage函数');
                        console.log(this);
                    },
                    'userMessage1':() => {
                        console.log('调用了userMessage1函数');
                        console.log(this);
                    }
                };
    
                user.userMessage();
                user.userMessage1();
            }
        </script>
    </body>
    
    </html>
    

使用函数模仿类

  • // 通过函数模拟类
    function Person(name,age){
        this.name = name;
        this.age = age;
    }
    // 返回类的实例
    let p = new Person('张三',20);
    let p1 = new Person('李四',30);
    
    console.log(`${p.name},${p.age}`);
    console.log(`${p1.name},${p1.age}`);
    
    console.log(typeof Person);
    
  • 原型对象:prototype

    // 通过函数模拟类
    function Person(name,age){
        this.name = name;
        this.age = age;
    }
    
    // 向模拟的Person类中添加函数
    Person.prototype.print = function(){
        console.log(`${this.name},${this.age}`);
    }
    
    // 返回类的实例
    let p = new Person('张三',20);
    let p1 = new Person('李四',30);
    
    p.print();
    p1.print();
    
    console.log(typeof Person);
    
    • 类所有的对象共享一个prototype原型对象。

      console.log(p === p1);
      console.log(p.prototype === p1.prototype);
      
    • 构造函数的原型对象prototype是所有实例对象共享的。

    • 每一个构造函数都有一个prototype属性。

  • 原型对象存在的意义是什么?

    • 共享方法,节省内存。

ES6中Class类

  • ES6中的Class的本质还是function。

基本语法

  • // 匿名类
    let Person = class{
        // 构造方法
        constructor(id = 100){
            this.id = id;
        }
    }
    
    console.log(Person);
    let p = new Person();
    console.log(p);
    console.log(p.id);
    let p1 = new Person(10);
    console.log(p1);
    console.log(p1.id);
    console.log(typeof Person);
    
  • // 命名类
    let Person = class Example {
        constructor(id, name) {
            this.id = id;
            this.name = name;
        }
    }
    console.log(Person);
    
    let p = new Person(100,'张三');
    console.log(p);
    console.log(p.id);
    console.log(p.name);
    console.log(Person.name); // 输出Example类名
    
  • // 声明类
    class Person{
        constructor(id,name,age){
            this.id = id;
            this.name = name;
            this.age = age;
        }
        print(){
            console.log(`${this.id},${this.name},${this.age}`);
        }
    }
    
    let p = new Person(100,'张三',20);
    console.log(p);
    p.print();
    console.log(typeof Person);
    

类中的方法

  • constructor构造方法

    • 类中默认的方法,如果没有在类中书写constructor()方法,则默认添加。

      class Person{
          constructor(){
              console.log('调用了构造方法');
          }
      }
      // 在new关键字的后面,自动调用构造方法
      new Person();
      
    • class Person{
          constructor(){
              // 默认返回this,也可以返回其它类型的对象
              return new Date();
          }
      }
      // 在new关键字的后面,自动调用构造方法
      console.log(new Person() instanceof Person); // false
      console.log(new Person() instanceof Date); // true
      

ES6中的模块(Module)

  • ES6出现之前JS没有模块。为了解决这个问题出了两种解决方案:CommonJS和AMD。前者用于服务器端,后者用于浏览器端。
  • 在ES6中出现了模块(Module)的概念,并且实现非常简单,所以ES6的出现,取代了CommonJS和AMD。
  • ES6的模块化设计思想是尽量静态化,在编译时确定模块的依赖翔升,以及输入与输出的变量。
  • ES6的模块主要由两个命令构成:export,import。
    • export命令:设计向外输出的接口。
    • import命令:导入模块。

export命令

  • // 声明并导出三个变量
    export let userId = 100;
    export let userName = '张三';
    export let userAge = 20;
    
  • let userId = 100;
    let userName = '张三';
    let userAge = 20;
    
    // 一次性输出内容
    export {userId,userName,userAge}
    
  • // 声明并输出方法
    export function sum(num1,num2){
        return num1 + num2;
    }
    
  • // 声明方法
    function sum(num1, num2) {
        return num1 + num2;
    }
    
    // 一次性输出内容
    export { userId, userName, userAge, sum }
    
  • export命令出现在JS的顶层,不能出现在函数或块中。

import命令

  • <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
    </head>
    <body>
        <script type="module">
            import {userId,userName,userAge,sum} from './js/test.js';
            console.log(userId);
            console.log(userName);
            console.log(userAge);
    
            console.log(sum(100,300));
        </script>
    </body>
    </html>
    

Vue.js

MVVM

  • M:Model,数据
  • V:View,视图
  • VM:ViewModel,连接M与V的工具。

Vue基本的使用与数据显示

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>

    <div id="app">
        <!-- 插值表达式:两对嵌套的大括号,将Vue对象中指定名字的数据,显示在HTML页面指定的位置 -->
        {{message}}
    </div>

    <div id="app1">
        <!-- v-text的功能与插值表达式一致,如果网速慢插值表达式会出现闪烁的情况,v-text不会 -->
        <p v-text="message"></p>
    </div>

    <div class="app2">
        <p>{{message}}</p>
        <p v-text="message"></p>
        <!-- v-html可以执行数据中的HTML与CSS代码 -->
        <p v-html="message"></p>
    </div>
    
    <!-- 导入Vue的JS文件 -->
    <script src="./js/vue.js"></script>
    <script>
        const vue = new Vue({
            // Vue操作的元素
            el: "#app",
            // 数据
            data: {
                message: '测试数据'
            }
        });

        const vue1 = new Vue({
            el: '#app1',
            data: {
                message: '测试数据1'
            }
        });

        const vue2 = new Vue({
            el: '.app2',
            data: {
                message: '<span style="color:#F00">测试数据1</span>'
            }
        });
    </script>
</body>
</html>

循环

  • <!DOCTYPE html>
    <html lang="en">
    
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
    </head>
    
    <body>
        <div id="app">
            <!-- 普通循环:v-for表示vue中的循环。 -->
            <div v-for="item in loop">{{item}}</div>
            <hr>
            <select name="" id="">
                <!-- 为循环添加索引,索引从0开始 -->
                <option v-for="(item,index) in loop">{{index}}->{{item}}</option>
            </select>
        </div>
    
        <div id="app1">
            <!-- 循环数组中的JSON对象 -->
            <table border="1" width="400px">
                <tr v-for="user in userList">
                    <td>{{user.userId}}</td>
                    <td>{{user.userName}}</td>
                    <td>{{user.userSex==0?'男':'女'}}</td>
                </tr>
            </table>
            <!-- 循环整数:从1开始循环到指定的整数 -->
            <p v-for="num in count">
                {{num}}
            </p>
        </div>
    
        <script src="./js/vue.js"></script>
        <script>
            const vue = new Vue({
                el: '#app',
                data: {
                    loop: ['AA', 'BB', 'CC', 'DD', 123, new Date().toLocaleDateString()]
                }
            });
    
            const vue1 = new Vue({
                el: '#app1',
                data: {
                    userList: [{
                        'userId': 100,
                        'userName': '张三',
                        'userSex': 0
                    }, {
                        'userId': 200,
                        'userName': '李四',
                        'userSex': 1
                    }, {
                        'userId': 300,
                        'userName': '王五',
                        'userSex': 0
                    }, {
                        'userId': 400,
                        'userName': '赵六',
                        'userSex': 1
                    }],
                    count: 10
                }
            });
        </script>
    </body>
    
    </html>
    

v-model双向绑定

  • <!DOCTYPE html>
    <html lang="en">
    
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
    </head>
    
    <body>
        <div id="app">
            <p>
                {{message}}
                <!-- v-model:数据双向绑定,视图中的数据与Vue对象中的数据会相互影响 -->
                <input type="text" v-model="message">
            </p>
            <hr>
            <p>
                用户编号:<input type="text" v-model="user.userId">
            </p>
            <p>
                用户姓名:<input type="text" v-model="user.userName">
            </p>
            <p>
                用户性别:<input type="text" v-model="user.userSex">
            </p>
            <p>
                <!-- v-on:绑定事件,当发生指定的事件时,调用Vue对象中指定名字的函数 -->
                <button v-on:click="updateUser">编辑</button>
            </p>
            <hr>
            <p>
                行:<input type="number" min="1" max="999" v-model="rowCount" v-on:change="changeRows">
            </p>
            <p>
                列:<input type="number" min="1" max="999" v-model="colCount" v-on:change="changeCols">
            </p>
            <table border="1">
                <tr v-for="r in rowArray">
                    <td v-for="c in colArray">{{r * c}}</td>
                </tr>
            </table>
        </div>
    
        <script src="./js/vue.js"></script>
        <script>
            const vue = new Vue({
                el: '#app',
                data: {
                    message: '',
                    user: {
                        'userId': 100,
                        'userName': '张三',
                        'userSex': '男'
                    },
                    rowCount: 1,
                    colCount: 1,
                    rowArray: [1],
                    colArray: [1]
                },
                // 函数
                methods: {
                    updateUser: function () {
                        console.log(this.user);
                    },
                    changeRows: function () {
                        // 根据rowCount的值,重置rowArray数组
                        this.rowArray = [];
                        for (let i = 1; i <= this.rowCount; i++) {
                            this.rowArray.push(i);
                        }
                    },
                    changeCols: function () {
                        this.colArray = [];
                        for (let i = 1; i <= this.colCount; i++) {
                            this.colArray.push(i);
                        }
                    }
                }
            });
        </script>
    </body>
    
    </html>
    

Vue3的使用

  • <!DOCTYPE html>
    <html lang="en">
    
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
    </head>
    
    <body>
    
        <div id="testApp">
            {{message}}
            <ul>
                <li v-text="user.userId"></li>
                <li v-text="user.userName"></li>
            </ul>
        </div>
    
        <!-- 导入Vue3 -->
        <script src="https://unpkg.com/vue@next"></script>
    
        <script>
            // Vue3.X
            const app = Vue.createApp({
                data() {
                    return {
                        message: '测试数据',
                        user: {
                            'userId': 100,
                            'userName': '张三'
                        }
                    }
                }
            });
            // 挂载元素
            app.mount('#testApp');
        </script>
    </body>
    
    </html>
    

computed计算属性

  • computed有缓存,当数据没有变化时computed会读取缓存中的数据,只有当数据发生变化时,才会自动调用指定的方法。

    <!DOCTYPE html>
    <html lang="en">
    
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
    </head>
    
    <body>
    
        <div id="testApp">
            <table style="width: 600px;text-align: left;">
                <thead>
                    <tr>
                        <th>序号</th>
                        <th>商品名称</th>
                        <th>商品价格</th>
                        <th>购买数量</th>
                        <th>合计</th>
                    </tr>
                </thead>
                <tbody>
                    <tr v-for="(goods,index) in goodsList">
                        <td>{{index + 1}}</td>
                        <td>{{goods.goodsName}}</td>
                        <td>{{goods.goodsPrice}}</td>
                        <td>
                            <input type="number" v-model="goods.goodsNum" style="width: 50px;border: none;outline: none;">
                        </td>
                        <td>{{goods.goodsPrice * goods.goodsNum}}</td>
                    </tr>
                    <tr>
                        <td colspan="5" style="text-align: right;">
                            合计:{{sum}}
                        </td>
                    </tr>
                </tbody>
            </table>
        </div>
    
        <script src="https://unpkg.com/vue@next"></script>
        <script>
            const app = Vue.createApp({
                data() {
                    return {
                        // 从后台服务器中得到的购物车信息
                        goodsList: [{
                            'goodsId': 100,
                            'goodsName': 'XXXXXXX-1',
                            'goodsPrice': 10.0,
                            'goodsNum': 1
                        }, {
                            'goodsId': 101,
                            'goodsName': 'XXXXXXX-2',
                            'goodsPrice': 100.0,
                            'goodsNum': 1
                        }, {
                            'goodsId': 102,
                            'goodsName': 'XXXXXXX-3',
                            'goodsPrice': 30.0,
                            'goodsNum': 1
                        }, {
                            'goodsId': 103,
                            'goodsName': 'XXXXXXX-4',
                            'goodsPrice': 50.0,
                            'goodsNum': 1
                        }, {
                            'goodsId': 104,
                            'goodsName': 'XXXXXXX-5',
                            'goodsPrice': 150.0,
                            'goodsNum': 1
                        }]
                    }
                },
                /*
                    如果多次调用一个方法,每次调用方法都会执行。
    				如果多次调用一个计算属性,如果值没有发生任何变化,则计算属性只会调用一次,后面几次直接显示结果。
                */
                computed: {
                    sum: function(){
                        let sum = 0;
                        for(goods of this.goodsList){
                            sum = sum + (goods.goodsPrice * goods.goodsNum);
                        }
                        return sum;
                    }
                }
            });
            app.mount("#testApp");
        </script>
    </body>
    
    </html>
    

watch属性

  • <!DOCTYPE html>
    <html lang="en">
    
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
    </head>
    
    <body>
        <div id="testApp">
            <p>computed示例:</p>
            <input type="text" v-model="email1" >
            <div v-text="checkEmail"></div>
            <hr>
            <p>watch示例:</p>
            <input type="text" v-model="email2">
            <div v-text="error2"></div>
        </div>
    
        <script src="https://unpkg.com/vue@next"></script> 
        <script>
            const app = Vue.createApp({
                data() {
                    return {
                        reg: /^[a-z|A-Z|0-9]+@[a-z|A-Z|0-9]+\.(com|cn)$/,
                        error1: '',
                        error2: '',
                        email1: '',
                        email2: ''
                    }
                },
                computed: {
                    checkEmail: function(){             
                        console.log('调用了计算属性的方法');    
                        if(this.email1 != '' && !this.reg.test(this.email1)){
                            return '邮箱格式不正确';
                        }else{
                            return '';
                        }
                    }
                },
                watch: {
                    email2: function(newValue,oldValue){  
                        if(newValue != '' && !this.reg.test(newValue)){
                            this.error2 = '邮箱格式不正确';
                        }else{
                            this.error2 = '';
                        }
                    }
                }
            });
            app.mount('#testApp');
        </script>
    </body>
    
    </html>
    
    • computed:有缓存,当数据没发生变化时,优先使用缓存中的数据,而不会重新执行代码,推荐使用。
    • watch:没有缓存,无论数据是否发生变化,都会重新执行代码。

v-bind与v-on

  • v-bind:用于设置标签的属性。可以使用冒号代替。v-bind:style可以简写为:style。

  • v-on:用于设置标签的事件。可以使用@代码。v-on:click可以简写为@click。

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
    </head>
    <body>
        <div id="wrapper">
            <p>
                用户姓名:
                <input type="text" v-model="userName">
                <span :style="fontColor" >{{userNameError}}</span>
            </p>
            <p>
                用户密码:
                <input type="password" v-model="userPassword">
                <span :style="fontColor">{{userPasswordError}}</span>
            </p>
            <p>
                <button @click="login">登录</button>
            </p>
        </div>
    
        <script src="https://unpkg.com/vue@next"></script>
        <script>
            const app = Vue.createApp({
                data () {
                    return {
                        fontColor: 'color:#F00',
                        userName: '',
                        userNameError: '*',
                        userPassword: '',
                        userPasswordError: '*'
                    }
                },
                methods: {
                    login: function(){
                        if(this.userName == '' || this.userName.length == 0){
                            this.userNameError = '用户名不能为空';
                            document.getElementsByTagName("input")[0].focus();
                            return;
                        }else{
                            this.userNameError = '*';
                        }
                        
                        if(this.userPassword == ''){
                            this.userPasswordError = '用户密码不能为空'
                            return;
                        }else{
                            this.userPasswordError = '*';
                        }
                    }
                }
            }).mount('#wrapper');
        </script>
    </body>
    </html>
    

操作Class属性

  • <!DOCTYPE html>
    <html lang="en">
    
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <link rel="stylesheet" href="./css/vue-08.css">
        <title>Document</title>
    </head>
    
    <body>
    
        <div id="wrapper">
            <!-- 当layout1为true时,使用panel样式。当layout2为true时,使用panel1样式 -->
            <div :class="{panel:layout1,panel1:layout2}">
                <div :class="{item:layout1,item1:layout2}"></div>
                <div :class="{item:layout1,item1:layout2}"></div>
                <div :class="{item:layout1,item1:layout2}"></div>
                <div :class="{item:layout1,item1:layout2}"></div>
            </div>
            <button @click="changeLayout(1)">水平布局</button>
            <button @click="changeLayout(2)">垂直布局</button>
        </div>
    
        <script src="https://unpkg.com/vue@next"></script>
        <script>
            const app = Vue.createApp({
                data() {
                    return {
                        layout1: true,
                        layout2: false
                    }
                },
                methods: {
                    changeLayout:function(type){
                        this.layout1 = false;
                        this.layout2 = false;
    
                        switch(type){
                            case 1:
                                this.layout1 = true;
                                break;
                            case 2:
                                this.layout2 = true;
                        }
    
                    }
                }
            }).mount('#wrapper');
        </script>
    </body>
    
    </html>
    

v-if与v-show

  • v-if:当条件为true时元素显示,否则元素隐藏。

  • v-show:当变量为true时元素显示,否则元素隐藏。

  • v-if与v-show的区别:

    • v-if:每次都会重新创建与删除元素,所以切换的消耗比较高,如果元素需要频繁切换不建议使用v-if。
    • v-show:切换时不会重新创建与删除元素,只是修改元素的display属性。所以初始渲染消耗比较高。如果元素很少被显示不建议使用v-show。
    <!DOCTYPE html>
    <html lang="en">
    
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <link rel="stylesheet" href="./css/vue-09.css">
        <title>Document</title>
    </head>
    
    <body>
    
        <!-- 总容器的开始 -->
        <div id="wrapper">
            <!-- 登录的开始 -->
            <!-- v- -->
            <div id="login-panel" v-if="showPanel === 'login'">
                <!-- 第1行 -->
                <div class="row1">
                    <p>用户名:</p>
                    <input type="text">
                </div>
                <!-- 第2行 -->
                <div class="row2">
                    <p>密码:</p>
                    <input type="password">
                </div>
                <!-- 第3行 -->
                <div class="row3">
                    <button>登录</button>
                    <button>重置</button>
                    <button @click="showDiv('register')">注册</button>
                </div>
            </div>
            <!-- 登录的结束 -->
    
            <!-- 注册的开始 -->
            <div id="register-panel" v-if="showPanel === 'register'">
                <div class="row">
                    <p>用户名:</p>
                    <input type="text">
                </div>
                <div class="row">
                    <p>密码:</p>
                    <input type="password">
                </div>
                <div class="row">
                    <p>确认密码:</p>
                    <input type="password">
                </div>
                <hr>
                <div class="row" v-show="showRow">
                    <p>邮箱:</p>
                    <input type="text">
                </div>
                <div class="row" v-show="showRow">
                    <p>联系电话:</p>
                    <input type="text">
                </div>
                <div>
                    <button>注册</button>
                    <button>重置</button>
                    <button @click="showFun">更多……</button>
                    <button @click="showDiv('login')">使用已有账号登录</button>
                </div>
            </div>
            <!-- 注册的结束 -->
        </div>
        <!-- 总容器的结束 -->
    
        <script src="https://unpkg.com/vue@next"></script>
        <script>
            const app = Vue.createApp({
                data() {
                    return {
                        showPanel: 'login',
                        showRow: false
                    }
                },
                methods: {
                    showDiv: function (type) {
                        this.showPanel = type;
                    },
                    showFun: function () {
                        this.showRow = !this.showRow;
                    }
                },
            }).mount("#wrapper");
        </script>
    </body>
    
    </html>
    

数组的变异方法

  • <!DOCTYPE html>
    <html lang="en">
    
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
    </head>
    
    <body>
        <div id="app">
            <p>
                内容:<input type="text" v-model="msg">
            </p>
            <p>
                位置:<input type="text" v-model="index">
            </p>
            <button @click="push">末尾追加</button>
            <button @click="pop">末尾移除</button>
            <button @click="unshift">开头添加</button>
            <button @click="shift">开头移除</button>
            <button @click="add">指定位置添加</button>
            <button @click="deleteItem">指定位置删除</button>
            <button @click="reverse">反转</button>
            <button @click="sort">排序</button>
            <hr>
            <ul>
                <li v-for="item in dataList">{{item}}</li>
            </ul>
        </div>
    
        <script src="https://unpkg.com/vue@next"></script>
        <script>
            const app = Vue.createApp({
                data() {
                    return {
                        dataList: ['AA', 'BB', 'CC'],
                        msg: '',
                        index: 0
                    }
                },
                methods: {
                    push: function () {
                        if (this.msg == '') {
                            return;
                        }
                        this.dataList.push(this.msg);
                        this.msg = '';
                    },
                    unshift: function () {
                        if (this.msg == '') {
                            return;
                        }
                        this.dataList.unshift(this.msg);
                        this.msg = '';
                    },
                    pop: function () {
                        if (this.dataList === null || this.dataList.length === 0) {
                            return;
                        }
                        this.dataList.pop();
                    },
                    shift: function () {
                        if (this.dataList === null || this.dataList.length === 0) {
                            return;
                        }
                        this.dataList.shift();
                    },
                    deleteItem: function () {
                        if (this.index == '' || this.index < 0 || this.index > this.dataList.length - 1) {
                            return;
                        }
                        // 从数组指定的位置开始,删除指定个数的数据
                        this.dataList.splice(this.index, 1);
                    },
                    add: function () {
                        if (this.msg == '') {
                            return;
                        }
                        if (this.index === '' || this.index < 0 || this.index > this.dataList.length - 1) {
                            return;
                        }
                        // 在数组指定的位置之前,插入第三个参数的数据
                        // 当第二个参数大于0时,表示根据第一个参数,将指定长度(第二个参数)的数据,替换为第三个参数的值
                        this.dataList.splice(this.index, 0, this.msg);
                    },
                    reverse: function () {
                        this.dataList.reverse();
                    },
                    sort: function () {
                        this.dataList.sort((item1, item2) =>  item1 - item2 );
                    }
                }
            }).mount('#app');
        </script>
    </body>
    
    </html>
    
  • <!DOCTYPE html>
    <html lang="en">
    
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
    </head>
    
    <body>
    
        <div id="app">
            <!-- 显示所有随机数的无序列表 -->
            <ul>
                <li v-for="num in numArray">{{num}}</li>
            </ul>
            <hr>
            <button @click="odd">奇数</button>
            <button @click="even">偶数</button>
            <h3>奇数</h3>
            <ul>
                <li v-for="odd in oddNumArray">{{odd}}</li>
            </ul>
            <h3>偶数</h3>
            <ul>
                <li v-for="even in evenNumArray">{{even}}</li>
            </ul>
        </div>
    
        <script src="./js/vue.global.js"></script>
        <script>
            const app = Vue.createApp({
                data() {
                    return {
                        numArray: [], // 保存所有的随机数
                        oddNumArray: [], // 保存所有的奇数
                        evenNumArray: [] // 保存所有的偶数
                    }
                },
                created() {
                    for (let i = 0; i < 10; i++) {
                        this.numArray[i] = parseInt(Math.random() * 100 + 1);
                    }
                },
                methods: {
                    odd: function () {
                        // 获得numArray数组中所有的奇数,并将奇数存入另一个数组中
                        this.oddNumArray = this.numArray.filter(function (item) {
                            if (item % 2 != 0) {
                                return item;
                            }
                        });
                    },
                    even: function(){
                        this.evenNumArray = this.numArray.filter(function(item){
                            if(item % 2 == 0){
                                return item;
                            }
                        });
                    }
                }
            }).mount('#app');
        </script>
    </body>
    
    </html>
    

表单数据的绑定

  • <!DOCTYPE html>
    <html lang="en">
    
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
    </head>
    
    <body>
    
        <div id="app">
            <table>
                <tr>
                    <td>用户名:</td>
                    <td>
                        <input type="text" v-model="user.userName">
                    </td>
                </tr>
                <tr>
                    <td>密码:</td>
                    <td>
                        <input type="password" v-model="user.userPassword1">
                    </td>
                </tr>
                <tr>
                    <td>确认密码:</td>
                    <td>
                        <input type="password" v-model="user.userPassword2">
                    </td>
                </tr>
                <tr>
                    <td>用户性别:</td>
                    <td>
                        <input type="radio" value="1" v-model="user.userSex">男
                        <input type="radio" value="2" v-model="user.userSex">女
                    </td>
                </tr>
                <tr>
                    <td>城市:</td>
                    <td>
                        <input type="checkbox" value="1" v-model="user.userCity">北京
                        <input type="checkbox" value="2" v-model="user.userCity">上海
                        <input type="checkbox" value="3" v-model="user.userCity">大连
                    </td>
                </tr>
                <tr>
                    <td>学历:</td>
                    <td>
                        <select v-model="user.userDegree">
                            <option value="1">小学</option>
                            <option value="2">中学</option>
                            <option value="3">大学</option>
                        </select>
                    </td>
                </tr>
                <tr>
                    <td>教育经历:</td>
                    <td>
                        <textarea name="" id="" cols="30" rows="10" v-model="user.userEdu"></textarea>
                    </td>
                </tr>
                <tr>
                    <td colspan="2">
                        <button @click="saveUser">注册</button>
                    </td>
                </tr>
            </table>
        </div>
    
        <script src="./js/vue.global.js"></script>
        <script>
            const app = Vue.createApp({
                data() {
                    return {
                        user: {
                            'userName': '测试用户名',
                            'userPassword1': '',
                            'userPassword2': '',
                            'userSex': '1',
                            'userCity': ['1', '3'],
                            'userDegree': '2',
                            'userEdu': ''
                        }
                    }
                },
                methods: {
                    saveUser(){
                        console.log(this.user);
                    }
                }
            }).mount('#app');
    
        </script>
    </body>
    
    </html>
    

组件(componet)

全局组件

  • <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
    </head>
    <body>
        <div id="app">
            <my-component></my-component>
            <my-component></my-component>
            <my-component></my-component>
        </div>
    
        <script src="./js/vue.global.js"></script>
    
        <script>
            const app = Vue.createApp({});
    
            // 创建全局组件,并为全局组件设置名字
            app.component('my-component',{
                template: `<ul>
                               <li>用户编号:100</li>
                               <li>用户姓名:张三</li>
                               <li>用户年龄:20</li>
                           </ul>`
            });
    
            app.mount('#app');
        </script>
    </body>
    </html>
    
  • 全局组件:只要声明,即使不使用也会初始化,影响性能

组件中的数据与方法

  • <!DOCTYPE html>
    <html lang="en">
    
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
    </head>
    
    <body>
        <div id="app">
            <my-component></my-component>
            <my-component></my-component>
            <my-component></my-component>
        </div>
    
        <script src="./js/vue.global.js"></script>
    
        <script>
            const app = Vue.createApp({});
    
            // 创建全局组件,并为全局组件设置名字
            app.component('my-component', {
                template: `<ul>
                               <li>用户编号:100</li>
                               <li>用户姓名:张三</li>
                               <li>用户年龄:20</li>
                               <li>得票总数:{{count}}</li>
                           </ul>
                           <button @click='add'>投票</button>
                           <hr>`,
                data() {
                    return {
                        count: 0
                    }
                },
                methods: {
                    add: function () {
                        this.count++;
                    }
                }
            });
    
            app.mount('#app');
        </script>
    </body>
    
    </html>
    

局部组件

  • <!DOCTYPE html>
    <html lang="en">
    
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
    </head>
    
    <body>
        <div id="app">
            <my-com></my-com>
            <my-com></my-com>
            <my-com></my-com>
            <my-com></my-com>
            <my-com></my-com>
        </div>
    
        <script src="./js/vue.global.js"></script>
    
        <script>
            // 创建局部组件
            const myCom = {
                template: `<ul>
                               <li>用户编号:100</li>
                               <li>用户姓名:张三</li>
                               <li>用户年龄:20</li>
                               <li>得票总数:{{count}}</li>
                           </ul>
                           <button @click='add'>投票</button>
                           <hr>`,
                data() {
                    return {
                        count: 0
                    }
                },
                methods: {
                    add: function () {
                        this.count++;
                    }
                }
            }
    
            const app = Vue.createApp({
                // 将局部组件以指定的名字,注册到Vue对象中
                components: {
                    'my-com': myCom
                }
            });
            app.mount('#app');
        </script>
    </body>
    
    </html>
    
  • 局部组件:如果不使用,就不会初始化,可以提高性能

组件模板

  • <!DOCTYPE html>
    <html lang="en">
    
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
    </head>
    
    <body>
        <div id="app">
            <my-com></my-com>
            <my-com></my-com>
            <my-com></my-com>
            <my-com></my-com>
            <my-com></my-com>
        </div>
    
        <!-- 组件模板:放在Vue对象挂载的DIV外面,作用:提高书写模板的效率 -->
        <template id="myTemplate">
            <ul>
                <li>用户编号:100</li>
                <li>用户姓名:张三</li>
                <li>用户年龄:20</li>
                <li>得票总数:{{count}}</li>
            </ul>
            <button @click='add'>投票</button>
            <hr>
        </template>
    
        <script src="./js/vue.global.js"></script>
    
        <script>
            // 创建局部组件
            const myCom = {
                template: '#myTemplate',
                data() {
                    return {
                        count: 0
                    }
                },
                methods: {
                    add: function () {
                        this.count++;
                    }
                }
            }
    
            const app = Vue.createApp({
                // 将局部组件以指定的名字,注册到Vue对象中
                components: {
                    'my-com': myCom
                }
            });
            app.mount('#app');
        </script>
    </body>
    
    </html>
    

父子组件

  • <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
    </head>
    <body>
        <div id="app">
            <my-com></my-com>
            <my-com></my-com>
            <my-com></my-com>
        </div>
    
        <!-- 父组件模板 -->
        <template id="myTemplate">
            <ul>
                <!-- 包含子组件 -->
                <sub-com></sub-com>
            </ul>
            <button @click="add">投票</button>
        </template>
    
        <!-- 子组件模板 -->
        <template id="subTemplate">
            <li>用户编号:100</li>
            <li>用户姓名:张三</li>
            <li>用户年龄:20</li>
            <li>得票总数:</li>
        </template>
    
        <script src="./js/vue.global.js"></script>
        <script>
            // 声明子组件
            const subCom = {
                template: '#subTemplate'
            }
            // 声明父组件
            const myCom = {
                template:'#myTemplate',
                data(){
                    return {
                        count: 0
                    }
                },
                methods: {
                    add:function(){
                        this.count++
                    }
                },
                // 在父组件中注册子组件
                components: {
                    'sub-com': subCom
                }
            }
    
            const app = Vue.createApp({
                // 在Vue对象中注册父组件
                components: {
                    'my-com': myCom
                }
            }).mount('#app');
    
        </script>
    </body>
    </html>
    

父组件向子组件传递数据

  • 组件的数据是独立。默认情况下,父子组件之间不能相互传递数据。

  • 如果父组件需要向子组件传递数据,则需要使用prop属性设置。

    <!DOCTYPE html>
    <html lang="en">
    
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
    </head>
    
    <body>
        <div id="app">
            <my-com></my-com>
            <my-com></my-com>
            <my-com></my-com>
        </div>
    
        <!-- 父组件模板 -->
        <template id="myTemplate">
            <ul>
                <!-- 使用子组件时,将数据以指定属性传递到子组件中 -->
                <sub-com :usercount="count"></sub-com>
            </ul>
            <button @click="add">投票</button>
        </template>
    
        <!-- 子组件模板 -->
        <template id="subTemplate">
            <li>用户编号:100</li>
            <li>用户姓名:张三</li>
            <li>用户年龄:20</li>
            <li>得票总数:{{usercount}}</li>
        </template>
    
        <script src="./js/vue.global.js"></script>
        <script>
            // 声明子组件
            const subCom = {
                template: '#subTemplate',
                // 在子组中使用prop设置接收数据的名字
                props: ['usercount']
            }
            // 声明父组件
            const myCom = {
                template: '#myTemplate',
                data() {
                    return {
                        count: 0
                    }
                },
                methods: {
                    add: function () {
                        this.count++
                    }
                },
                // 在父组件中注册子组件
                components: {
                    'sub-com': subCom
                }
            }
    
            const app = Vue.createApp({
                // 在Vue对象中注册父组件
                components: {
                    'my-com': myCom
                }
            }).mount('#app');
    
        </script>
    </body>
    
    </html>
    

子组件向父组件传递数据

  • 父组件不能一直监听子组件是否传递了数据。所以如果子组件需要向父组件传递数据,则子组件需要调用父组件的方法,向父组件传递数据。

  • 子组件可以使用$emit()方法触发事件/自定义事件

    <!DOCTYPE html>
    <html lang="en">
    
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
    </head>
    
    <body>
        <div id="app">
            <my-com></my-com>
            <my-com></my-com>
            <my-com></my-com>
        </div>
    
        <!-- 父组件模板 -->
        <template id="myTemplate">
            <ul :style="color">
                <!-- 使用子组件时,将数据以指定属性传递到子组件中 -->
                <sub-com :usercount="count"></sub-com>
            </ul>
            <button @click="add">投票</button>
            <sub-com2 @setcolor="setColor"></sub-com2>
        </template>
    
        <!-- 子组件模板 -->
        <template id="subTemplate">
            <li>用户编号:100</li>
            <li>用户姓名:张三</li>
            <li>用户年龄:20</li>
            <li>得票总数:{{usercount}}</li>
        </template>
    
        <!-- 子组件模板 -->
        <template id="subTemplate2">
            <input type="color" @change="colorChange">
        </template>
    
        <script src="./js/vue.global.js"></script>
        <script>
            // 声明子组件
            const subCom = {
                template: '#subTemplate',
                // 在子组中使用prop设置接收数据的名字
                props: ['usercount']
            }        
            const subCom2 = {
                template: '#subTemplate2',
                methods: {
                    colorChange: function(event){
                        // 获得触发事件控件的值
                        let color = event.path[0].value;
                        // 触发父组件自定义事件,并将值传递到父组件中
                        this.$emit('setcolor',color);
                    }
                },
            }
    
            // 声明父组件
            const myCom = {
                template: '#myTemplate',
                data() {
                    return {
                        count: 0,
                        color: 'color:#000'
                    }
                },
                methods: {
                    add: function () {
                        this.count++
                    },
                    setColor: function(color){
                        this.color = 'color:' + color;
                    }
                },
                // 在父组件中注册子组件
                components: {
                    'sub-com': subCom,
                    'sub-com2': subCom2
                }
            }
    
            const app = Vue.createApp({
                // 在Vue对象中注册父组件
                components: {
                    'my-com': myCom
                }
            }).mount('#app');
    
        </script>
    </body>
    
    </html>
    

插槽(slot)

  • 组件可以使用插槽预留出空白位置,父组件再向子组件的插槽中添加内容。

  • 插槽与prop的区别:

    • prop:只能传递字符串。

    • 插槽:可以传递HTML代码。

      <!DOCTYPE html>
      <html lang="en">
      
      <head>
          <meta charset="UTF-8">
          <meta http-equiv="X-UA-Compatible" content="IE=edge">
          <meta name="viewport" content="width=device-width, initial-scale=1.0">
          <title>Document</title>
      </head>
      
      <body>
          <div id="app">
              <my-com v-for="(user,index) in userList" :userid="user.userId" :username="user.userName" :userage="user.userAge">
                  <!-- 向子组件的插槽中添加内容 -->
                  <li><p style="color:#f00 ;">测试插槽{{index}}</p></li>
              </my-com>
          </div>
      
          <!-- 父组件模板 -->
          <template id="myTemplate">
              <ul :style="color">
                  <!-- 预留插槽 -->
                  <slot></slot>
                  <!-- 使用子组件时,将数据以指定属性传递到子组件中 -->
                  <sub-com :usercount="count" :id="userid" :name="username" :age="userage"></sub-com>
              </ul>
              <button @click="add">投票</button>
              <sub-com2 @setcolor="setColor"></sub-com2>
          </template>
      
          <!-- 子组件模板 -->
          <template id="subTemplate">
              <li>用户编号:{{id}}</li>
              <li>用户姓名:{{name}}</li>
              <li>用户年龄:{{age}}</li>
              <li>得票总数:{{usercount}}</li>
          </template>
      
          <!-- 子组件模板 -->
          <template id="subTemplate2">
              <input type="color" @change="colorChange">
          </template>
      
          <script src="./js/vue.global.js"></script>
          <script>
              // 声明子组件
              const subCom = {
                  template: '#subTemplate',
                  // 在子组中使用prop设置接收数据的名字
                  props: ['usercount', 'id', 'name', 'age']
              }
              const subCom2 = {
                  template: '#subTemplate2',
                  methods: {
                      colorChange: function (event) {
                          // 获得触发事件控件的值
                          let color = event.path[0].value;
                          // 触发父组件自定义事件,并将值传递到父组件中
                          this.$emit('setcolor', color);
                      }
                  },
              }
      
              // 声明父组件
              const myCom = {
                  template: '#myTemplate',
                  data() {
                      return {
                          count: 0,
                          color: 'color:#000'
                      }
                  },
                  methods: {
                      add: function () {
                          this.count++
                      },
                      setColor: function (color) {
                          this.color = 'color:' + color;
                      }
                  },
                  // 在父组件中注册子组件
                  components: {
                      'sub-com': subCom,
                      'sub-com2': subCom2
                  },
                  // 设置接收来自于Vue对象传递数据的属性名,均为小写
                  props: ['userid', 'username', 'userage']
              }
      
              const app = Vue.createApp({
                  // 在Vue对象中注册父组件
                  components: {
                      'my-com': myCom
                  },
                  data() {
                      return {
                          userList: [{
                              'userId': 100,
                              'userName': '张三',
                              'userAge': 20
                          }, {
                              'userId': 101,
                              'userName': '李四',
                              'userAge': 20
                          }, {
                              'userId': 102,
                              'userName': '王五',
                              'userAge': 20
                          }, {
                              'userId': 103,
                              'userName': '赵六',
                              'userAge': 20
                          }, {
                              'userId': 103,
                              'userName': '宋六',
                              'userAge': 20
                          }]
                      }
                  }
              }).mount('#app');
      
          </script>
      </body>
      
      </html>
      

Vue路由(Vue-router)

  • vue-router不包含在vue中,所以需要单独导入vue-router的JS文件。
  • Vue是单页面应用SPA(Simple Page Applicaiton)

路由基本使用

  • <!DOCTYPE html>
    <html lang="en">
    
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
    </head>
    
    <body>
    
        <div id="app">
            <!-- 5.设置路由链接 -->
            <router-link to="/home">首页</router-link>
            &nbsp;
            <router-link to="/news">新闻</router-link>
    
            <!-- 6.设置路由出口 -->
            <router-view></router-view>
        </div>
    
        <script src="./js/vue.global.js"></script>
        <script src="./js/vue-router.global.js"></script>
    
        <script>
    
            // 1.创建组件
            const Home = {
                template: '<h1>这是首页组件</h1>'
            }
            const News = {
                template: '<h1>这是新闻组件</h1>'
            }
    
            // 2.创建路由规则,设置请求与组件的映射关系
            const routes = [
                {
                    path: '/',
                    redirect: '/home'
                },
                {
                    path: '/home',
                    component: Home
                }, {
                    path: '/news',
                    component: News
                }]
    
            // 3.创建Vue路由对象
            const router = VueRouter.createRouter({
                history: VueRouter.createWebHashHistory(),
                routes: routes  // 当键与值一样时,可以简写为routes
            });
    
            const app = Vue.createApp({});
    
            // 4.设置Vue对象使用的Vue路由对象
            app.use(router);
    
            app.mount('#app');
        </script>
    </body>
    
    </html>
    

路由嵌套

  • <!DOCTYPE html>
    <html lang="en">
    
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
    </head>
    
    <body>
    
        <div id="app">
            <router-link to="/home">首页</router-link>
            &nbsp;
            <router-link to="/news">新闻</router-link>
    
            <router-view></router-view>
        </div>
    
        <!-- 1.设置首页组件模板 -->
        <template id="homeTemplate">
            <div>
                <h3>首页组件</h3>
                <ul>
                    <li>
                        <router-link to="/home/login">登录</router-link>
                    </li>
                    <li>
                        <router-link to="/home/register">注册</router-link>
                    </li>
                </ul>
                <router-view></router-view>
            </div>
        </template>
    
        <script src="./js/vue.global.js"></script>
        <script src="./js/vue-router.global.js"></script>
    
        <script>
            // 2.重新设置首页组件
            const Home = {
                template: '#homeTemplate'
            }
            const News = {
                template: '<h1>这是新闻组件</h1>'
            }
    
            // 3.创建登录与注册的子组件
            const Login = {
                template: '<h4>这是登录子组件</h4>'
            }
            const Register = {
                template: '<h4>这是注册子组件</h4>'
            }
    
            const routes = [
                {
                    path: '/',
                    redirect: '/home'
                },
                {
                    path: '/home',
                    component: Home,
                    // 4.设置子路由
                    children: [
                        {
                            path: '/home/login',
                            component: Login
                        },
                        {
                            path: '/home/register',
                            component: Register
                        }
                    ]
                }, {
                    path: '/news',
                    component: News
                }]
    
            const router = VueRouter.createRouter({
                history: VueRouter.createWebHashHistory(),
                routes: routes  // 当键与值一样时,可以简写为routes
            });
    
            const app = Vue.createApp({});
    
            app.use(router);
    
            app.mount('#app');
        </script>
    </body>
    
    </html>
    

路由传递数据方法1-params

  • <!DOCTYPE html>
    <html lang="en">
    
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
    </head>
    
    <body>
    
        <div id="app">
            <router-link to="/home">首页</router-link>
            &nbsp;
            <!-- 1.使用params传递数据 -->
            <router-link :to="{name: 'News',params:{userId:100,userName:'张三'}}">新闻</router-link>
    
            <router-view></router-view>
        </div>
    
        <template id="homeTemplate">
            <div>
                <h3>首页组件</h3>
                <ul>
                    <li>
                        <router-link to="/home/login">登录</router-link>
                    </li>
                    <li>
                        <router-link to="/home/register">注册</router-link>
                    </li>
                </ul>
                <router-view></router-view>
            </div>
        </template>
    
        <script src="./js/vue.global.js"></script>
        <script src="./js/vue-router.global.js"></script>
    
        <script>
            const Home = {
                template: '#homeTemplate'
            }
            // 2.在路由对应的组件中,获得路由传递的数据
            const News = {
                template: `<h3>新闻组件</h3>
                           <ul>
                            <li>{{$route.params.userId}}</li>
                            <li>{{$route.params.userName}}</li>
                           </ul>
                          `
            }
    
            const Login = {
                template: '<h4>这是登录子组件</h4>'
            }
            const Register = {
                template: '<h4>这是注册子组件</h4>'
            }
    
            const routes = [
                {
                    path: '/',
                    redirect: '/home'
                },
                {
                    path: '/home',
                    name: 'Home',
                    component: Home,
                    children: [
                        {
                            path: '/home/login',
                            component: Login
                        },
                        {
                            path: '/home/register',
                            component: Register
                        }
                    ]
                }, {
                    path: '/news',
                    name: 'News',
                    component: News
                }]
    
            const router = VueRouter.createRouter({
                history: VueRouter.createWebHashHistory(),
                routes: routes  // 当键与值一样时,可以简写为routes
            });
    
            const app = Vue.createApp({});
    
            app.use(router);
    
            app.mount('#app');
        </script>
    </body>
    
    </html>
    
  • 使用params方式传递数据时,如果执行刷新操作,则数据会丢失。

路由传递数据方法2-query

  • <!DOCTYPE html>
    <html lang="en">
    
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
    </head>
    
    <body>
    
        <div id="app">
            <router-link to="/home">首页</router-link>
            &nbsp;
            <!-- 2.设置使用query方式传递数据 -->
            <router-link :to="{path:'/news',query:{'userId':user.userId,'userName':user.userName}}">新闻</router-link>
    
            <router-view></router-view>
        </div>
    
        <template id="homeTemplate">
            <div>
                <h3>首页组件</h3>
                <ul>
                    <li>
                        <router-link to="/home/login">登录</router-link>
                    </li>
                    <li>
                        <router-link to="/home/register">注册</router-link>
                    </li>
                </ul>
                <router-view></router-view>
            </div>
        </template>
    
        <script src="./js/vue.global.js"></script>
        <script src="./js/vue-router.global.js"></script>
    
        <script>
            const Home = {
                template: '#homeTemplate'
            }
            const News = {
                // 3.获得query方式传递的数据
                template: `<h3>新闻组件</h3>
                           <ul>
                            <li>{{$route.query.userId}}</li>
                            <li>{{$route.query.userName}}</li>
                           </ul>
                          `
            }
    
            const Login = {
                template: '<h4>这是登录子组件</h4>'
            }
            const Register = {
                template: '<h4>这是注册子组件</h4>'
            }
    
            const routes = [
                {
                    path: '/',
                    redirect: '/home'
                },
                {
                    path: '/home',
                    name: 'Home',
                    component: Home,
                    children: [
                        {
                            path: '/home/login',
                            component: Login
                        },
                        {
                            path: '/home/register',
                            component: Register
                        }
                    ]
                }, {
                    path: '/news',
                    name: 'News',
                    component: News
                }]
    
            const router = VueRouter.createRouter({
                history: VueRouter.createWebHashHistory(),
                routes: routes  // 当键与值一样时,可以简写为routes
            });
    
            const app = Vue.createApp({
                data(){
                    return {
                        // 1.设置需要传递的数据
                        user:{
                            'userId':101,
                            'userName':'李四'
                        }
                    }
                }
            });
    
            app.use(router);
    
            app.mount('#app');
        </script>
    </body>
    
    </html>
    
  • params与query的区别:

    • params:传递的数据在浏览器地址栏中看不到,刷新页面时params传递的数据会丢失。
    • query:传递的数据在浏览器地址栏中可以看到,刷新页面时query传递的数据不会丢失

编程式路由

  • 使用JS代码实现路由的功能。

  • <!DOCTYPE html>
    <html lang="en">
    
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
    </head>
    
    <body>
    
        <div id="app">
            <!-- <router-link to="/home">首页</router-link>
            &nbsp;
            <router-link :to="{path:'/news',query:{'userId':user.userId,'userName':user.userName}}">新闻</router-link> -->
            <!-- 1.将router-link标签改为button -->
            <button @click="toHome">首页</button>
            <button @click="toNews">新闻</button>
            <router-view></router-view>
        </div>
    
        <template id="homeTemplate">
            <div>
                <h3>首页组件</h3>
                <ul>
                    <li>
                        <router-link to="/home/login">登录</router-link>
                    </li>
                    <li>
                        <router-link to="/home/register">注册</router-link>
                    </li>
                </ul>
                <router-view></router-view>
            </div>
        </template>
    
        <script src="./js/vue.global.js"></script>
        <script src="./js/vue-router.global.js"></script>
    
        <script>
            const Home = {
                template: '#homeTemplate'
            }
            const News = {
                template: `<h3>新闻组件</h3>
                           <ul>
                            <li>{{$route.query.userId}}</li>
                            <li>{{$route.query.userName}}</li>
                           </ul>
                          `
            }
    
            const Login = {
                template: '<h4>这是登录子组件</h4>'
            }
            const Register = {
                template: '<h4>这是注册子组件</h4>'
            }
    
            const routes = [
                {
                    path: '/',
                    redirect: '/home'
                },
                {
                    path: '/home',
                    name: 'Home',
                    component: Home,
                    children: [
                        {
                            path: '/home/login',
                            component: Login
                        },
                        {
                            path: '/home/register',
                            component: Register
                        }
                    ]
                }, {
                    path: '/news',
                    name: 'News',
                    component: News
                }]
    
            const router = VueRouter.createRouter({
                history: VueRouter.createWebHashHistory(),
                routes: routes  // 当键与值一样时,可以简写为routes
            });
    
            const app = Vue.createApp({
                data() {
                    return {
                        user: {
                            'userId': 101,
                            'userName': '李四'
                        }
                    }
                },
                methods: {
                    // 2.实现按钮单击事件对应的方法
                    toHome: function(){
                        this.$router.push('/home');
                    },
                    toNews: function(){
                        this.$router.push({
                            path: '/news',
                            query: {
                                'userId': this.user.userId,
                                'userName': this.user.userName
                            }
                        });
                    }
                },
            });
    
            app.use(router);
    
            app.mount('#app');
        </script>
    </body>
    
    </html>
    

编程式路由-前进/后退

  • <!DOCTYPE html>
    <html lang="en">
    
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
    </head>
    
    <body>
    
        <div id="app">       
            <button @click="toHome">首页</button>
            <button @click="toNews">新闻</button>
            <!-- 1.添加前进按钮 -->
            <button @click="toForward">前进</button>
            <router-view></router-view>
        </div>
    
        <template id="homeTemplate">
            <div>
                <h3>首页组件</h3>
                <ul>
                    <li>
                        <router-link to="/home/login">登录</router-link>
                    </li>
                    <li>
                        <router-link to="/home/register">注册</router-link>
                    </li>
                </ul>
                <router-view></router-view>
            </div>
        </template>
    
        <script src="./js/vue.global.js"></script>
        <script src="./js/vue-router.global.js"></script>
    
        <script>
            const Home = {
                template: '#homeTemplate'
            }
            const News = {
                template: `<h3>新闻组件</h3>
                           <ul>
                            <li>{{$route.query.userId}}</li>
                            <li>{{$route.query.userName}}</li>
                           </ul>
                          `
            }
    
            const Login = {
                // 2.添加后退按钮
                template: `<h4>这是登录子组件</h4>
                           <button @click="toBack">后退</button>`
                ,methods: {
                    // 4.实现后退功能
                    toBack: function(){
                        this.$router.back();
                    }
                }
            }
            const Register = {
                template: '<h4>这是注册子组件</h4>'
            }
    
            const routes = [
                {
                    path: '/',
                    redirect: '/home'
                },
                {
                    path: '/home',
                    name: 'Home',
                    component: Home,
                    children: [
                        {
                            path: '/home/login',
                            component: Login
                        },
                        {
                            path: '/home/register',
                            component: Register
                        }
                    ]
                }, {
                    path: '/news',
                    name: 'News',
                    component: News
                }]
    
            const router = VueRouter.createRouter({
                history: VueRouter.createWebHashHistory(),
                routes: routes  // 当键与值一样时,可以简写为routes
            });
    
            const app = Vue.createApp({
                data() {
                    return {
                        user: {
                            'userId': 101,
                            'userName': '李四'
                        }
                    }
                },
                methods: {
                    toHome: function(){
                        this.$router.push('/home');
                    },
                    toNews: function(){
                        this.$router.push({
                            path: '/news',
                            query: {
                                'userId': this.user.userId,
                                'userName': this.user.userName
                            }
                        });
                    },
                    toForward: function(){
                        // 3.实现前进功能
                        this.$router.forward();
                    }
                },
            });
    
            app.use(router);
    
            app.mount('#app');
        </script>
    </body>
    
    </html>
    

路由监听

  • const app = Vue.createApp({
        data() {
            return {
                user: {
                    'userId': 101,
                    'userName': '李四'
                }
            }
        },
        methods: {
            toHome: function () {
                this.$router.push('/home');
            },
            toNews: function () {
                this.$router.push({
                    path: '/news',
                    query: {
                        'userId': this.user.userId,
                        'userName': this.user.userName
                    }
                });
            },
            toForward: function () {
                this.$router.forward();
            }
        }, watch: {
            // 添加路由监听
            $route: function(newRouter,oldRouter){
                console.log(newRouter);
                console.log(oldRouter);
            }
        }
    });
    

路由守卫

  • 路由守卫与路由监听实现的功能类似。

  • 路由守卫的分类

    • 全局守卫:适用所有路由。beforeEach(路由跳转之前),afterEach(路由跳转之后)。

    • 组件内守卫:只针对一个路由组件。beforeRouterEnter(进入路由之前),beforRouterUpdate(更新路由之前),beforeRouterLeave(离开路由之前)

    • 独享守卫:只针对一个路由组件,只有一个beforeEnter(进入路由之前)事件。

    • // 创建全局路由守卫
      // next:是一个方法,表示系统的下一个动作
      router.beforeEach((to, from, next)=>{
          console.log(to);
          console.log(from);
          // ……
          next();
      });
      

Vue-cli脚手架

Vue-cli项目结构

  • node_modules目录:项目依赖包。
  • public目录:存入模板文件与静态资源。
  • src目录:开发目录。
    • assets:存放CSS、图片等资源。
    • components:组件(公用)。
    • router:路由。
    • views:视图组件。
    • App.vue:根组件。
    • main.js:项目入口。
  • package.json:项目依赖信息。
  • vue.config.js:项目配置。

TodoList练习

App.vue

  • <template>
      <h3>今日待办事件列表</h3>
      <!-- 3.使用子组件 -->
      <AddNew @submitNewItem="addNewItem"></AddNew>
      <!-- 待办事项 -->
      <TheList :list="todoList" @changeDone="changeDone"></TheList>
      <hr>
      <!-- 已完成事项 -->
      <TheList :list="doneList" :listType="true" @removeList="removeList"></TheList>
    
    </template>
    
    <script>
    // 1.导入AddNew.vue组件
    import AddNew from './components/AddNew.vue';
    import TheList from './components/TheList.vue';
    
    export default {
      // 2.设置子组件
      components: { AddNew, TheList },
      data() {
        return {
          // 4.待办事项列表
          todoList: [],
          // 已完成事项列表
          doneList: []
        }
      },
      methods: {
        // 5.完成自定义事件对应的方法
        addNewItem: function (item) {
          this.todoList.push(item);
        },
        changeDone: function (index) {
          this.doneList.push(this.todoList.splice(index, 1)[0]);
        },
        removeList: function (index) {
          this.doneList.splice(index, 1);
        }
      },
    }
    </script>
    
    <style>
    </style>
    

AddNew.vue

  • <template>
        <div class="addNew">
            <input type="text" v-model="newItem">
            <button @click="addItem">添加</button>
        </div>
    </template>
    
    <script>
    export default {
        name: 'AddNew',
        data() {
            return {
                // 新待办事项
                newItem:''
            }
        }, methods: {
            addItem: function(){
                if(this.newItem === ''){
                    alert('不能为空');
                    return;
                }
                // 将新待办事项,传递到父组件中
                this.$emit('submitNewItem',this.newItem);
                this.newItem = '';
            }
        }
    }
    </script>
    
    <!-- scoped:表示样式代码只作用于当前文件 -->
    <style scoped>
        input {
            border: none;
            outline: none;
            width: 300px;
            height: 30px;
            border: solid 1px #999;
            border-radius: 5px;
            padding-left: 10px;
        }
        button {
            border: none;
            outline: none;
            width: 80px;
            height: 36px;
            border-radius: 5px;
            margin-left: 5px;
            background-color: #42b983;
            color: #fff;
        }
    </style>
    

TheList.vue

  • <template>
        <ol>
            <li v-for="(item, index) in list" :key="index" @click="toDone(index)">{{ item }}</li>
        </ol>
    </template>
    
    <script>
    export default {
        name: 'TheList',
        props: {
            // 接收列表数据的属性名
            list: {
                type: Array,
                required: true // 必须传递的数据
            },
            // 列表类型属性名,true表示已完成事项列表,false表示待办事项列表
            listType: {
                type: Boolean,
                default: false
            }
        },
        methods: {
            toDone: function (index) {
                if(this.listType){
                    // 已完成事项
                    this.$emit('removeList', index);
                }else{
                    // 待办事项
                    // 触发父组件自定义事件,并且将索引传递给父组件
                    this.$emit('changeDone', index);
                }
            }
        },
    }
    </script>
    
    <style scoped>
    li {
        cursor: pointer;
    }
    </style>
    

Vue-cli打包编译

  • 在vue.config.js文件中对打包信息进行配置。

    const { defineConfig } = require('@vue/cli-service')
    module.exports = defineConfig({
      transpileDependencies: true,
      // 打包编译时使用相对路径
      publicPath: './',
      // 设置编译出的文件存放的目录
      outputDir: 'dist',
      // 设置静态资源存放目录
      assetsDir: 'assets'
    })
    
    
  • 在控制台中执行:npm run build

AJAX基础

  • AJAX的特点:
    • 异步
    • 页面不刷新

AJAX示例

  • AJAX中最重要的组件:XMLHttpRequest类。

  • onreadystatechange事件:可以监听readyState状态的变化。

  • readyState是XMLHttpRequest的属性,有5种状态:

    • 0:未初始化,还没有调用send()方法。
    • 1:载入,已经调用了send()方法,正在发出请求。
    • 2:载入完成,send()方法全部执行完毕,并且已经接收到了所有的响应结果。
    • 3:交互:正在解析响应的结果。
    • 4:完成:响应的结果全部解析完毕,用于可以接收响应的结果。
    <!DOCTYPE html>
    <html lang="en">
    
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
    </head>
    
    <body>
    
        <script>
            let xhr = new XMLHttpRequest();
            // 设置向服务器发出请求的模式以及URL
            xhr.open('get', 'http://api.tianapi.com/esports/index?key=键&num=10');
    
            // 向服务器发出请求
            xhr.send(null);
    
            // 监听readyState的状态
            xhr.onreadystatechange = function(){
                if(xhr.readyState == 4 && xhr.status == 200){
                    console.log(JSON.parse(xhr.responseText));
                }
            }
        </script>
    </body>
    
    </html>
    

AJAX异步

  • <script>
        let xhr = new XMLHttpRequest();
        // 设置向服务器发出请求的模式以及URL
        xhr.open('get', 'http://api.tianapi.com/esports/index?key=键&num=10');
    
        // 向服务器发出请求
        xhr.send(null);
    
        // 声明变量保存响应的结果
        let result ;
        // 监听readyState的状态
        xhr.onreadystatechange = function(){
            if(xhr.readyState == 4 && xhr.status == 200){
                // console.log(JSON.parse(xhr.responseText));
                result = xhr.responseText;
            }
        }
        // 输出undefined,此时第27行代码没有执行
        console.log(result);
    </script>
    

axios

axios发出get模式的请求

  • <!DOCTYPE html>
    <html lang="en">
    
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
    </head>
    
    <body>
    
        <script src="https://unpkg.com/axios/dist/axios.min.js"></script>
    
        <script>
            axios.get("http://api.tianapi.com/esports/index", {
                params: {
                    key: '键',
                    num: 10
                }
            }).then(function (response) {
                console.log(response);
            }).catch(function (error) {
                console.log(error);
            });
        </script>
    </body>
    
    </html>
    

axios发出post模式的请求

  • <script src="./js/axios.min.js"></script>
    
    <script>
        let params = new URLSearchParams();
        params.append('key','键');
        params.append('num','10');
    
        axios.post("http://api.tianapi.com/esports/index",params).then(function (response) {
            console.log(response);
        }).catch(function (error) {
            console.log(error);
        });
    </script>
    

axios拦截器

请求拦截器

  • <!DOCTYPE html>
    <html lang="en">
    
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
    </head>
    
    <body>
    
        <script src="./js/axios.min.js"></script>
    
        <script>
            let params = new URLSearchParams();
            params.append('key','ada67558a172bf95a50818cbfc6a4333');
            params.append('num','20');
    
            // 创建请求拦截器
            axios.interceptors.request.use(function(config){
                // 发出请求之前执行的代码
                console.log("发出请求之间执行的代码");
                return config;
            },function(error){
                // 发生异常时,处理异常的代码
            });
    
            axios.post("http://api.tianapi.com/esports/index",params).then(function (response) {
                console.log(response);
            }).catch(function (error) {
                console.log(error);
            });
        </script>
    </body>
    
    </html>
    

响应拦截器

  • <!DOCTYPE html>
    <html lang="en">
    
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
    </head>
    
    <body>
    
        <script src="./js/axios.min.js"></script>
    
        <script>
            let params = new URLSearchParams();
            params.append('key','ada67558a172bf95a50818cbfc6a4333');
            params.append('num','20');
    
            // 创建请求拦截器
            axios.interceptors.request.use(function(config){
                // 发出请求之前执行的代码
                console.log("发出请求之间执行的代码");
                return config;
            },function(error){
                // 发生异常时,处理异常的代码
            });
    
            // 创建响应拦截器
            axios.interceptors.response.use(function(response){
                // 得到响应后,执行的代码
                console.log("得到响应后执行的代码");
                return response;
            },function(error){
                // 发生异常时,处理异常的代码
            });
    
            axios.post("http://api.tianapi.com/esports/index",params).then(function (response) {
                console.log(response);
            }).catch(function (error) {
                console.log(error);
            });
        </script>
    </body>
    
    </html>
    

Vue-cli中使用axios

  • 安装axios:cnpm install axios --save
  • 安装qs:cnpm install qs --save,用于封装post请求的数据。

将axios配置到Vue全局属性中

  • main.js文件中。

    import { createApp } from 'vue'
    import App from './App.vue'
    import router from './router'
    // 导入axios
    import axios from 'axios'
    // 导入qs
    import qs from 'qs'
    
    // 设置axios基础的URL
    axios.defaults.baseURL = 'http://api.tianapi.com/';
    // 创建Vue对象
    const app = createApp(App);
    // 将axios设置到Vue对象的全局属性中
    app.config.globalProperties.$axios = axios;
    // 将qs设置到Vue对象的全局属性中
    app.config.globalProperties.$qs = qs;
    
    app.use(router).mount('#app')
    

在Vue-cli中使用axios发出get模式请求

  • <template>
      <div class="home">
        <h1>主页</h1>
        <button @click="selectItem">查询</button>
      </div>
    </template>
    
    <script>
    export default {
      name: 'HomeView',
      methods: {
        selectItem: function () {
          this.$axios.get('esports/index?key=键&num=10').then(function (response) {
            console.log(response);
          }).catch(function (error) {
            console.log(error);
          });
        }
      },
    }
    </script>
    
    

在Vue-cli中使用axios发出post模式请求

  • <template>
      <div class="home">
        <h1>主页</h1>
        <button @click="selectItem">查询</button>
      </div>
    </template>
    
    <script>
    export default {
      name: 'HomeView',
      methods: {
        selectItem: function () {
          this.$axios.post('esports/index', this.$qs.stringify({
            key: 'ada67558a172bf95a50818cbfc6a4333',
            num: '12'
          })).then(function (response) {
            console.log(response);
          }).catch(function (error) {
            console.log(error);
          });
        }
      },
    }
    </script>
    
    

跨域

  • 同源策略(Sameoriginpolicy)是一种约定。
  • 所谓同源(即指在同一个域)就是两个页面具有相同的协议(protocol),域名(host)和端口号(port)。
  • 当一个请求url的协议、域名、端口三者之间任意一个与当前页面url不同即为跨域。

使用Vue-cli的代理解决跨域问题

  • 跨域

    Access to XMLHttpRequest at 'http://v.juhe.cn/todayOnhistory/queryEvent.php' from origin 'http://localhost:8080' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
    
  • vue.config.js

    const { defineConfig } = require('@vue/cli-service')
    module.exports = defineConfig({
      transpileDependencies: true,
      devServer: {
        // 跨域代理:将以指定字符串开头的URL,开头部分替换为对应的内容
        proxy: {
          '/juhe': {
            // 替换目标的URL
            target: 'http://v.juhe.cn/',
            // 是否使用相同端口号
            changeOrigin: true,
            // 如何处理开头的内容
            pathRewrite: {
              '/juhe': ''
            }
          }
        }
      }
    })
    
  • AboutView.vue

    <template>
      <div class="about">
        <h1>关于</h1>
        <button @click="select">查询</button>
      </div>
    </template>
    
    <script>
    export default {
      name: 'AboutView',
      methods: {
        select: function () {
          this.$axios.post('/juhe/todayOnhistory/queryEvent.php', this.$qs.stringify({
            key: 'fd3b71a2f85eb7fedc35af6e70e51bf3',
            date: '8/11'
          })).then(function (response) {
            console.log(response);
          }).catch(function (error) {
            console.log(error);
          });
        }
      }
    }
    </script>
    

Vuex

  • Vuex是一个专为Vue.js应用程序开发的状态管理模式+库

  • 集中式存储管理应用的所有组件的状态(其实是管理组件需要共同访问的数据)。

    import { createStore } from 'vuex'
    
    export default createStore({
      state: {
        // 存放全局数据
        message: '测试全局数据'
      },
      getters: {
        // 存放全局方法
      },
      mutations: {
        // 存放修改全局数据的方法
        // 此部分的方法是线程安全的(同步)
      },
      actions: {
        // 功能与mutations类似
        // Actions返回的是mutations,而不是直接修改全局数据
        // Actions是线程不安全的(异步)
      },
      modules: {
        // 注册Vuex的子模块
      }
    })
    
    

Vue的生命周期

  • 什么是生命周期函数:在生命周期的某个时刻自动执行的函数。

  • Vue生命周期中有四个主要的事件:

    • 创建:创建组件时执行。
    • 挂载:DOM被挂载时执行。
    • 更新:当数据修改时执行。
    • 销毁:在元素被销毁之前立即执行。
  • 每个生命周期的事件对应两个钩子函数。

    • vue2.x钩子函数名
      • beforeCreate()
      • created()
      • beforeMount()
      • mountd()
      • beforeUpdate()
      • updated()
      • beforeDestroy()
      • destroyed()
    • vue3.x钩子函数名
      • beforeCreate()
      • created()
      • beforeMount()
      • mountd()
      • beforeUpdate()
      • updated()
      • beforeUnmount()
      • unmounted()
    <template>
      <div class="about">
        <h1>This is an about page</h1>
        <h1>{{ $store.state.message }}</h1>
        <input type="text" ref="el">
        {{ num }}
      </div>
    </template>
    
    <script>
    export default {
      name: 'AboutView',
      data() {
        return {
          msg: '测试生命周期的数据',
          num: 100
        }
      },
      beforeCreate() {
        // 创建组件之前执行,无法调用组件中的数据、函数等内容。
        console.log('beforeCreate-->' + this.msg);
      },
      created() {
        // 组件创建后执行,可以获得组件中的数据、函数等内容。
        console.log('created-->' + this.msg);
        console.log(this.$refs.el);
      },
      beforeMount() {
        // 在DOM对象挂载前执行
        console.log('beforeMount-->' + this.msg);
        console.log(this.$refs.el);
      },
      mounted() {
        // 在DOM对象挂载完毕后执行
        console.log('mounted-->' + this.msg);
        console.log(this.$refs.el);
        setTimeout(() => this.num = 1000, 2000);
      },
      beforeUpdate(){
        // 组件数据修改前执行
        console.log('beforeUpdate-->');
      },
      updated(){
        // 组件数据修改后执行
        console.log('updated-->');
      },
      beforeUnmount(){
        // 对应Vue2.x中的beforeDestroy()函数,在组件销毁前执行
        console.log('beforeUnmount-->');
      },
      unmounted(){
        // 对应Vue2.x中的destroyed()函数,在组件销毁完毕时执行
        console.log('unmounted-->');
      }
    }
    </script>
    
    

程序的模型

  • 单机模型:数据共享困难。
  • C(客户端)/S(服务器)模型
    • 必须在PC中安装客户端程序,使用程序连接服务器。
      • 缺点:对客户端PC的配置要求高,升级时成本高。
      • 优点:客户体验好。
  • B(浏览器)/S(服务器)模型
    • 优点:程序升级与维护时,成本相对低。对客户端PC配置要求低。
    • 缺点:客户体验没有C/S好。

Tomcat

  • Tomcat属于Web服务器。

配置Tomcat环境变量

  • 首先,必须先安装配置相应的JDK。
  • 再配置Tomcat的环境变量:
    • JAVA_HOME:JDK的路径
    • HOME_PATH:JDK的路径

Tomcat常用目录

  • bin目录:存放与Tomcat运行相关的类库与批处理文件。
  • conf目录:存放Tomcat配置文件。
  • lib目录:存放公有的类库,此目录下的资源当前服务器下所有的Web应用(站点)都可以使用。
  • logs目录:存放日志文件。
  • webapps目录:Web Applications,用于存放当前服务器下所有的Web应用。
  • work目录:存放JSP文件生成的.class文件。

解析URL

  • http://www.baidu.com/bbs/index.html
    • http:http协议,浏览器默认的协议。
    • www.baidu.com:域名,可以通过DNS服务器将域名解析成唯一的IP地址。也可以替换为服务器名或IP地址。
    • bbs:服务器中的目录。
    • index.html:服务器中的文件。

修改Tomcat端口号

  • Tomcat默认监听的端口:8080

  • 修改Tomcat目录中-->conf目录-->server.xml文件。

    <!-- A "Connector" represents an endpoint by which requests are received
             and responses are returned. Documentation at :
             Java HTTP Connector: /docs/config/http.html (blocking & non-blocking)
             Java AJP  Connector: /docs/config/ajp.html
             APR (HTTP/AJP) Connector: /docs/apr.html
             Define a non-SSL/TLS HTTP/1.1 Connector on port 8080
        -->
    <Connector port="8081" protocol="HTTP/1.1"
               connectionTimeout="20000"
               redirectPort="8443" />
    <!-- A "Connector" using the shared thread pool-->
    

在Eclipse中配置Tomcat

  • Window菜单->Preferences->Server->Runtime Environments

    image-20220811151735962
  • 点击Add...按钮,选择对应版本的Tomcat。

    image-20220811152041058
  • 浏览选择Tomcat目录。

    image-20220811152121217
  • 点击Finish按钮即可。

第一个Servlet示例

  • 浏览器如何访问服务器中的Servlet。

  • Servlet如何将数据传递到浏览器。

  • 公有空间与私有空间的区别

    • 公有空间:WEB-INF以外的空间称为公有空间,公有空间下的资源用户可以访问,可以下载。
    • 私有空间:WEB-INF目录称为私有空间,私有空间中的资源用户不能直接访问,不能下载。
  • WEB-INF目录中常用的文件与目录

    • web.xml文件:存放当前web项目的配置信息。
    • classes目录:存放.class文件。
    • lib目录:存放私有类库(.jar文件)。
    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="UTF-8">
    <title>Insert title here</title>
    </head>
    <body>
    	<a href="first">获得当前时间</a>
    </body>
    </html>
    
    package com.test.servlet;
    
    import java.io.IOException;
    import java.io.PrintWriter;
    import java.util.Date;
    
    import javax.servlet.ServletException;
    import javax.servlet.annotation.WebServlet;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    // 设置当前类为Servlet,并设置访问的URL
    @WebServlet(urlPatterns = "/first")
    public class FirstServlet extends HttpServlet {
    
    	@Override
    	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    		// 获得向浏览器中输出数据的输出流
    		PrintWriter out = resp.getWriter();
    		// 使用输出流向浏览器输出数据
    		out.println("<html>");
    		out.println("	<body>");
    		out.println("		<p>" + new Date() + "</p>");
    		out.println("	</body>");
    		out.println("</html>");
    
    		// 刷新缓冲区
    		out.flush();
    		// 关闭输出流
    		out.close();
    	}
    
    	@Override
    	protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    		// TODO Auto-generated method stub
    		super.doPost(req, resp);
    	}
    
    }
    
    

Servlet

  • Servlet是用Java编写的存放在服务器端的组件。可以动态扩展服务器的功能。

  • Servlet的结构

    • javax.servletr.Servlet接口:声明了Servlet最基础的方法。
    • javax.servlet.GenericServlet类:实现了Servlet接口,并重写了Servlet接口中的方法。
    • javax.servlet.http.HttpServlet类:继承GenericServlet类,并对HTTP协议进行了优化。
    image-20220812091712260
  • 创建自定义的Servlet:直接或间接实现Servlet接口

Servlet生命周期

  • 当浏览器向服务器发出请求,请求一个Servlet资源时。
  • 服务器会接收请求后,会在内存(缓存)中查找是否存在指定的Servlet实例
    • 当服务器没有在内存中找到Servlet实例时,服务器会创建Servlet的实例,并调用Servlet的init()方法进行初始化,最后调用Servlet的service()方法对请求做出响应
    • 当服务器在内存中找到了Servlet实例时,直接调用Servlet实例的service()方法对请求做出响应
  • 当服务器发现在一段时间没有任何请求访问Servlet实例时,服务器会调用Servlet的destroy()方法,再销毁此Servlet实例

HttpServletRequest与HttpServletResponse

javax.servlet.http.HttpServletRequest常用方法

  • getParameter("名字"):获得请求中指定名字的数据,返回类型一定是String类型。
  • setCharacterEncoding("字符集"):设置请求的字符集。
  • getParameterValues("名字"):获得请求中名字相同的一组数据,返回类型一定是String[]类型的数组。
  • getServletConfig():获得当前Servlet对应的ServletConfig实例。

javax.servlet.http.HttpServletResponse常用方法

  • setCharacterEncoding("字符集"):设置响应的字符集。
  • setContentType("text/html;charset=字符集"):设置目标浏览器显示的内容类型以及使用的字符集。

服务器端跨域(CORS)

  • resp.setHeader("Access-Control-Allow-Origin", "*");
    

HTTP协议的“无状态”

  • 服务器无法保存浏览器的状态。
  • 服务器认为浏览器发出的请求,都是第一次请求。

javax.servlet.http.Cookie类

  • Cookie是存放在浏览器端的一个文本文件

  • 用户可以在浏览器中设置拒绝接收Cookie。

    package com.test.servlet;
    
    import java.io.IOException;
    
    import javax.servlet.ServletException;
    import javax.servlet.annotation.WebServlet;
    import javax.servlet.http.Cookie;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    @WebServlet(urlPatterns = "/cookie")
    public class CookieServlet extends HttpServlet {
    
    	@Override
    	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    		this.doPost(req, resp);
    	}
    
    	@Override
    	protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    		 // 创建Cookie
    		 Cookie cookie = new Cookie("userName", "admin");
    		 // 设置Cookie的有效时间
    		 cookie.setMaxAge(60 * 60 * 24);
    		 // 将Cookie添加到响应中
    		 resp.addCookie(cookie);
    		
    		// 通过请求获得浏览器中的Cookie
    		Cookie[] cookies = req.getCookies();
    		for (Cookie c : cookies) {
    			System.out.println(c.getName());
    			System.out.println(c.getValue());
    		}
    	}
    }
    

javax.servlet.http.HttpSession接口

  • Session保存在服务器端。

  • Session是服务器中的一段内存

  • setAttribute("名字",数据):将数据以指定的名字存入到Session中。

  • getAttribute("名字"):根据名字从Session中获得指定的数据,返回类型一定为java.lang.Object类型。

  • removeAttribute("名字"):移除Session中指定名字的数据。

    package com.test.servlet;
    
    import java.io.IOException;
    
    import javax.servlet.ServletException;
    import javax.servlet.annotation.WebServlet;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import javax.servlet.http.HttpSession;
    
    @WebServlet(urlPatterns = "/session")
    public class SessionServlet extends HttpServlet {
    
    	@Override
    	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    		this.doPost(req, resp);
    	}
    
    	@Override
    	protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    		// 获得浏览器对应的session,如果浏览器没有session则返回null
    		// HttpSession session = req.getSession();
    		// 获得浏览器对应的session,如果浏览器没有session则为浏览器创建新的session
    		HttpSession session1 = req.getSession(true);
    		// 获得session的ID
    		System.out.println(session1.getId());
    		// 获得session默认的有效时间,单位秒
    		System.out.println(session1.getMaxInactiveInterval());
    		// 设置指定session的有效时间
    		session1.setMaxInactiveInterval(60 * 60 * 24);
    		// 获得session创建的时间,返回类型为long
    		System.out.println(session1.getCreationTime());
    		// 获得session最后一次被访问的时间,返回类型为long
    		System.out.println(session1.getLastAccessedTime());
    		// 向session中添加数据
    		session1.setAttribute("userName", "张三");
    		// 获得session中指定名字的数据
    		String name = (String) session1.getAttribute("userName");
    		System.out.println(name);
    		// 移除session中指定名字的数据
    		session1.removeAttribute("userName");
    	}
    }
    

标签:function,console,log,笔记,全部,let,user,组件
From: https://www.cnblogs.com/1A-tao/p/17121719.html

相关文章

  • 微信小程序练习笔记(更新中。。。)
      微信小程序的练习笔记,用来整理思路的,文档持续更新中。。。案例一:实现行的删除和增加操作 test.js//当我们在特定方法中创建对象或者定义变量给与初始值的时......
  • 读Java实战(第二版)笔记10_函数式编程的技巧
    1. 设计原则1.1. 将所有你愿意接受的作为参数的函数可能带来的副作用以文档的方式记录下来1.2. 最理想的情况下你接收的函数参数应该没有任何副作用1.3. 延迟数据......
  • 【学习笔记】数列特征方程与特征根
    觉得有意思就稍微微写写,内容大多摘自某本书.1.不动点求数列通项对于函数\(f(x)\),若存在实数\(x_0\)使得\(f(x_0)=x_0\),则称\(x_0\)是函数\(f(x)\)的一......
  • VisionPro学习笔记(1)——软件介绍和基本使用
    前言自己使用visionPro已经有段时间了,最近也一直在研究其算子的理论,为了加深印象,计划将自己的学习笔记整理在博客园,当然其官方文档对如何使用及其各种算子都有详细的......
  • 谷粒商城day01笔记
    mybatis目录mybatis特性mybatis日志使用1.insert2.update3.select4.delete5.性能分析插件5.条件构造器lombok注解mp是一个MyBatis的增强工具,在MyBatis的基础......
  • 【量化读书笔记】【打开量化投资的大门】Ch.03 阿尔法模型:Qunat如何盈利?
    阿尔法模型非常规定义:在交易中关于买卖时机把握和持有头寸选择的技巧。阿尔法是指扣除市场基准回报之后的投资回报率。一、两类阿尔法模型:理论驱动型和数据驱动型1.1......
  • PMP学习笔记《第一章 引论》
    什么是项目?项目是:为创造独特的产品、服务或成果而进行的临时性工作。项目的三大特性:临时性、独特性、渐进明细。1)项目的过程是临时的,但临时并不意味着时间短比如:修建体育场......
  • 2月14日笔记
    Pycharm的基本使用1.修改Pycharm主题File→settings→Apperance→Theme  2.修改字体大小File→settings→Editor→Font  3.切换解释器File→settings→Proj......
  • 第7天笔记
    第七天笔记日期对象日期对象是用于表示日期时间的一个对象,他里面包含对应设置日期时间及获取日期时间的方法日期对象的声明使用new关键字定义newDate()无参构造声明......
  • FWT 快速沃尔什变换学习笔记
    \(\text{FWT}\)快速沃尔什变换给定两个序列\(a,b\),求解序列\(c\)满足:\[c_i=\sum_{j\cdotk=i}a_jb_k\]其中\(\cdot\)可以为\(\&\),\(|\),还有\(\oplus\)等位......