文章目錄
一、Vue:
1. vue 是什麼?
- Vue (讀音 /vjuː/,類似於 view) 是一套用於構建用戶界面的漸進式框架;
- vue 的核心庫只關注視圖層,不僅易於上手,還便於與第三方庫或既有項目整合;
- 漸進式: 聲明式渲染 -> 組件系統 -> 客戶端路由 -> 集中式狀態管理 -> 項目構建
- 官網: https://cn.vuejs.org/
2. Vue基本使用
<head>
<title>01_hello VUE</title>
<script src="../vue.js"></script>
</head>
<body>
<div id="app">
<div>{{msg}}</div>
</div>
<script>
// Vue的基本使用步驟:
// 1. 需要提供標籤用於填充數據;
// 2. 引入vue.js庫文件;
// 3. 可以使用vue的語法做功能;
// 4. 把vue提供的數據填充到標籤裏面;
var vm = new Vue({
el: "#app",
data: {
msg: "Hello Vue"
}
})
</script>
</body>
- 實例參數分析:
- el: 元素的掛載位置(值可以使css選擇器或DOM元素);
- data: 模型數據(值是一個對象)
- 插值表達式用法:
- 將數據填充到html標籤中;
- 插值表達式支持基本的計算操作;
- Vue代碼運行原理分析:
3. :使用Vue將helloworld 渲染到頁面上:
3.1 模板語法概述:
如何理解前端渲染:
把數據填充到HTML標籤中
前端渲染方式:
- 原生js拼接字符串;
- 使用前端模板引擎;
- 使用vue特有的模板語法;
vue模板語法:
- 插值表達式;
- 指令;
- 事件綁定;
- 屬性綁定;
- 分支循環結構;
二、指令:
1. 什麼是指令:
- 本質就是自定義屬性
- Vue中指定都是以 v- 開頭;
2. v-cloak 防止閃動:
防止頁面加載時出現閃爍問題:
<style type="text/css">
/*
1、通過屬性選擇器 選擇到 帶有屬性 v-cloak的標籤 讓他隱藏
*/
[v-cloak]{
/* 元素隱藏*/
display: none;
}
</style>
<body>
<div id="app">
<!--
2、 讓帶有插值 語法的 添加 v-cloak 屬性
在數據渲染完場之後,v-cloak 屬性會被自動去除,
v-cloak一旦移除也就是沒有這個屬性了 屬性選擇器就選擇不到該標籤
也就是對應的標籤會變爲可見
-->
<div v-cloak >{{msg}}</div>
</div>
<script type="text/javascript" src="js/vue.js"></script>
<script type="text/javascript">
var vm = new Vue({
// el 指定元素 id 是 app 的元素
el: '#app',
// data 裏面存儲的是數據
data: {
msg: 'Hello Vue'
}
});
</script>
</body>
</html>
3. 渲染:
3.1 v-text 將數據填充到標籤中:
- v-text指令用於將數據填充到標籤中,作用於插值表達式類似,但是沒有閃動問題;
- 如果數據中有HTML標籤會將html標籤一併輸出;
- 注意:此處爲單向綁定,數據對象上的值改變,插值會發生變化;但是當插值發生變化並不會影響數據對象的值;
<head>
<title>01_hello VUE</title>
<script src="../vue.js"></script>
</head>
<body>
<div id="app">
<div>{{msg}}</div>
<div v-text="msg"></div>
<!-- 注意:在指令中不要寫插值語法 直接寫對應的變量名稱
在 v-text 中 賦值的時候不要在寫 插值語法
一般屬性中不加 {{}} 直接寫 對應 的數據名 -->
</div>
<script>
var vm = new Vue({
el: "#app",
data: {
msg: "Hello Vue"
}
})
</script>
</body>
3.2 v-html 將HTML片段填充到標籤中:
- 用法和v-text 相似 但是他可以將HTML片段填充到標籤中;
- 可能有安全問題, 一般只在可信任內容上使用 v-html,永不用在用戶提交的內容上;
- 它與v-text區別在於v-text輸出的是純文本,瀏覽器不會對其再進行html解析,但v-html會將其當html標籤解析後輸出;
<div id="app">
<p v-html="html"></p> <!-- 輸出:html標籤在渲染的時候被解析 -->
<p>{{message}}</p> <!-- 輸出:<span>通過雙括號綁定</span> -->
<p v-text="text"></p> <!-- 輸出:<span>html標籤在渲染的時候被源碼輸出</span> -->
</div>
<script>
let app = new Vue({
el: "#app",
data: {
message: "<span>通過雙括號綁定</span>",
html: "<span>html標籤在渲染的時候被解析</span>",
text: "<span>html標籤在渲染的時候被源碼輸出</span>",
}
});
</script>
3.3 v-pre 跳過編譯過程:
- 顯示原始信息跳過編譯過程;
- 跳過這個元素和它的子元素的編譯過程;
- 一些靜態的內容不需要編譯加這個指令可以加快渲染;
<span v-pre>{{ this will not be compiled }}</span>
<!-- 顯示的是{{ this will not be compiled }} -->
<span v-pre>{{msg}}</span>
<!-- 即使data裏面定義了msg這裏仍然是顯示的{{msg}} -->
<script>
new Vue({
el: '#app',
data: {
msg: 'Hello Vue.js'
}
});
</script>
4. 數據響應式:
4.1 如何理解數據響應式:
- html5中的響應式(屏幕尺寸的變化導致樣式的變化);
- 數據的響應式(數據的變化導致頁面內容的變化);
4.2 什麼是數據綁定;
- 數據綁定: 將數據填充到標籤中;
4.3 v-once: 只編譯一次
顯示內容之後不再具有響應式;
<div v-once>{{info}}</div>
5. 雙向數據綁定:
- 當數據發生變化的時候,視圖也就發生變化;
- 當視圖發生變化的時候,數據也會跟着同步變化;
5.1 v-model:
- v-model是一個指令,限制在 <input>、<select>、<textarea>、<components>中使用:
<div id="app">
<div>{{msg}}</div>
<div>
當輸入框中內容改變的時候, 頁面上的msg 會自動更新
<input type="text" v-model='msg'>
</div>
</div>
5.2 mvvm
- MVC 是後端的分層開發概念; MVVM是前端視圖層的概念,主要關注於 視圖層分離,也就是說:MVVM把前端的視圖層,分爲了 三部分 Model, View , VM ViewModel;
- m model
- 數據層 Vue 中 數據層 都放在 data 裏面
- v view 視圖
- Vue 中 view 即 HTML頁面
- vm (view-model) 控制器 將數據和視圖層建立聯繫
- vm 即 Vue 的實例 就是 vm
三、事件綁定:
1. v-on
1.1 v-on基本用法:
- 用來綁定事件的
<button v-on:click='num++'>點擊</button>
- 形式如:v-on:click 縮寫爲 @click;
<button @click='num++'>點擊</button>
1.2 v-on事件函數調用:
直接綁定函數名稱:
<button @click='handle1'>點擊1</button>
調用函數:
<button @click='handle2()'>點擊2</button>
事件函數傳參:
- 如果事件直接綁定函數名稱,那麼默認會傳遞事件對象作爲事件函數的第一個參數;
- 如果事件綁定函數調用,那麼事件對象必須作爲最後一個參數顯示傳遞, 並且事件對象的名稱必須是$event;
<button v-on:click='handle2(123, 456, $event)'>點擊2</button>
代碼演示:
<head>
<title>v_on</title>
<script src="../vue.js"></script>
</head>
<body>
<div id="app">
<div>{{num}}</div>
<div>
<button v-on:click='handle1'>點擊1</button>
<button v-on:click='handle2(123, 456, $event)'>點擊2</button>
</div>
</div>
<script type="text/javascript" src="js/vue.js"></script>
<script type="text/javascript">
var vm = new Vue({
el: '#app',
data: {
num: 0
},
methods: {
handle1: function(event) {
console.log(event.target.innerHTML)
},
handle2: function(p, p1, event) {
console.log(p, p1)
console.log(event.target.innerHTML)
this.num++;
}
}
});
</script>
</body>
1.3 事件修飾符:
- 在事件處理程序中調用 event.preventDefault() 或 event.stopPropagation() 是非常常見的需求。
- Vue 不推薦操作DOM 爲了解決這個問題,Vue.js 爲 v-on 提供了事件修飾符
- 修飾符是由點開頭的指令後綴來表示的
<!-- 阻止單擊事件繼續傳播 -->
<a v-on:click.stop="doThis"></a>
<!-- 提交事件不再重載頁面 -->
<form v-on:submit.prevent="onSubmit"></form>
<!-- 修飾符可以串聯 即阻止冒泡也阻止默認事件 -->
<a v-on:click.stop.prevent="doThat"></a>
<!-- 只當在 event.target 是當前元素自身時觸發處理函數 -->
<!-- 即事件不是從內部元素觸發的 -->
<div v-on:click.self="doThat">...</div>
使用修飾符時,順序很重要;相應的代碼會以同樣的順序產生;因此,用 v-on:click.prevent.self 會阻止所有的點擊,而 v-on:click.self.prevent 只會阻止對元素自身的點擊;
1.4 按鍵修飾符:
- 在做項目中有時會用到鍵盤事件,在監聽鍵盤事件時,我們經常需要檢查詳細的按鍵。Vue 允許爲 v-on 在監聽鍵盤事件時添- 加按鍵修飾符
- 常用的按鍵修飾符
修飾符 | 表示 |
---|---|
.enter | enter鍵 |
.tab | tab鍵 |
.delete (捕獲“刪除”和“退格”按鍵) | 刪除鍵 |
.esc | 取消鍵 |
.space | 空格鍵 |
.up | 上 |
.down | 下 |
.left | 左 |
.right | 右 |
<!-- 只有在 `keyCode` 是 13 時調用 `vm.submit()` -->
<input v-on:keyup.13="submit">
<!-- -當點擊enter 時調用 `vm.submit()` -->
<input v-on:keyup.enter="submit">
<!--當點擊enter或者space時 時調用 `vm.alertMe()` -->
<input type="text" v-on:keyup.enter.space="alertMe" >
<script>
var vm = new Vue({
el:"#app",
methods: {
submit:function(){},
alertMe:function(){},
}
})
</script>
1.4 自定義按鍵修飾符別名
- 在Vue中可以通過config.keyCodes自定義按鍵修飾符別名;
<div id="app">
預先定義了keycode 116(即F5)的別名爲f5,因此在文字輸入框中按下F5,會觸發prompt方法
<input type="text" v-on:keydown.f5="prompt()">
</div>
<script>
Vue.config.keyCodes.f5 = 116;
let app = new Vue({
el: '#app',
methods: {
prompt: function() {
alert('我是 F5!');
}
}
});
</script>
1.5 案例:簡單計算器:
需求:
實現簡單的加法計算, 分別輸入數值a和b, 點擊計算, 結果顯示在下面
分析:
- 通過v-model指令實現數值a和b的綁定;
- 給計算按鈕綁定事件, 實現計算邏輯;
- 將計算結果綁定到對應位置;
實現:
<head>
<title>簡單計算器</title>
<script src="../vue.js"></script>
</head>
<body>
<div id="app">
<h1>簡單計算器</h1>
<div>
數值A:
<input type="text" v-model='a'>
</div>
<div>
數值B:
<input type="text" v-model='b'>
</div>
<button @click="handleAdd">計算</button>
<div>
計算結果:
<span v-text='r'></span>
</div>
</div>
<script>
var vm = new Vue({
el: "#app",
data: {
a:0,
b:0,
r:0
},
methods: {
handleAdd: function() {
this.r = parseFloat(this.a) + parseFloat(this.b);
}
}
});
</script>
</body>
四、屬性綁定:
1. v-bind
- v-bind 指令被用來響應地更新 HTML 屬性
- v-bind:href 可以縮寫爲 :href;
<!-- 綁定一個屬性 -->
<img v-bind:src="imageSrc">
<!-- 縮寫 -->
<img :src="imageSrc">
2. v-model的底層實現原理分析:
<input v-bind:value="msg" v-on:input="msg=$event.target.value">
五、樣式綁定:
1. 綁定對象:
- 可以給v-bind:class 一個對象,以動態地切換class。
- 注意:v-bind:class指令可以與普通的class特性共存
1.1 v-bind 中支持綁定一個對象
如果綁定的是一個對象 則 鍵爲 對應的類名 值 爲對應data中的數據 :
HTML最終渲染爲 <ul class=“box textColor textSize”></ul>
注意:
- textColor,textSize 對應的渲染到頁面上的CSS類名
- isColor,isSize 對應vue data中的數據 如果爲true 則對應的類名 渲染到頁面上
- 當 isColor 和 isSize 變化時,class列表將相應的更新, 例如,將isSize改成false,class列表將變爲 <ul class=“box textColor”></ul>
<ul class="box" v-bind:class="{textColor:isColor, textSize:isSize}">
<li>學習Vue</li>
<li>學習Node</li>
<li>學習React</li>
</ul>
<div v-bind:style="{color:activeColor,fontSize:activeSize}">對象語法</div>
<sript>
var vm= new Vue({
el:'.box',
data:{
isColor:true,
isSize:true,
activeColor:"red",
activeSize:"25px",
}
})
</sript>
<style>
.box{
border:1px dashed #f0f;
}
.textColor{
color:#f00;
background-color:#eef;
}
.textSize{
font-size:30px;
font-weight:bold;
}
</style>
1.2 v-bind 中支持綁定一個數組:
v-bind 中支持綁定一個數組 數組中classA和 classB 對應爲data中的數據
- 這裏的classA 對用data 中的 classA
- 這裏的classB 對用data 中的 classB
<ul class="box" :class="[classA, classB]">
<li>學習Vue</li>
<li>學習Node</li>
<li>學習React</li>
</ul>
<script>
var vm= new Vue({
el:'.box',
data:{
classA:‘textColor‘,
classB:‘textSize‘
}
})
</script>
<style>
.box{
border:1px dashed #f0f;
}
.textColor{
color:#f00;
background-color:#eef;
}
.textSize{
font-size:30px;
font-weight:bold;
}
</style>
1.3 樣式綁定相關語法細節:
- 對象綁定和數組綁定可以結合使用;
- class綁定的值可以簡化操作;
- 默認的class如何處理;
<head>
<meta charset="UTF-8">
<title>Document</title>
<style type="text/css">
.active {
border: 1px solid red;
width: 100px;
height: 100px;
}
.error {
background-color: orange;
}
.test {
color: blue;
}
.base {
font-size: 28px;
}
</style>
</head>
<body>
<div id="app">
<div v-bind:class='[activeClass, errorClass, {test: isTest}]'>測試樣式</div>
<div v-bind:class='arrClasses'></div>
<div v-bind:class='objClasses'></div>
<div class="base" v-bind:class='objClasses'></div>
<button v-on:click='handle'>切換</button>
</div>
<script type="text/javascript" src="js/vue.js"></script>
<script type="text/javascript">
var vm = new Vue({
el: '#app',
data: {
activeClass: 'active',
errorClass: 'error',
isTest: true,
arrClasses: ['active','error'],
objClasses: {
active: true,
error: true
}
},
methods: {
handle: function(){
// this.isTest = false;
this.objClasses.error = false;
}
}
});
</script>
</body>
1.3 綁定對象和綁定數組 的區別
- 綁定對象的時候 對象的屬性 即要渲染的類名 對象的屬性值對應的是 data 中的數據;
- 綁定數組的時候數組裏面存的是data 中的數據;
2. 綁定style:
- CSS 屬性名可以用駝峯式 (camelCase) 或短橫線分隔 (kebab-case,記得用單引號括起來);
- 組語法可以將多個樣式對象應用到同一個元素;
<body>
<div id="app">
<div v-bind:style='{border: borderStyle, width: widthStyle, height: heightStyle}'></div>
<div v-bind:style='objStyles'></div>
<div v-bind:style='[objStyles, overrideStyles]'></div>
<button v-on:click='handle'>切換</button>
</div>
<script type="text/javascript" src="js/vue.js"></script>
<script type="text/javascript">
/*
樣式綁定之內聯樣式Style:
*/
var vm = new Vue({
el: '#app',
data: {
borderStyle: '1px solid blue',
widthStyle: '100px',
heightStyle: '200px',
objStyles: {
border: '1px solid green',
width: '200px',
height: '100px'
},
overrideStyles: {
border: '5px solid orange',
backgroundColor: 'blue'
}
},
methods: {
handle: function(){
this.heightStyle = '100px';
this.objStyles.width = '100px';
}
}
});
</script>
</body>
六、分支/循環結構:
1. 分支結構:
1.1 v-if 使用場景
- 多個元素 通過條件判斷展示或者隱藏某個元素, 或者多個元素;
- 進行兩個視圖之間的切換;
<head>
<title>分支結構</title>
<script src="../vue.js"></script>
</head>
<body>
<div id="app">
<div v-if="score>=90">優秀</div>
<div v-else-if="score>=75">一般</div>
<div v-else-if="score>=60">及格</div>
<div v-else>不及格</div>
<div :style="objStyle" v-show="flag"></div>
<button @click="handle">切換</button>
</div>
<script>
var vm = new Vue({
el: "#app",
data: {
score: 50,
flag: true,
objStyle: {
width: "100px",
height: "100px",
border: "1px solid red"
}
},
methods: {
handle: function() {
this.flag = !this.flag;
}
}
})
</script>
</script>
</body>
1.2 v-show 和 v-if的區別
- v-show本質就是標籤display設置爲none,控制隱藏;
- v-show只編譯一次,後面其實就是控制css,而v-if不停的銷燬和創建,故v-show性能更好一點;
- v-if是動態的向DOM樹內添加或者刪除DOM元素;
- v-if切換有一個局部編譯/卸載的過程,切換過程中合適地銷燬和重建內部的事件監聽和子組件;
2. 循環結構:
2.1 v-for遍歷數組:
<li v-for='item in list'> {{item}} </li>
<li v-for='(item, index) in list'> {{item}} + "-----" + {{index}}</li>
<ul id="example-1">
<!-- 循環結構-遍歷數組
item 是自己定義的一個名字 代表數組裏面的每一項
items對應的是 data中的數組-->
<li v-for="item in items">
{{ item.message }}
</li>
</ul>
<script>
new Vue({
el: '#example-1',
data: {
items: [
{ message: 'Foo' },
{ message: 'Bar' }
],
}
})
</script>
- 不推薦同時使用 v-if 和 v-for;
- 當 v-if 與 v-for 一起使用時,v-for 具有比 v-if 更高的優先級;
<head>
<title>Document</title>
<script src="../vue.js"></script>
</head>
<body>
<div id="app">
<div v-if='v==13' v-for='(v,k,i) in obj'>{{v + '---' + k + '---' + i}}</div>
</div>
<script>
new Vue({
el: '#app',
data: {
items: [
{ message: 'Foo' },
{ message: 'Bar' }
],
obj: {
uname: 'zhangsan',
age: 13,
gender: 'female'
}
}
})
</script>
</body>
2.2 key的作用:
幫助vue區分不同的元素, 從而提高性能
<li :key='item:id' v-for='(item, index) in list '>{{item}} + '-----' + {{index}}</li>
七、案例: Tab選項卡:
1. 需求:
2. 實現步驟:
-
實現靜態UI效果;
- 用傳統的方式實現標籤結構和樣式;
-
基於數據重構UI效果:
- 將靜態的結構和樣式重構爲基於Vue模板語法的形式;
- 處理事件綁定和js控制邏輯;
-
聲明式編程:
- 模板的結構和最終顯示的效果基本一致;
3. 實現過程:
3.1 靜態ui:
3.2 把數據渲染到頁面:
- 把tab欄 中的數替換到頁面上:
- 把 data 中 title 利用 v-for 循環渲染到頁面上;
- 把 data 中 path利用 v-for 循環渲染到頁面上;
3.3 給每一個tab欄添加事件,並讓選中的高亮:
-
讓默認的第一項tab欄高亮:
- tab欄高亮 通過添加類名active 來實現 (CSS active 的樣式已經提前寫好);
- 在data 中定義一個 默認的 索引 currentIndex 爲 0;
- 給第一個li 添加 active 的類名;
- 通過動態綁定class 來實現 第一個li 的索引爲 0 和 currentIndex 的值剛好相等;
- currentIndex === index 如果相等 則添加類名 active 否則 添加 空類名;
-
讓默認的第一項tab欄對應的img 顯示:
- 實現思路 和 第一個 tab 實現思路一樣 只不過 這裏控制第一個img 顯示的類名是 current;
3.4 點擊每一個tab欄 當前的高亮 其他的取消高亮
- 給每一個li添加點擊事件;
- 讓當前的索引 index 和 當前 currentIndex 的 值 進項比較;
- 如果相等 則當前li 添加active 類名 當前的 li 高亮 當前對應索引的 img 添加 current 當前img 顯示 其他隱藏;
4. 實現:
<head>
<title>tab欄切換</title>
<style>
* {
padding: 0;
margin: 0;
}
.tab {
margin: 100px auto;
width: 800px;
}
.tab ul {
overflow: hidden;
}
.tab ul li{
/* 爲元素指定的任何內邊距和邊框都將在已設定的寬度和高度內進行繪製 */
box-sizing: border-box;
padding: 0;
float: left;
width: 100px;
height: 45px;
list-style: none;
text-align: center;
line-height: 45px;
border-top: 1px solid blue;
border-right: 1px solid blue;
cursor: pointer;
}
.tab ul li:first-child {
border-left: 1px solid blue;
}
.tab ul li.active {
background-color: orange;
}
.tab div {
width: 540px;
height: 304px;
overflow: hidden;
text-align: center;
font-size: 30px;
line-height: 310px;
border: 1px solid blue;
border-top: 0px;
}
.tab div img {
display: none;
}
.tab div img.current {
display: block;
}
</style>
</head>
<body>
<div id="app">
<div class="tab">
<ul>
<li @click='change(index)' :class='currentIndex==index ? "active" : ""' :key='item.id' v-for='(item, index) in imgList'>{{item.title}}</li>
</ul>
<div>
<img :class='currentIndex==index ? "current" : ""' :key='item.id' v-for='(item, index) in imgList' :src="item.path">
</div>
</div>
</div>
<script src="../../vue.js"></script>
<script>
var vm = new Vue({
el: "#app",
data: {
currentIndex: 0,
imgList: [
{
id:1,
title: '圖片',
path: './images/1.jpg'
},
{
id:2,
title: '圖片二',
path: './images/2.jpg'
},
{
id:3,
title: '圖片三',
path: './images/3.jpg'
}
]
},
methods: {
change: function(index) {
this.currentIndex = index;
}
}
})
</script>
</body>