Python自動化開發學習15-JavaScript和DOM
JavaScript(後面都簡寫為js)是一門獨立的語言。瀏覽器本身就具有js解釋器。
js的存在形式
和css類似,js代碼要放在<script>標簽中。
同樣和css類似,還可以寫在一個js文件中,比如文件名就叫 commons.js ,然後在head中引入 <script src="commons.js"></script>
,src的值就是js的文件路徑。
<script type="text/javascript"> 和 <script> 是一樣的,或者說script默認就是js。看到這麽寫全的情況要認識。
上面兩種情況都用的是 <script> 標簽。而這個標簽可以放在head中,也可以放在body中。解釋器是從上到下順序執行的,所以放在越上面就越早執行。這就有一個問題,如果script先執行,那麽執行完成script代碼後才會導入網頁內容。這樣用戶體驗會比較差。而且用戶只有先看到網頁的內容才有可能會需要用到script的代碼。所以建議把<script>標簽放到最後,也就是body的內部的最下面。這樣就是先顯示網頁的內容,然後再導入js的動態內容。
hellow world
語法:alert(message)
會顯示一個帶有消息和確定按鈕的警告框。
<head>
<meta charset="UTF-8">
<title>Title</title>
<script>
alert("Hello 1")
</script>
</head>
<body>
<h1>什麽時候出現這裏的內容</h1>
<script>
alert("Hello 2")
</script>
</body>
在head裏寫了一個alert,在body的下面也寫了一個alert。打開網頁後,會先彈出上面的消息,然後顯示網頁的內容,最後再彈出最下面的消息。
註釋
js代碼的註釋的語法如下:
單行註釋:// 你的代碼
多行註釋:/* 你的代碼 */
<body>
<h1>什麽時候出現這裏的內容</h1>
<script>
// alert("Hello 1")
alert("Hello 2")
/*
這裏的內容也不會執行
alert("Hello 3")
*/
</script>
</body>
JavaScript 語句
js可以通過換行或者是分號來區分單獨的語句。所以對於單行語句,行尾有沒有分號都一樣。但是建議加上分號,這樣我們的js在編輯完成上線時,可以去掉語句間的縮進和換行(即變成很長的一行代碼),節省空間。保證用戶端的訪問的流暢。
學習JavaScript
變量
變量直接賦值就可以是使用:
<script>
a = "hello"
alert(a)
</script>
但是在函數中的變量就存在全局變量和局部變量的區別。需要先用var聲明變量,這個變量才是局部變量,否則就是全局變量。建議都先加上var聲明為局部變量。
<script>
function func() {
// 局部變量
var a = ‘A‘;
// 全局變量
b = ‘B‘
}
</script>
用控制臺調試js代碼
除了寫一個html文件來調試代碼外,也可以用瀏覽器自帶的控制臺來調試,用起來就類似一個IDE。
先用 about:blank
來打開一個空白頁,然後F12進入開發調試工具,找到控制臺(Console)標簽就可以在這裏直接寫代碼了。
另外使用js命令 console.log()
可以直接向你的控制臺輸出信息:
<body>
<script>
console.log("你好!")
</script>
</body>
打開這樣的一個頁面,應該是空白的,去控制臺看一下有沒有一條消息。
定義函數(function)
使用function來定義函數,後面跟函數名,然後是一個"{}"大括號。大括號js的代碼塊,大括號內部就是這個函數的代碼。
<script>
// 定義一個函數,函數名 fun
function fun() {
alert("你好!")
}
// 調用執行函數
fun();
</script>
數據類型
js中的數據類型分為原始類型和對象類型:
- 原始類型
- 數字
- 字符串
- 布爾值
- 對象類型
- 數組
- 字典
另外還有2個特別的值:
- null,它表示一個特殊值,常用來描述“空值”。
- undefined,是一個特殊值,表示變量未定義。
數字(Number)
字符串轉數字的方法:
parseInt() :轉為整形,不成功則NaN。
parseFloat() :轉為浮點數,不成功則NaN。
> parseInt(‘123‘)
< 123
> parseInt(‘123.123‘)
< 123
> parseInt(‘abc‘)
< NaN
> parseFloat(‘321‘)
< 321
> parseFloat(‘321.123‘)
< 321.123
>
一些常量:Math.E
:常量e,自然對數的底數。Math.PI
:圓周率。
一些靜態函數:Math.sin()
:計算正弦值Math.asin()
:計算反正弦值,根據值計算出弧度Math.cos()
:計算余弦值Math.acos()
:計算反余弦值,根據值計算出弧度Math.tan()
:計算正切值Math.atan()
:計算反正切值,根據值計算出弧度Math.abs()
:計算絕對值Math.round()
:返回一個整數,4舍5入。Math.ceil()
:返回一個整數,浮點數向上取整。Math.floor()
:返回一個整數,浮點數向下取整。
> Math.ceil(1.234)
< 2
> Math.ceil(-1.234)
< -1
> Math.floor(1.234)
< 1
> Math.floor(-1.234)
< -2
>
Math.random()
:生成隨機數Math.sqrt()
:計算平方根
字符串(String)
字符串是由字符組成的數組,但在JavaScript中字符串是不可變的:可以訪問字符串任意位置的文本,但是JavaScript並未提供修改已知字符串內容的方法。
常用方法:str.length
:獲取字符串的長度str.trim()
:移除字符串兩邊的空白,也可以指定只移除左邊(trimLeft)或右邊(trimRight)。
> str = ‘ abc ‘
< " abc "
> str.length // 字符串長度
< 7
> str.trim() // 移除空白
< "abc"
> str.trimLeft() // 移除左邊的空白
< "abc "
> str.trimRight() // 移除右邊的空白
< " abc"
>
str.concat()
:字符串拼接
> str = ‘aaa‘
< "aaa"
> str.concat(‘bbb‘)
< "aaabbb"
> str.concat(‘ ‘,‘bbb‘,‘ ‘,‘ccc‘,‘ ‘,111) // 可以拼接多個字符串,數字也能處理
< "aaa bbb ccc 111"
>
str.charAt()
:返回字符串中的第n個字符str.substring()
:根據索引獲取子序列,字符串切割。str.slice()
:字符串切片,其實和上面的subsring差不多。不過如果第一個參數大於第二個參數,這裏會返回空字符串,而substring會自動調整兩個參數的位置。
> str = ‘abcdefg‘
< "abcdefg"
> str.charAt(0) // 下標是0的字符
< "a"
> str.charAt(2) // 下標是2的字符
< "c"
> str.substring(2) // 返回下標2到末尾的字符串
< "cdefg"
> str.substring(2,5) // 返回下標2,到下標5(不包括)之前的字符串
< "cde"
> str.slice(2,5) // 結果和substring一樣
< "cde"
> str.substring(5,2) // 會自動調整參數位置
< "cde"
> str.slice(5,2) // 返回空字符串
< ""
>
到這裏可以先暫停一下,看一下下一個小標題定時器和跑馬燈示例str.indexOf()
:獲取子序列的下標str.lastIndexOf()
:獲取子序列的下標,從後往前找。
> str = ‘sonmething for nothing!‘
< "sonmething for nothing!"
> str.indexOf(‘thing‘)
< 5
> str.indexOf(‘thing‘,6) // 從下標6的位置開始查找
< 17
> str.lastIndexOf(‘thing‘,16) // 從下標16的位置開始往前查找
< 5
>
str.toLowerCase()
:轉為小寫字母str.toLocaleUpperCase()
:轉為大寫字母
> str = "Any Way"
< "Any Way"
> str.toLowerCase()
< "any way"
> str.toLocaleUpperCase()
< "ANY WAY"
>
str.split()
:把字符串分割成數組。第一個參數,指定進行分隔的字符串或正則表達式。第二個參數,指定返回數組的最大長度。
> str = ‘What are you doing?‘
< "What are you doing?"
> str.split() // 沒有參數的話,就沒有分隔,但是變成了一個數組
< [object Array]: ["What are you doing?"]
> str.split(‘ ‘) // 按空格進行分隔
< [object Array]: ["What", "are", "you", "doing?"]
> str.split(‘ ‘,2) // 指定返回數組的最大長度,多余的就丟棄了
< [object Array]: ["What", "are"]
> str.split(‘‘) // 如果按字符串進行分隔,就是分隔每個字符
< [object Array]: ["W", "h", "a", "t", " ", "a", "r", "e", " ", "y", "o", "u", " ", "d", "o", "i", "n", "g", "?"]
>
最後還有3個方法,先放這裏留個空,之後講正則表達式的時候還會再遇到。str.search()
:檢索字符串中指定的子字符串,或檢索與正則表達式相匹配的子字符串。str.match()
:在字符串內檢索指定的值,或找到一個或多個正則表達式的匹配。str.replace()
:在字符串中用一些字符替換另一些字符,或替換一個與正則表達式匹配的子串。
布爾值(Boolean)
js裏的布爾值分別是 ‘true‘ 和 ‘false‘ ,都是小寫的。
比較運算符:
==
:等於。值相等,類型可以不一樣!=
:不等於。只比較值===
:全等。值和類型都相等!==
:不等於。比較值和類型<
、>
、<=
、>=
:小於、大於、小於等於、大於等於
邏輯運算符:
&&
:and,與||
:or,或!
:not,非
數組(Array)
常用方法:arr.length
:數組的大小arr.push()
:向數組的末尾添加一個或多個元素,並返回新的長度arr.pop()
:刪除並返回數組的最後一個元素arr.unshift()
:向數組的開頭添加一個或更多元素,並返回新的長度arr.shift()
:刪除並返回數組的第一個元素
> arr = [11,22,33,44]
< [object Array]: [11, 22, 33, 44]
> arr.length
< 4
> arr.push(55,66) // 添加2個元素到末尾
< 6
> arr.pop() // 取出最後一個元素
< 66
> arr.unshift(‘a‘,‘b‘) // 在頭部插入2個元素
< 7
> arr.shift() // 取出第一個元素
< "a"
> arr // 現在數組的成員
< [object Array]: ["b", 11, 22, 33, 44, 55]
>
arr.splice()
:在數組中添加/刪除元素,然後返回被刪除的元素。
語法: arrayObject.splice(index,howmany,item1,.....,itemX)
index :必需。整數,規定起始元素的位置,使用負數可從數組結尾處規定位置。
howmany :必需。要刪除的元素數量。如果設置為 0,則不刪除元素。
item :可選。向數組添加的新元素。
> arr = [11,22,33,44]
< [object Array]: [11, 22, 33, 44]
> arr.splice(1,2,‘a‘,‘b‘,‘c‘) // 從下標1的位置,刪除2個元素,並且在這個位置插入新的元素
< [object Array]: [22, 33]
> arr // 操作後的數組
< [object Array]: [11, "a", "b", "c", 44]
>
arr.slice()
:切片arr.reverse()
:反轉arr.join()
:把數組中的所有元素拼接為一個字符串。參數可選,指定要使用的分隔符。如果省略參數,則使用逗號作為分隔符。arr.concat()
:連接兩個或多個數組。參數可以是具體的值,也可以是數組對象。可以是任意多個。arr.sort()
:對數組的元素進行排序
字典
字典沒有太多內容,直接看定義和取值的例子:
> dic = {‘k1‘:‘v1‘,‘k2‘:‘v2‘,‘k3‘:‘v3‘}
< [object Object]: {k1: "v1", k2: "v2", k3: "v3"}
> dic[‘k1‘]
< "v1"
>
定時器
使用setInterval可以創建一個定時器,第一個參數是要執行的代碼(一般是一個函數),第二個參數是間隔時間(ms)。
下面是一個每個一段時間彈框的例子:
<script>
// 創建一個定時器
// 第一個參數可以是一個函數,第二個參數是間隔時間(ms)
setInterval("alert(‘Hellow‘)", 2000)
</script>
跑馬燈示例
運用定時器和上面的字符串的內容來實現一個字符串滾動顯示的效果:
<body>
<div id="welcome">歡迎公司領導蒞臨指導。 </div>
<script>
function func() {
// 根據id來獲取到標簽
var tag = document.getElementById(‘welcome‘);
// 獲取標簽內部的內容
var content = tag.innerText;
var f = content.charAt(0);
var l = content.substring(1, content.length);
// 重新拼接成新的字符串
var new_content = l.concat(f);
// 給標簽內容重新賦值,賦值後頁面顯示就會有變化
tag.innerText = new_content;
}
setInterval("func()", 500)
</script>
</body>
JavaScript 語句
for/in 循環
遍歷的是索引,不是值。遍歷一個數組,遍歷的就是數組的下標:
> arr = [‘a‘,‘b‘,‘c‘,‘d‘]
< [object Array]: ["a", "b", "c", "d"]
> for (i in arr){
console.log(i) // 這個是下標不是值
console.log(arr[i]) // 這樣才能取到值
}
0
a
1
b
2
c
3
d
< undefined
>
遍歷一個字典,就是遍歷字典的key:
> dic = {‘k1‘:‘v1‘,‘k2‘:‘v2‘,‘k3‘:‘v3‘}
< [object Object]: {k1: "v1", k2: "v2", k3: "v3"}
> for (k in dic){
console.log(k);
console.log(dic[k]);
}
k1
v1
k2
k3
v3
< undefined
>
for 循環
這種for循環是用的比較多的。但是這種循環駕馭不了字典的key,所以遍歷不了字典。遇到字典的情況還是得用for/in。
for (語句 1; 語句 2; 語句 3)
{
被執行的代碼塊
}
語句1:在循環(代碼塊)開始前執行
語句2:定義運行循環(代碼塊)的條件
語句3:在循環(代碼塊)已被執行之後執行
> for (var i=0; i<5; i++){
console.log(i)
}
0
1
2
3
4
< undefined
>
if 語句
語法:
if (條件 1)
{
當條件 1 為 true 時執行的代碼
}
else if (條件 2)
{
當條件 2 為 true 時執行的代碼
}
else
{
當條件 1 和 條件 2 都不為 true 時執行的代碼
}
js的基礎先會這麽多,下一節在補充其他的內容
DOM
文檔對象模型 DOM(Document Object Model)是一種用於HTML和XML文檔的編程接口。它給文檔提供了一種結構化的表示方法,可以改變文檔的內容和呈現方式。我們最為關心的是,DOM把網頁和腳本以及其他的編程語言聯系了起來。DOM屬於瀏覽器,而不是JavaScript語言規範裏的規定的核心內容。
查找
首先,要先通過查找的方法獲取到對象。
直接查找
document.getElementById()
:根據ID獲取一個標簽document.getElementsByName()
:根據name屬性獲取標簽集合document.getElementsByClassName()
:根據class屬性獲取標簽集合document.getElementsByTagName()
:根據標簽名獲取標簽集合
根據ID獲取到的是唯一的值,返回的是對象。其他的方法獲取到的值可能是多個,返回的都是包含每一個對象的數組。
我們可以通過獲取對象的innerText屬性,來獲取到標簽中的文本內容。也可以通過修改這個屬性,來修改頁面的內容。
舉例:
<body>
<div id="i1" class="c1">我是i1</div>
<span>a</span>
<span>b</span>
<span>c</span>
<span>d</span>
<script>
i1 = document.getElementById(‘i1‘);
alert(i1.innerText); // 彈框顯示i1的信息
t1 = document.getElementsByTagName(‘span‘);
// 修改span標簽中的內容
for (var i=0; i<t1.length;i++){
t1[i].innerText = i;
}
</script>
</body>
間接查找
parentElement
:父標簽children
:所有子標簽集合,這個是數組firstElementChild
:第一個子標簽lastElementChild
:最後一個子標簽nextElementtSibling
:下一個兄弟標簽previousElementSibling
:上一個兄弟標簽
<body>
<div>我是父標簽
<div id="i1">我是i1
<div>我是子標簽1</div>
<div>我是子標簽2</div>
</div>
</div>
<div>(空)</div>
<script>
i1 = document.getElementById(‘i1‘); // 先獲取到i1標簽的對象
// 子標簽集合第一個元素的,下一個兄弟標簽的,文本內容
alert(i1.children[0].nextElementSibling.innerText);
// 修改父標簽的下一個兄弟標簽的內容
i1.parentElement.nextElementSibling.innerText = "我是父標簽的兄弟";
</script>
</body>
操作
之前我們已經對innerText屬性進行過操作了。能做的還有很多
操作內容
innerText
:開始和結束標簽之間的文本內容innerHTML
:開始和結束標簽之間的 HTML 內容value
:元素的值
操作對象的class屬性
className
:獲取所有類名classList.add
:添加一個類名classList.remove
:刪除一個類名
<body>
<div id="i1">我是i1</div>
<script>
d1 = document.getElementById(‘i1‘);
d1.className = ‘i1 i2 i3‘;
alert(d1.className);
d1.classList.remove(‘i2‘);
d1.classList.add(‘i4‘);
alert(d1.className);
</script>
</body>
後面示例中的模態對話框有應用場景的例子。操作起來比直接修改style方便。
事件
下面2個事件,後面的示例中會用到:
- onclick :事件會在對象被點擊時發生。
- onmouseover :事件會在鼠標指針移動到指定的對象上時發生。
後面的示例中有例子。這裏直接跳到後面看示例就好。
下面關於事件的內容還未學習,應該是下次要講的補充內容了。
事件句柄 (Event Handlers)
屬性 | 此事件發生在何時... |
---|---|
onabort | 圖像的加載被中斷。 |
onblur | 元素失去焦點。 |
onchange | 域的內容被改變。 |
onclick | 當用戶點擊某個對象時調用的事件句柄。 |
ondblclick | 當用戶雙擊某個對象時調用的事件句柄。 |
onerror | 在加載文檔或圖像時發生錯誤。 |
onfocus | 元素獲得焦點。 |
onkeydown | 某個鍵盤按鍵被按下。 |
onkeypress | 某個鍵盤按鍵被按下並松開。 |
onkeyup | 某個鍵盤按鍵被松開。 |
onload | 一張頁面或一幅圖像完成加載。 |
onmousedown | 鼠標按鈕被按下。 |
onmousemove | 鼠標被移動。 |
onmouseout | 鼠標從某元素移開。 |
onmouseover | 鼠標移到某元素之上。 |
onmouseup | 鼠標按鍵被松開。 |
onreset | 重置按鈕被點擊。 |
onresize | 窗口或框架被重新調整大小。 |
onselect | 文本被選中。 |
onsubmit | 確認按鈕被點擊。 |
onunload | 用戶退出頁面。 |
對於事件需要註意的要點:
- this :當前正在操作的標簽
- event :封裝了當前事件的內容
- 事件鏈以及跳出
示例
模態對話框
這裏的思路是,單獨定義個hide的class,樣式裏定義隱藏屬性(display: none;)。只要有標簽加上hide這個class,就會被隱藏。我們之後只需要進行標簽的class的add和remove的操作,就實現了樣式的變化。
實現的方法有很多,直接把display寫在class的樣式裏,然後修改樣式的屬性也是可以的。
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
/*遮罩層樣式*/
.c1{
position: fixed;
top: 0;
bottom: 0;
right: 0;
left: 0;
background-color: black;
opacity: 0.6;
z-index: 5;
}
/*彈出框樣式*/
.c2{
width: 500px;
height: 400px;
background-color: pink;
position: fixed;
left: 50%;
margin-left: -250px;
margin-top: 100px;
z-index: 10;
}
/*顯示/隱藏 遮罩層和彈出框*/
.hide{
display: none;
}
</style>
</head>
<body>
<div>
點擊
<input type="button" value="按鈕" onclick="ShowModel()" />
彈出對話框
</div>
<!--遮罩層-->
<div class="c1 hide" id="i1"></div>
<!--彈出框-->
<div class="c2 hide" id="i2">
<div style="padding: 100px 50px">
<p>
<label for="username">用戶名:</label>
<input type="text" id="username" />
</p>
<p>
<label for="password">密碼:</label>
<input type="password" id="password" />
</p>
<p>
<input type="button" value="確定" onclick="HideModel()" />
<input type="button" value="取消" onclick="HideModel()" />
</p>
</div>
</div>
<script>
function ShowModel() {
document.getElementById(‘i1‘).classList.remove(‘hide‘)
document.getElementById(‘i2‘).classList.remove(‘hide‘)
}
function HideModel() {
document.getElementById(‘i1‘).classList.add(‘hide‘)
document.getElementById(‘i2‘).classList.add(‘hide‘)
}
</script>
</body>
全選、取消、反選
操作選擇框:對於單選框(type="radio")和復選框(type="checkbox"),可以通過checked屬性獲取它當前的狀態,true為選中,false未選中。也可以通過賦值來改變它的狀態。
<body>
<div>
<input type="button" value="全選" onclick="ChooseAll()">
<input type="button" value="取消" onclick="CancelAll()">
<input type="button" value="反選" onclick="Reverse()">
</div>
<div>
<table border="3">
<thead>
<tr>
<th>choice</th>
<th>name</th>
<th>age</th>
</tr>
</thead>
<tbody id="tb">
<tr>
<td><input type="checkbox" title="choose the student"></td>
<td>Adam</td>
<td>23</td>
</tr>
<tr>
<td><input type="checkbox" title="choose the student"></td>
<td>Bob</td>
<td>24</td>
</tr>
<tr>
<td><input type="checkbox" title="choose the student"></td>
<td>Clark</td>
<td>25</td>
</tr>
</tbody>
</table>
</div>
<script>
function ChooseAll() {
var tbody = document.getElementById(‘tb‘);
var tr_list = tbody.children;
for (var i=0; i<tr_list.length; i++){
var checkbox = tr_list[i].firstElementChild.firstElementChild;
checkbox.checked = true;
}
}
function CancelAll() {
var tbody = document.getElementById(‘tb‘);
var tr_list = tbody.children;
for (var i=0; i<tr_list.length; i++){
var checkbox = tr_list[i].firstElementChild.firstElementChild;
checkbox.checked = false;
}
}
function Reverse() {
var tbody = document.getElementById(‘tb‘);
var tr_list = tbody.children;
for (var i=0; i<tr_list.length; i++){
var checkbox = tr_list[i].firstElementChild.firstElementChild;
checkbox.checked = !checkbox.checked;
}
}
</script>
</body>
後臺管理左側菜單
這裏采用了鼠標懸停事件(onmousemove),會展開當前菜單。子菜單的隱藏依舊是通過操作class屬性實現的。
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
.hide{
display: none;
}
.item .header{
height: 35px;
background-color: blue;
color: white;
line-height: 35px;
}
</style>
</head>
<body>
<div style="height: 48px"></div>
<div style="width: 300px">
<div class="item">
<div class="header" onmousemove="ShowMenu(this)">菜單1</div>
<div class="content hide">
<div>內容1-1</div>
<div>內容1-2</div>
<div>內容1-3</div>
</div>
</div>
<div class="item">
<div class="header" onmousemove="ShowMenu(this)">菜單2</div>
<div class="content hide">
<div>內容2-1</div>
<div>內容2-2</div>
<div>內容2-3</div>
</div>
</div>
<div class="item">
<div class="header" onmousemove="ShowMenu(this)">菜單3</div>
<div class="content hide">
<div>內容3-1</div>
<div>內容3-2</div>
<div>內容3-3</div>
</div>
</div>
</div>
<script>
function ShowMenu(x){
var content_list = document.getElementsByClassName(‘content‘);
for (var i=0; i<content_list.length; i++){
content_list[i].classList.add(‘hide‘)
}
x.nextElementSibling.classList.remove(‘hide‘)
}
</script>
</body>
作業
電子商務網站頁面(動態)(仿京東),要做4個頁面
主頁
主要是實現中間的那個部分,四分格的商品展示的樣式。還要做返回頂部的功能
登陸
要做出右邊有圖標的input框
註冊
紅色的星號(*)表示必填項
購物車
左邊有菜單:類似後臺管理的左側菜單
右邊有表格:表格要有全選、反選。還能用模態框添加內容
Python自動化開發學習15-JavaScript和DOM