周回顾
目录
- JS简介
- JS基础
- 变量与常量
- 基本数据类型
- 运算符
- 流程控制
- 函数
- 内置对象
- JSON对象
- RegExp对象
- BOM操作与DOM操作
- BOM(浏览器对象模型)
- DOM操作
- 查找标签
- 操作节点
- 获取值操作
- class与css操作
- 事件
- 事件实战案例
- jQuery类库
- 标签对象与jQuery对象
- 作业讲解
- jQuery查找标签
- 操作标签
- jQuery事件
- 事件相关补充
- jQuery动画效果(了解)
- Bootstrap页面框架
- 核心部分讲解
- 重要样式
- 组件
- 推导流程
- python主流web框架
- django简介
- django基本使用
- django app的概念
- django主要目录结构
- django小白必会三板斧
- 静态文件配置
- 静态文件相关配置
- form表单
- request对象
- pycharm连接数据库
- django连接数据库
- ORM简介
- ORM基本操作
- ORM基本语句
JS简介
全称JavaScript但是与Java一毛钱关系都没有 之所以这么叫是为了蹭Java的热度
它是一门前端工程师的编程语言 但是它本身有很多逻辑错误(不是很严谨)
IT行业鄙视链: 后端 > 前端、运维、测试、产品、老板
前端想一统天下:node.js
JS发展史>>>:JavaScript很容易学习
JS基础
1.注释语法
// 单行注释
/*多行注释*/
2.引入js的多种方式
1.head内script标签内编写
2.head内script标签src属性引入外部js资源
3.body内最底部通过script标签src属性引入外部js资源(最常用)
ps:注意页面的下载是从上往下的 所以操作标签js代码一定要等待标签加载完毕再执行才可以正常运行
3.结束符号
分号(很多时候不写也没问题)
变量与常量
"""
1.pycharm创建js文件或者html文件(适合编写较为复杂的js代码)
2.浏览器提供编写js代码的环境
"""
在js中声明变量需要使用关键字
var
var name = 'jason';
let
let name = 'tony';
ps:let是ECMA6新语法 可以在局部定义变量不影响全局
在js中声明常量也需要使用关键字
const
const pi = 3.14;
基本数据类型
"""
在JS中查看数据类型的方式 typeof
"""
1.数值类型(Number)
在JS中整型与浮点型不分家 都叫Number
NaN也属于数值类型 意思是:不是一个数字(Not A Number)
2.字符类型(String)
单引号 'jason'
双引号 "jason"
模板字符串 `jason`
let name1 = 'jason'
let age1 = 18
undefined
let desc = `my name is ${name1} my age is ${age1}`
1.字符串拼接推荐使用加号
2.常见内置方法
3.布尔类型(Boolean)
JS里面的布尔值与Python不同
JS是纯小写的 而Python是首字母大小
var a = true;
var b = false;
""(空字符串)、0、null、undefined、NaN都是false。
4.null与undefined
null表示值为空(曾经拥有过) undefined表示没有定义(从来没有过)
null表示值是空,一般在需要指定或清空一个变量时才会使用,如 name=null;
undefined表示当声明一个变量但未初始化时,该变量的默认值是undefined。还有就是函数无明确的返回值时,返回的也是undefined。
5.对象(object)
对象之数组(Array)>>>:类似于python中的列表
let l1 = []
对象之自定义对象(Object)>>>:类似于python的字典
let d1 = {'name':'jason',}
let d2 = new Object();
运算符
1.算术运算符
+ - * / % ++(自增1) --(自减1)
var x=10;
var res1=x++; 加号在后面 先赋值后自增
var res2=++x; 加号在前面 先自增后赋值
2.比较运算符
!=(值不等 弱) ==(值相等 弱) ===(值相等 强) !==(值不等 强)
3.逻辑运算符
&&(与) ||(或) !(非)
流程控制
1.单if分支
if (条件){
条件成立执行的代码
}
2.if...else分支
if(条件){
条件成立执行的代码
}else{
条件不成立执行的代码
}
3.if...else if...else分支
if(条件1){
条件1成立执行的代码
}else if(条件2){
条件1不成立条件2执行的代码
}
else{
条件1和2都不成立执行的代码
}
4.如果分支结构中else if很多还可以考虑使用switch语法
switch(条件){
case 条件1:
条件1成立执行的代码;
break; 如果没有break会基于某个case一直执行下去
case 条件2:
条件2成立执行的代码;
break;
case 条件3:
条件3成立执行的代码;
break;
case 条件4:
条件4成立执行的代码;
break;
default:
条件都不满足执行的代码
}
for循环
for(起始条件;循环条件;条件处理){
循环体代码
}
for(let i=0;i<10;i++){
console.log(i)
}
let dd = {'name':'jason','age':18}
for(let k in dd){
console.log(k)
}
while循环
while(循环条件){
循环体代码
}
"""
三元运算
python中: 值1 if 条件 else 值2
JS中: 条件?值1:值2
"""
函数
"""
python中函数的定义
def 函数名(形参):
'''函数注释'''
函数体代码
return 返回值
"""
function 函数名(形参){
// 函数注释
函数体代码
return 返回值
}
# 匿名函数
var s1 = function(a, b){
return a + b;
}
# 箭头函数
var f = v => v;
var f = function(v){
return v;
}
var f = () => 5;
var f = function(){return 5};
var sum = (num1, num2) => num1 + num2;
var sum = function(num1, num2){
return num1 + num2;
}
1.JS中函数的形参与实参个数可以不对应
传少了就是undefined 传多了不用
2.函数体代码中有一个关键字arguments用来接收所有的实参
3.函数的返回值如果有多个需要自己处理成一个整体
内置对象
var d = new Date();
//getDate() 获取日
//getDay () 获取星期
//getMonth () 获取月(0-11)
//getFullYear () 获取完整年份
//getYear () 获取年
//getHours () 获取小时
//getMinutes () 获取分钟
//getSeconds () 获取秒
//getMilliseconds () 获取毫秒
//getTime () 返回累计毫秒数(从1970/1/1午夜)
JSON对象
var str1 = '{"name": "Tony", "age": 18}';
var obj1 = {"name": "Tony", "age": 18};
// JSON字符串转换成对象 反序列化关键字parse
var obj = JSON.parse(str1);
// 对象转换成JSON字符串 序列化关键字stringify
var str = JSON.stringify(obj1);
RegExp对象
定义正则表达式两种方式
var reg1 = new RegExp("^[a-zA-Z][a-zA-Z0-9]{5,11}");
var reg2 = /^[a-zA-Z][a-zA-Z0-9]{5,9}$/;
1.全局模式的规律
lastIndex
2.test匹配数据不传默认传undefined
BOM操作与DOM操作
BOM(Browser Object Model)是指浏览器对象模型,它使 JavaScript 有能力与浏览器进行“对话”。
DOM (Document Object Model)是指文档对象模型,通过它,可以访问HTML文档的所有元素。
BOM(浏览器对象模型)
window对象
所有浏览器都支持 window 对象。它表示浏览器窗口。
一些常用的Window方法:
window.innerHeight - 浏览器窗口的内部高度
window.innerWidth - 浏览器窗口的内部宽度
window.open() - 打开新窗口
window.close() - 关闭当前窗口
window.open()
window.open('https://www.sogo.com/','','width=800px,left=200px')
window.close()
关闭当前浏览器窗口
navigator.userAgent
标识自己是一个浏览器
history.forward()
前进一页
history.back()
后退一页
window.location.href
获取当前页面所在的网址 也可以再加赋值符号和网址跳转
window.location.reload()
刷新当前页面
alert()
警告框
confirm()
确认框
prompt()
提示框
设置定时任务
在等待一定时间间隔后执行指定的任务。
timeTask = setTimeout(function(){
alert("警告警告!!")
}, 3000) // 传入函数任务和延迟时间(时间单位为毫秒)
clearTimeout(timeTask) // 取消定时任务(不执行任务)
循环定时任务
loopTask = setInterval(function(){
alert("警告警告!!")
}, 3000) // 每三秒弹出一次警告窗
setTimeout(function(){
clearInterval(loopTask) // 结束指定的循环的任务
}, 10000) // 到十秒了结束循环任务
总结:
方法 说明
setTimeout(func, time) 设置定时任务,提交函数任务和延迟时间
clearTimeout(task) 关闭定时任务不执行,task是setTimeout()的返回对象
setInterval(func,interval_time) 设置循环定时任务,提交函数任务和间隔时间
clearInterval(loop_task) 关闭循环定时任务,loop_task是setInterval()的返回对象
DOM操作
DOM (Document Object Model)是指文档对象模型,通过它可以访问HTML文档的所有元素
既然DOM操作是通过js代码来操作标签 所以我们需要先学习如何查找标签之后才能给标签绑定一些JS代码(DOM操作)
查找标签
"""
1.js中变量名的命名风格推荐是驼峰体
2.js代码查找到的标签如果需要反复使用可以用变量接收 规律 xxxEle
"""
document.getElementById('d1')
结果就是标签对象本身
document.getElementsByClassName('c1')
结果是数组里面含有多个标签对象
document.getElementsByTagName('span')
结果是数组里面含有多个标签对象
parentElement 父节点标签元素
children 所有子标签
firstElementChild 第一个子标签元素
lastElementChild 最后一个子标签元素
nextElementSibling 下一个兄弟标签元素
previousElementSibling 上一个兄弟标签元素
操作节点
创建节点
我们可以通过js动态的创建一个标签节点:createElement("标签类型")
let divEle = document.createELement("div") // 创建一个div标签
添加节点
创建好的节点可以插入html文档流中:
// js代码查找div标签并将a追加到div内部
let divEle = document.getElementsByTagName('div')[0]
divEle.appendChild(aEle)
删除节点和替换节点
需要分别找到父节点和要删除或替换的节点,然后通过父节点删除或替换子节点。
somenode.removeChild(要删除的节点); // 删除节点
somenode.replaceChild(newnode, 某个节点); // 替换节点
设置节点属性*
获取和设置文本节点的值:
.innerText 获取标签内部所有的文本内容
.innerText = '文本' 替换/设置标签内部的文本(不识别标签语法)
.innerHTML 获取标签内部所有的标签包含文本
.innerHTML = '文本' 替换/设置标签内部的文本(识别标签语法)
attribute操作
// 对于标签对象中原本没有的属性也可以进行操作的attribute操作
divEle.setAttribute("age","18")
divEle.getAttribute("age")
divEle.removeAttribute("age")
// 对于标签已经有的属性可以通过点的方式:
inputEle.value // 拿到value值
inputEle.value="blabla"
/*这类操作就可以拿到用户输入的内容并做些简单的判断和做出一些即时的判断*/
获取值操作
1.针对用户输入的和用户选择的标签
标签对象.value
找select
2.针对用户上传的文件数据
标签对象.files fileList [文件对象、文件对象、文件对象]
标签对象.files[0] 文件对象
class与css操作
1.js操作标签css样式
标签对象.style.属性名(下划线没有 变成驼峰体)
2.js操作标签class属性
标签对象.classList.add()
标签对象.classList.contains() # 判断有没有这个属性
标签对象.classList.remove()
标签对象.classList.toggle() # 如果有这个属性就删掉 没有就添加
事件
在网页节点上发生的一些变化都可以称之为事件,我们可以通过js代码在触发这些事件的时候对节点进行操作。
常见事件
onclick:点击某标签时触发,经常用于空白button
onfocus:获取焦点时触发
onblur:失去焦点时触发
焦点常应用于表单标签,用户操作时的动效设计
onchange:域的内容发生变化时触发,如select标签选择的选项发生变化。
onload:等待页面、图片加载出来触发 window.onload
页面加载完成意味着所有的标签节点都在DOM树中了
绑定事件的多种方式
<!--绑定事件的方式1-->
<button onclick="showMsg()">快按我</button>
<!--绑定事件的方式2-->
<input type="button" value="快快快" id="d1">
<script>
function showMsg() {
// let msg = prompt('你确定要这样')
// console.log(msg)
console.log(this)
}
let inputEle = document.getElementById('d1');
inputEle.onclick = function () {
// alert('谁在那里点我')
console.log(this.getAttribute('username'))
}
</script>
事件函数中的this关键字
this指代的就是当前被操作的标签对象本身
如果事件函数内有多层嵌套那么最好在一开始用变量存储一下防止后续变化
onload方法
XXX.onload 等待XXX加载完毕之后再执行后面的代码
事件实战案例
# input焦点事件
<input type="text" value="游戏机" id="d1">
<script>
let inputEle = document.getElementById('d1')
inputEle.onfocus = function () {
this.value = ''
}
inputEle.onblur = function () {
this.value = '下次再来哟!'
}
</script>
# 校验用户数据
<p>username:
<input type="text" id="d1">
<span style="color: red"></span>
</p>
<p>password:
<input type="text" id="d2">
<span style="color: red"></span>
</p>
<button id="suBtn">提交</button>
<script>
// 1.查找提交按钮的标签
subEle = document.getElementById('suBtn')
// 2.给按钮标签绑定点击事件
subEle.onclick = function (){
// 3.查找获取用户输入的标签并获取数据
let userNameEle = document.getElementById('d1')
let passWordEle = document.getElementById('d2')
if(userNameEle.value === 'jason'){
userNameEle.nextElementSibling.innerText = '用户名不能是Jason'
}
if(passWordEle.value === '123'){
passWordEle.nextElementSibling.innerText = '密码不能是123'
}
}
</script>
# 省市联动
省:
<select name="" id="d1">
</select>
市:
<select name="" id="d2">
</select>
<script>
let data = {
"河北": ["廊坊市", "邯郸市"],
"北京": ["朝阳区", "海淀区"],
"山东": ["威海市", "烟台市"],
"安徽": ["芜湖市", "合肥市"],
"上海": ["浦东新区", "静安区"]
}
// 提前查找好省和市的select标签
let proSeEle = document.getElementById('d1');
let citySeEle = document.getElementById('d2');
// 1.获取所有的省信息
for (let pro in data) {
// 2.创建option标签
let proOpEle = document.createElement('option');
// 3.添加文本及属性
proOpEle.innerText = pro;
proOpEle.setAttribute('value', pro);
// 4.将创建好的option标签添加到省下拉框中
proSeEle.appendChild(proOpEle)
}
// 5.给省标签绑定文本域变化事件 onchange
proSeEle.onchange = function () {
citySeEle.innerHTML = ''; // 每次操作市之前清空市数据
// 6.获取用户选择的省信息 根据省获取市信息
let targetProData = this.value;
let cityDataList = data[targetProData];
// 7.循环获取每一个市信息 创建option标签 添加到市下拉框中
for (let i = 0; i < cityDataList.length; i++) {
let cityOpEle = document.createElement('option');
cityOpEle.innerText = cityDataList[i];
cityOpEle.setAttribute('value', cityDataList[i]);
citySeEle.appendChild(cityOpEle)
}
}
</script>
jQuery类库
"""
IE浏览器:前端针对IE有时候需要单独再编写一份代码
"""
Write less, do more 写的更少做的更多
1.加载速度快
2.选择器更多更好用
3.一行代码走天下
4.支持ajax请求(重点)
5.兼容多浏览器
准备工作
1.下载核心文件到本地引入(没有网络也可以使用)
<script src="jQuery3.6.js"></script>
2.CDN网络资源加载(必须有网络才可以使用)
https://www.bootcdn.cn/
https://cdn.bootcdn.net/ajax/libs/jquery/3.6.1/jquery.js
https://cdn.bootcdn.net/ajax/libs/jquery/3.6.1/jquery.min.js
什么是CDN
内容分发网络
jQuery导入之后需要使用关键字才可以使用
默认的关键字就是jQuery但是不好输入 >>>: $
var $variable = jQuery对像
var variable = DOM对象
$variable[0] // jQuery对象可以转成DOM对象
jQuery封装了JS代码 让编写更简单 但是有时候JS代码更快
js代码与jQuery代码对比
let pEle = document.getElementsByTagName('p')[0] // 拿到p标签
pEle.style.color = 'red' // 将p标签的内容颜色改为红
pEle.nextElementSibling.style.color = 'green' // 将p标签的下一个标签的颜色改为绿
$('p').first().css('color','yellow').next().css('color','blue') // 将p标签的颜色改为黄,它的下一个标签改成蓝
标签对象与jQuery对象
1.不同的对象能够调用的方法是不同的
在编写代码的时候一定要看清楚手上是什么对象
2.两者可以互相转换
标签对象转jQuery对象
$(标签对象)
jQuery对象转标签对象
jQuery对象[0]
作业讲解
1.校验用户数据
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.1/jquery.js"></script>
</head>
<body>
<p>username:
<input type="text" id="d1">
<span style="color: red"></span>
</p>
<p>password:
<input type="text" id="d2">
<span style="color: red"></span>
</p>
<button id="d3">提交</button>
<script>
let usernameEle = document.getElementById('d1');
let passwordEle = document.getElementById('d2');
let subBtn = document.getElementById('d3');
subBtn.onclick = function () {
if (usernameEle.value === 'jason'){
usernameEle.nextElementSibling.innerText = '用户名不能是jason'
}
if (passwordEle.value === '123'){
passwordEle.nextElementSibling.innerText = '密码不能是123'
}
}
usernameEle.onfocus = function () {
this.nextElementSibling.innerText = ''
}
passwordEle.onfocus = function () {
this.nextElementSibling.innerText = ''
}
</script>
</body>
</html>
2.页面计时器
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.1/jquery.js"></script>
</head>
<body>
<input type="text" id="d1">
<button id="startBtn">开始</button>
<script>
// 先写最简单的起步>>>:点击开始按钮 将那一刻的时间展示到input框中即可
// 想让展示时间的代码能够根据时间的变化反复的执行>>>:循环定时任务
// 再创建结束按钮点击即终止循环定时任务的执行>>>:结束定时任务
let startBtnEle = document.getElementById('startBtn');
let inputEle = document.getElementById('d1');
let stopBtnEle = document.getElementById('stopBtn');
function showTime() {
let currentTime = new Date();
inputEle.value = currentTime.toLocaleString()
}
// 全局定义一个存储计时器的变量名
let t;
startBtnEle.onclick = function () {
if(!t){
t = setInterval(showTime, 1000)
}
}
stopBtnEle.onclick = function () {
clearInterval(t)
t = null;
}
</script>
</body>
</html>
jQuery查找标签
-
基本选择器
$('#d1') id选择器 $('.c1') class选择器 $('div') 标签选择器
-
组合选择器
$('div#d1') 查找id是d1的div标签 $('span.c1') 查找含有c1样式类的span标签 $('div,span,p') 查找div或者span或者p标签 $('#d1,.c1,span') 查找id是d1的或者class含有c1的或者span标签
-
层级选择器
$('div p') 查找div里面所有的后代p标签 $('div>p') 查找div里面的儿子p标签 $('div+p') 查找div同级别下面紧挨着的p标签 $('div~p') 查找div同级别下面所有的p标签
-
属性选择器
$('[username]') 查找含有username属性名的标签 $('[username="jason"]') 查找含有username属性名并且值等于jason的标签 $('input[username="jason"]') 查找username='jason'的input标签
-
基本筛选器
:first // 第一个 :last // 最后一个 :eq(index)// 索引等于index的那个元素 :even // 匹配所有索引值为偶数的元素,从 0 开始计数 :odd // 匹配所有索引值为奇数的元素,从 0 开始计数 :gt(index)// 匹配所有大于给定索引值的元素 :lt(index)// 匹配所有小于给定索引值的元素 :not(元素选择器)// 移除所有满足not条件的标签 :has(元素选择器)// 选取所有包含一个或多个标签在其内的标签(指的是从后代元素找) $('li:first') 优化 $('li').first()
-
表单筛选器
$(':text') 查找文本 $(':password') 查找密码 $(':checked') checked与selected都会找到 $(':selected') selected
-
筛选器方法
$("#id").next() 下一个元素 $("#id").nextAll() $("#id").nextUntil("#i2") $("#id").prev() 上一个元素 $("#id").prevAll() $("#id").prevUntil("#i2") $("#id").parent() 父亲元素 $("#id").parents() // 查找当前元素的所有的父辈元素 $("#id").parentsUntil() // 查找当前元素的所有的父辈元素,直到遇到匹配的那个元素为止。 $("#id").children();// 儿子们 儿子和兄弟元素 $("#id").siblings();// 兄弟们 补充: .first() // 获取匹配的第一个元素 .last() // 获取匹配的最后一个元素 .not() // 从匹配元素的集合中删除与指定表达式匹配 的元素 .has() // 保留包含特定后代的元素,去掉那些不含有指定后代的元素。 .eq() // 索引值等于指定值的元素
操作标签
1.class操作
addClass();// 添加指定的CSS类名
classList.add() # dom操作
removeClass();// 移除指定的CSS类名。
classList.remove() # dom操作
hasClass();// 判断样式存不存在
classList.contains() # dom操作
toggleClass();// 切换CSS类名,如果有就移除,如果没有就添加。
classList.toggle() # dom操作
2.位置操作
$(window).scrollTop()// 获取匹配元素相对滚动条顶部的偏移
offset()// 获取匹配元素在当前窗口的相对偏移或设置元素位置
position()// 获取匹配元素相对父元素的偏移
scrollTop()// 获取匹配元素相对滚动条顶部的偏移
scrollLeft()// 获取匹配元素相对滚动条左侧的偏移
3.文本操作
HTML:
html()// 取得第一个匹配元素的html内容
html(val)// 设置所有匹配元素的html内容
4.文本值:
text()// 取得所有匹配元素的内容
text(val)// 设置所有匹配元素的内容
5.值:
val()// 取得第一个匹配元素的当前值
val(val)// 设置所有匹配元素的值
val([val1, val2])// 设置多选的checkbox、多选select的值
6.文件:
jQuery对象[0].files
7.创建标签:
document.createElement() $('<a>')
8.属性操作
attr()/removeAttr() 相当于js中的xxxAttribute()
attr(attrName)// 返回第一个匹配元素的属性值
attr(attrName, attrValue)// 为所有匹配元素设置一个属性值
attr({k1: v1, k2:v2})// 为所有匹配元素设置多个属性值
removeAttr()// 从每一个匹配的元素中删除一个属性
attr针对动态变化的属性获取会失真
prop('checked') prop('selected')
9.文档处理
$(A).append(B)// 把B追加到A
$(A).appendTo(B)// 把A追加到B
$(A).prepend(B)// 把B前置到A
$(A).prependTo(B)// 把A前置到B
$(A).after(B)// 把B放到A的后面
$(A).insertAfter(B)// 把A放到B的后面
$(A).before(B)// 把B放到A的前面
$(A).insertBefore(B)// 把A放到B的前面
remove()// 从DOM中删除所有匹配的元素。
empty()// 删除匹配的元素集合中所有的子节点。
jQuery事件
JS绑定事件
标签对象.on事件名 = function(){}
jQuery事件绑定
方式1:
jQuery对象.事件名(function(){})
方式2:
jQuery对象.on('事件名称',function(){})
ps:默认就用方式1 不行了再用方式2
ps:补充
clone属性
clone(true) 默认不克隆事件 加true就可以
事件相关补充
1.取消后续事件
事件函数的最后return false即可
2.阻止事件冒泡
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.1/jquery.js"></script>
<script>
$(function () {
})
</script>
</head>
<body>
<div>div
<p>div>p
<span>div>p>span</span>
</p>
</div>
<script>
$('div').click(function () {
alert('我是div')
})
$('p').click(function () {
alert('我是p')
return false
})
$('span').click(function (e) {
alert('我是span')
// return false
e.stopPropagation()
})
</script>
</body>
</html>
情况说明:
当return false和e.stopPropagation()被注释后,会出现调用内部的span标签是同时弹出三个标签的点击事件,点击p标签的时候,也会出现div标签的点击事件。
解决方法:
当我们在p标签和span标签的点击事件下方加上retun false或是e.stopPropagation()都可以解决事件的冒泡现象。
3.等待页面加载完毕再执行代码
$(function(){}) 缩略写法
$(document).ready(function(){}) 完整写法
4.事件委托
主要针对动态创建的标签也可以使用绑定的事件
$('body').on('click','button',function(){})
将body内所有的单击事件委托给button标签执行
jQuery动画效果(了解)
// 基本
show([s,[e],[fn]])
hide([s,[e],[fn]])
toggle([s],[e],[fn])
// 滑动
slideDown([s],[e],[fn])
slideUp([s,[e],[fn]])
slideToggle([s],[e],[fn])
// 淡入淡出
fadeIn([s],[e],[fn])
fadeOut([s],[e],[fn])
fadeTo([[s],o,[e],[fn]])
fadeToggle([s,[e],[fn]])
// 自定义(了解即可)
animate(p,[s],[e],[fn])
Bootstrap页面框架
使用Bootstrap页面框架,就相当于使用别人已经提前写好了的一大堆css和js,我们只需要引入之后按照人家规定好的操作方式即可使用所有的样式和功能。
官网地址:https://v3.bootcss.com/
版本有很多 使用V3即可
文件结构
bootstrap.css
bootstrap.js
ps:js部分是需要依赖于jQuery
CDN
<link href="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css" >
<script src="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/js/bootstrap.min.js"></script>
pycharm自动提示问题
当我们第一次在pycharm中使用Bootstrap的时候会发现在编写代码的时候并不会出现自动提示。
解决方法就是先在pycharm中本地导入几次,之后在使用的时候就会出现自动提示了。
核心部分讲解
我们在使用Bootstrap的时候其实就是给需要添加样式的标签添加class类,添加了对应的类,就可以产生对应的美化效果。
官网教学文档:https://v3.bootcss.com/css/#formshorizontal
其他文档也在官网
部分功能介绍
布局容器
class = "container" 有留白
class = "container-fluid" 没有留白
栅格系统
class = 'row' // 默认开设一行均分12份
class = 'col-md-n' // 指定需要几份,一行最多12份
屏幕参数 // 栅格参数可以做到响应式布局:xs sm md lg...
class=col-md-6 col-xs-2 col-sm-3 col-lg-3
栅格偏移 如果一行十二份用不完 可以调整位置
class=col-md-offset-3
重要样式
1.表格样式
参考官网即可 有样式有源码 拷贝使用即可
// 表格样式
<table class="table table-hover table-striped table-bordered">
// 单元格颜色
<tr class="active">
class="success"
class="warning"
class="danger"
class="info"
2.表单样式
.pull-left 左浮
.pull-right 右浮
class='form-control'
针对radio和checkbox不能加!!!
3.按钮样式
class = 'btn'
# 按钮颜色
<a href="" class="btn btn-info">言多必失</a>
<a href="" class="btn btn-danger">言多必失</a>
<a href="" class="btn btn-warning">言多必失</a>
<a href="" class="btn btn-primary">言多必失</a>
<a href="" class="btn btn-success">言多必失</a>
# 按钮尺寸
<a href="" class="btn btn-sm">言多必失</a>
<a href="" class="btn btn-lg">言多必失</a>
<a href="" class="btn btn-block">言多必失</a>
组件
1.图标
<span class="glyphicon glyphicon-search" aria-hidden="true"></span>
https://fontawesome.com.cn/
2.导航条
class="navbar navbar-inverse"
3.其他
推导流程
纯手撸web框架
-
web框架的本质
1.连接前端于数据库的中间介质 2.socket服务端
-
手写web框架
1.编写socket服务端代码 2.浏览器访问响应无效>>>:HTTP协议 HTTP协议: 超文本传输协议:规定了浏览器与服务器之间数据交互的格式 HTTP协议的四大特性: 1.基于请求响应 -- 浏览器给服务端发起请求,服务端收到后做出回应 2.基于TCP、IP协议作用于应用层之上的协议 3.无状态 -- 不保存用户端的登录状态,见你千百遍我都当你如初见 4.无(短)连接 -- 一次请求响应后即断开连接 HTTP协议的数据传输格式: 1.请求数据格式: 请求首行(请求方法...) 请求头(一大堆K:V键值对) \r\n ---换行 请求体(并不是所有的请求方法都有 主要用来携带敏感性数据) 2.响应数据格式: 响应首行(响应状态码...) 响应头(一大堆k:v键值对) \r\n ---换行 响应体(展示给用户的数据) 3.根据网址后缀的不同获取不同的页面内容 4.想办法获取到用户输入的后缀>>>:请求数据 5.请求首行 GET /login HTTP/1.1 GET:朝服务端索要数据 POST:朝服务端提交数据 6.从请求数据格式中筛选出用户输入的网址后缀(从字符串中截取出来需要得内容) target_url = data.decode('utf8').split(' ')[1] 注意: """ 1.socket代码过于重复 2.针对请求数据处理繁琐 3.后缀匹配逻辑过于LowB """
代码: import socket server = socket.socket() # TCP UDP server.bind(('127.0.0.1', 8080)) # IP PORT server.listen(5) # 半连接池 while True: sock, address = server.accept() # 等待连接 data = sock.recv(1024) # 字节(bytes) # print(data.decode('utf8')) # 解码打印 sock.send(b'HTTP/1.1 200 OK\r\n\r\n') data_str = data.decode('utf8') # 先转换成字符串 target_url = data_str.split(' ')[1] # 按照空格切割字符串并取索引1对应的数据 # print(target_url) # /index /login /reg if target_url == '/index': # sock.send(b'index page') with open(r'myhtml01.html','rb') as f: sock.send(f.read()) elif target_url == '/login': sock.send(b'login page') else: sock.send(b'home page!')
基于wsgiref模块
wsgiref是一种内置模块,它是很多web框架底层使用的模块
作用:封装了socket代码
处理了请求数据
这时使用wsgiref模块可以:
1.固定代码启动服务端
2.查看处理之后的request大字典
3.根据不同的网址后缀返回不同的内容>>>:它是一个字典键值对,研究大字典键值对
4.立刻解决上述纯手撸的前两个问题
5.针对最后一个问题代码如何优化
代码:
from wsgiref.simple_server import make_server
def run(request, response):
"""
:param request: 请求相关数据
:param response: 响应相关数据
:return: 返回给客户端的真实数据
"""
response('200 OK', []) # 固定格式 不用管它
# print(request) 是一个处理之后的大字典
path_info = request.get('PATH_INFO')
if path_info == '/index':
return [b'index']
elif path_info == '/login':
return [b'login']
return [b'hello wsgiref module']
if __name__ == '__main__':
server = make_server('127.0.0.1', 8080, run) # 实时监听127.0.0.1:8080 一旦有请求过来自动给第三个参数加括号并传参数调用
server.serve_forever() # 启动服务端
代码封装优化
作用:
1.网址后缀的匹配问题
2.每个后缀匹配成功后执行的代码有多有少
面条版 函数版 模块版
3.将分支的代码封装成一个个函数
4.将网址后缀与函数名做对应关系
5.获取网址后缀循环匹配
6.如果想新增功能只需要先写函数再添加一个对应关系即可
7.根据不同的功能拆分成不同的py文件
views.py 存储核心业务逻辑(功能函数)
urls.py 存储网址后缀与函数名对应关系
templates目录 存储html页面文件
8.为了使函数体代码中业务逻辑有更多的数据可用
将request大字典转手传给这个函数(可用不用但是不能没有)
views代码:
def index_func(request):
return 'index function'
def login_func(request):
with open(r'templates/myhtml02.html', 'r', encoding='utf8') as f:
return f.read()
# return 'login function'
def reg_func(request):
return 'reg function'
def error_func(request):
return '404 Not Found'
def logout_func(request):
return 'logout function'
urls代码:
from views import *
urls = [
('/index', index_func),
('/login', login_func),
('/reg', reg_func),
('/logout', logout_func),
('/get_time', get_time_func),
('/get_dict', get_dict_func),
('/get_user', get_user_func)
]
动静态网页
动态网页
页面数据来源于后端
静态网页
页面数据直接写死
1.访问某个网址后缀 后端代码获取当前时间 并将该时间传到html文件上再返回给浏览器展示给用户看
读取html内容(字符串类型) 然后利用字符串替换 最后再返回给浏览器
2.将字典传递给页面内容 并且在页面上还可以通过类似于后端的操作方式操作该数据
模板语法>>>:jinja2模块
jinja2模块
pip3 install jinja2
from jinja2 import Template
def get_dict_func(request):
user_dict = {'name': 'jason', 'age': 18, 'person_list': ['阿珍', '阿强', '阿香', '阿红']}
with open(r'templates/get_dict_page.html', 'r', encoding='utf8') as f:
data = f.read()
temp_obj = Template(data) # 将页面数据交给模板处理
res = temp_obj.render({'d1': user_dict}) # 给页面传了一个 变量名是d1值是字典数据的数据
return res
<p>{{ d1 }}</p>
<p>{{ d1.name }}</p>
<p>{{ d1['age'] }}</p>
<p>{{ d1.get('person_list') }}</p>
jinja2能够让我们在html文件内使用类似于后端的语法来操作各种数据类型
jinja2模板语法:
{{···}}
{%···%}
前端、后端、数据库三者联动
关系:前端浏览器访问get_user
后端连接数据库查询user表中所有的数据 然后传递到某个html页面 弄好样式 最后发送给浏览器展示
{% for user_dict in user_data_list %}
<tr>
<td>{{ user_dict.id }}</td>
<td>{{ user_dict.name }}</td>
<td>{{ user_dict.age }}</td>
</tr>
{% endfor %}
python主流web框架
"""
作为小白的你 初学阶段不要混着学 很容易走火入魔
"""
1.django
大而全 自身自带的功能组件非常的多 类似于航空母舰
2.flask
小而精 自身自带的功能组件非常的少 类似于游骑兵
几乎所有的功能都需要依赖于第三方模块
3.tornado
异步非阻塞 速度极快效率极高甚至可以充当游戏服务端
ps:sanic、fastapi...
三大主流web框架特点
django:
socket部分用的是别人的 wsgiref模块
路由与视图函数对应关系(路由匹配)用的是自己的
模版语法用的是自己的(没有jinja2好用 但是也很方便)
flask:
socket部分用的是别人的 werkzeug(内部还是wsgiref模块)
路由与视图函数对应关系(路由匹配)自己写的
模版语法用的别人的(jinja2)
tornado:
socket部分,路由与视图函数对应关系(路由匹配),模版语法都是自己写的
django简介
-
版本问题
django1.X:同步 1.11 LTS稳定版 django2.X:同步 2.2 LTS稳定版 django3.X:支持异步 3.2 LTS稳定版 django4.X:支持异步 4.2 LTS稳定版 ps:版本之间的差异其实不大 主要是添加了额外的功能
-
注意事项
1.django项目中所有的文件名目录名不要出现中文 2.计算机名称尽量也不要出现中文 3.一个pycharn尽量就是一个完整的项目(不要嵌套 不要叠加) 4.不同版本的python解释器与不同版本的django可能会出现小问题
django基本使用
1.下载 pip3 install django 默认最新版 pip3 install django==版本号 指定版本 pip3 install django==2.2.22 是我们需要下载的 pip下载模块会自动解决依赖问题(会把关联需要用到的模块一起下了) 2.验证下载是否成功 django-admin 3.常见命令 3.1 创建django项目 django-admin startproject 项目名 3.2 启动django项目 cd 项目名 python38 manage.py runserver ip:port 4.pycharm自动创建django项目 在pycharm下载完成时会自动创建templates文件夹 但是配置文件中可能会报错 加上[os.path.join(BASE_DIR,'templates'), ]
django app的概念
-
django类似于是一所大学 app类似于大学里面的各个学院
-
django里面的app类似于某个具体的功能模块
user app 所有用户相关的都写在user app下 goods app 所有商品相关的都写在goods app下
-
命令行创建应用
python38 manage.py startapp 应用名
-
pycharm创建应用
新建django项目可以默认创建一个 并且自动注册
"""
创建的app一定要去settings.py中注册
INSTALLED_APPS = [
'app01.apps.App01Config', 全写
'app01', 简写
]
"""
django主要目录结构
-
django项目目录名
django项目同名目录 settings.py 配置文件 urls.py 存储网址后缀与函数名对应关系(不严谨) wsgi.py wsgiref网关文件 db.sqlite3文件 django自带的小型数据库(项目启动之后才会出现) manage.py 入口文件(命令提供)
-
应用目录
migrations目录 存储数据库相关记录 admin.py django内置的admin后台管理功能 apps.py 注册app相关 models.py 与数据库打交道的(非常重要) tests.py 测试文件 views.py 存储功能函数(不严谨) templates目录 存储html文件(命令行不会自动创建而pycharm会自动创建) 配置文件中还需要配置路径 [os.path.join(BASE_DIR,'templates'),]
-
重要名词讲解
urls.py 路由层 views.py 视图层 models.py 模型层 templates 模版层 """ 网址后缀 路由 函数 视图函数 类 视图类 """
django小白必会三板斧
导入的模块
from django.shortcuts import render,HttpResponse,redirect
HttpResponse 返回字符串类型的数据
render 返回html页面并且支持传值
redirect 重定向
静态文件配置
-
编写一个用户登录页面
-
静态文件
它是不怎么经常变化的文件 主要针对html文件所使用的到的各种资源 像css文件、js文件、img文件、第三方框架文件 这时候django针对静态文件资源需要单独开始一个目录统一存放到static目录
static目录: 该目录下如果各种类型的文件都多 还可以继续创建目录 css目录 js目录 img目录 utils目录/plugins目录/libs目录/others目录/不创
-
资源访问
我们在地址栏中之所以可以属于路由获取到相应的资源是因为程序员提前开设了资源的接口
-
静态文件资源访问
默认情况下无法访问 因为我们没有提前开设静态文件资源的访问接口
静态文件相关配置
STATICFILES_DIRS = [
os.path.join(BASE_DIR, 'static')
]
-
1.接口前缀
STATIC_URL = '/xxx/' # 访问静态文件资源的接口前缀(通行证) STATICFILES_DIRS = [ os.path.join(BASE_DIR, 'static'), # 存储静态文件资源的目录名称 os.path.join(BASE_DIR, 'static1'), # 存储静态文件资源的目录名称 os.path.join(BASE_DIR, 'static2'), # 存储静态文件资源的目录名称 ] ''' 接口前缀正确之后 会拿着后面的路径依次去到列表中自上而下查找 一旦找到就返回 '''
-
2.接口前缀动态匹配
{% load static %} <link rel="stylesheet" href="{% static 'bootstrap-3.4.1-dist/css/bootstrap.min.css' %}"> <script src="{% static 'bootstrap-3.4.1-dist/js/bootstrap.min.js' %}"></script>
form表单
-
action
它是控制数据提交的地址 1.action="" 数据默认提交给当前页面所在的地址 2.action="https://www.baidu.com/" 完整地址 3.action="/index/" 朝当前服务端的index地址提交
-
method
控制数据提交的方法
默认是get
可以改post
- 请求方法补充
- get:
朝服务端索要数据 也可以携带一些额外的要求
携带额外数据的方式: URL?xxx=yyy&uuu=zzz
上面问号后面携带数据的大小是有限制(2KB)的并且不能携带敏感数据
- post:
朝服务端提交数据
携带额外数据的方式: 请求体
请求体携带数据安全性较高并且没有大小限制
前期发送post请求需要注释掉配置文件中的某一行
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
# 'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
request对象
request.method 获取请求方式 结果是纯大写的字符串数据
其中有两个GET\POST
request.POST 获取post请求请求体里面携带的数据
有request.POST.get() 获取列表最后一个数据值
request.POST.getlist() 获取整个列表数据
request.GET 获取网址问号后面携带的数据request.GET.get() 获取列表最后一个数据值
request.GET.getlist() 获取整个列表数据
"""
在视图函数中针对不同的请求代码编写套路
if request.method == 'POST':
return HttpResponse()
return HttpResponse()
"""
pycharm连接数据库
1.pycharm初次连接数据库 需要下载对于的驱动
django连接数据库
django自带的sqlite3是一个小型的数据库 功能比较少 主要用于本地测试
我们实际项目中都会替换掉它
默认配置sqlite3
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
}
}
首先我们需要:
1.修改配置文件
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'day51',
'HOST': '127.0.0.1',
'PORT': 3306,
'USER': 'root',
'PASSWORD': '123',
'CHARSET': 'utf8'
}
}
2.需要指定模块
django1.X版本需要在项目目录下或者app目录下的__init__.py编写代码
import pymysql
pymysql.install_as_MySQLdb()
django2.X及以上都可以直接通过下载mysqlclient模块解决
pip3.8 install mysqlclient
ps:该模块windows下载问题不大 主要是mac电脑可能有问题
ORM简介
ORM:它是对象关系映射
能够让不会SQL语句的python程序员 使用python面向对象的语法来操作数据库
类 表
对象 一条条数据
对象点名字 数据获取字段对应的值
ORM由于高度封装了SQL 所以有时候效率较低 我们需要自己写SQL
ORM基本操作
- 第一步是先在models.py中编写模型类
class GirlsInfo(models.Model):
# 字段名 = 字段类型 + 约束条件
id = models.AutoField(primary_key=True)
name = models.CharField(max_length=32)
age = models.IntegerField()
- 第二步再执行数据库迁移相关命令
python38 manage.py makemigrations 将操作记录到小本本上(migrations)
python38 manage.py migrate 将操作同步到数据库上
'''注意每次在models.py修改了与数据库相关的代码 都需要再次执行上述命令''
ORM基本语句
from app01 import models
models.类名.objects.create() 增加
models.类名.objects.filter() 查询
models.类名.objects.update() 这是修改所有的数据,如果想要只修改一条数据就要在update前面加上filter
models.类名.objects.delete() 这是删除所有的数据,如果想要只删除一条数据就要在delete前面加上filter