快速入門#
環境配置#
獲取 vue.js 文件
前往官網下載 vue2
去除瀏覽器提示#
- 瀏覽器下載開發者工具
2.html 中 js 腳本關閉生產提示
<script>
Vue.config.productionTip = false //關閉生產vue提示
</script>
基本使用#
創建容器#
el 的其他寫法#
<script>
Vue.config.productionTip = false //關閉生產vue提示
const v = new Vue({
// el:"#app",
data: {
name: "miaolme"
}
})
// 1s後執行
setTimeout(() => {
v.$mount("#app") //設置el
}, 1000);
</script>
data 的兩種寫法#
函數式
//1. 創建vue核心對像
new Vue({
el:"#app",
data: function(){
return {
username:""
}
}
});
簡寫
//1. 創建vue核心對像
new Vue({
el: "#app",
data() {
return {
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>Vue使用</title>
<script src="./js/vue2.js"></script>
</head>
<body>
<div id="app">
<input v-model="username">
<!-- 插值表達式 -->
{{username}}
</div>
</body>
<script>
//1. 創建vue核心對像
new Vue({
el: "#app",
data() {
return {
username: ""
}
}
})
</script>
</html>
Vue 常用指令#
指令:HTML 標籤上帶有 V - 前綴的特殊屬性,不同指令具有不同含義
指令 | 作用 |
---|---|
v-bind | 為 HTML 標籤綁定屬性值,如設置href ,css 樣式等 |
v-model | 在表單元素上創建雙向數據綁定 |
v-on | 為 HTML 標籤綁定事件 |
v-if v-else v-else-if | 條件性的渲染某元素,判定為 true 時渲染,否則不渲染 |
v-show | 根據條件展示某元素,區別在於切換的是 display 屬性的值 |
v-for | 列表渲染,遍歷容器的元素或者對象的屬性 |
v-model#
v-model 在表單元素上創建雙向數據綁定
表單的變化會影響整個 vue 的設定值
v-bind#
修改href,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>Vue使用</title>
<script src="./js/vue2.js"></script>
</head>
<body>
<div id="app">
<a v-bind:href="url">點擊一下</a>
<br>
<a :href="url">簡化格式</a>
</div>
</body>
<script>
//1. 創建vue核心對像
new Vue({
el: "#app",
data() {
return {
username: "",
url: "https://baidu.com"
}
}
})
</script>
</html>
v-on#
定義事件
<!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>Vue使用</title>
<script src="./js/vue2.js"></script>
</head>
<body>
<!-- 這個div中的id決定了下方vue是否可用 -->
<div id="app">
<input type="button" value="一個按鈕" v-on:click="show()">
<br>
<!-- 簡化書寫 -->
<input type="button" value="第二個按鈕" @click="show()">
</div>
</body>
<script>
//1. 創建vue核心對像
new Vue({
el: "#app",
data() {
return {
username: "",
url: "https://baidu.com"
}
},
methods: {
show() {
alert("我被點中了",number)
}
}
/*
methods: {
show(number) { //可以傳參
alert("我被點中了",number)
}
}
*/
})
</script>
</html>
<input type="button" value="一個按鈕" v-on:click="show()">
<!-- 簡化書寫 -->
<input type="button" value="第二個按鈕" @click="show()">
v-for#
列表渲染,遍歷容器的元素或者對象的屬性
v-for:
<div v-for='addr in addrs'>
{{addr}}<br>
</div>
加索引
<div v-for="(addr,i) in addrs">
<!-- i表示索引,從0開始 -->
{{i + 1}}:{{addr}}<br>
</div>
<!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/vue2.js"></script>
</head>
<body>
<div id="app">
<div v-for="addr in addrs">
{{addr}} <br>
</div>
<hr>
<div v-for="(addr,i) in addrs">
{{i+1}}--{{addr}} <br>
</div>
</div>
</body>
<script>
new Vue({
el: "#app",
data() {
return {
addrs: ["北京", "上海", "天津"]
}
}
})
</script>
</html>
Vue 數據代理#
對象添加數據#
Object.defineProperty
<script>
let person = {
name: "張三",
sex: "男"
}
Object.defineProperty(person, 'age', {
value: 18 //往person對象中添加一個新的鍵值對 age:18
enumerable: true //控制屬性是否可枚舉,默認false
writable: true //控制屬性是否可用被修改,默認false
configurable: true //控制屬性是否可被刪除,默認false
})
console.log(person) //{name: '張三', sex: '男', age: 18}
</script>
默認:不可枚舉,不可遍歷,不可修改,不可刪除
let person = {
name: "張三",
sex: "男"
}
let number = 18
Object.defineProperty(person, 'age', {
/*
get: function () {
return number //每次調用age的值會返回number
}
*/
//簡寫
get(){
return number //每次調用age的值會返回number
},
//當有人修改person的age屬性時,set函數(setter)就會被調用,且會收到修改的具體值
set(value){
console.log('有人修改了age屬性,且修改的值是',value)
number = value
}
})
console.log(person)
事件處理#
new Vue({
el: "#App",
data: {
name: 'xingli'
},
methods: {
showInfo(e) {
console.log(e.target.value)
}
},
})
方法寫入 method 中
v-on#
用於事件綁定,可以用 @代替 例如 @click
@click.stop 停止事件冒泡
Vue 中的事件修飾符:
1.prevent: 阻止默認事件(常用);
2.stop: 阻止事件冒泡(常用);
3.once: 事件只觸發一次(常用);
4.capture: 使用事件的捕獲模式; 在事件捕獲階段進行事件處理,自上而下
5.self: 只有 event.target 是當前操作的元素是才觸發事件;
6.passive: 事件的默認行為立即執行,無需等待事件回調執行完畢;
鍵盤事件#
綁定 vue 按鍵事件的 @
常用@keydown
@keyup
Vue 中常用的按鍵別名:
- 回車 =>enter
- 刪除 =>delete (捕獲 “刪除” 和 “退格” 鍵)
- 退出 =>esc
- 空格 =>space
- 換行 =>tab
- 上 =>up
- 下 =>down
- 左 =>left
- 右 =>right
<!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/vue2.js"></script>
</head>
<body>
<div id="App">
<input type="text" placeholder="按下回車提示輸入" @keyup="showInfo">
</div>
</body>
<script>
new Vue({
el: "#App",
data: {
name: 'xingli'
},
methods: {
showInfo(e) {
if (e.keyCode !== 13) return //設置按下回車返回輸入值
console.log(e.target.value)
}
},
})
</script>
</html>
2.Vue 未提供別名的按鍵,可以使用按鍵原始的 key 值去綁定,但注意要轉為 kebab-case (短橫線命名)
showInfo(e) {//使用該代碼可以得到key值
console.log(e.key)
console.log(e.keyCode)
}
**4. 也可以使用 keyCode 去指定具體的按鍵(不推薦)** 不同鍵盤的 keyCode 不同
5.Vue.config.keyCodes. 自定義鍵名 = 鍵碼,可以去定制按鍵別名
3. 系統修飾鍵(用法特殊)、alt、shift、meta
(1). 配合 keyup 使用:按下修飾鍵的同時,再按下其他鍵,隨後釋放其他鍵,事件才被觸發。
(2). 配合 keydown 使用:正常觸發事件。
修飾符可用。連接連續寫#
@keyup.ctrl.y
按下 ctrl+y 觸發事件
@click.prevent.stop
先阻止默認事件,再停止冒泡
計算屬性與監視#
計算屬性 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>
<script src="./js/vue2.js"></script>
</head>
<body>
<div id="App">
姓<input type="text" v-model="firstName"> <br> <br>
名<input type="text" v-model="lastName"> <br> <br>
姓名: <span>{{fullName}}</span>
</div>
</body>
<script>
new Vue({
el: '#App',
data: {
firstName: '張',
lastName: '三'
},
computed: {
fullName: {//最後存在data中
get() {
console.log('get被調用了')
return this.firstName + '-' + this.lastName
},
/* set(value) {
console.log('set被調用了',value)
const arr = value.split('-') // 陣列之間有一個-
this.firstName = arr[0]
this.lastName = arr[1]
} */
}
},
})
</script>
</html>
計算屬性簡寫
computed: {
fullname:function(){//只考慮讀取不考慮修改
console.log('get被調用了')
return this.firstName + '-' + this.lastName
}
}
監視屬性 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>
<script src="./js/vue2.js"></script>
</head>
<body>
<div id="app">
<!-- <h2>今天天氣很{{ishot ? '炎熱' : '涼爽'}}</h2> -->
<h2>今天天氣很{{info}}</h2>
<br>
<button @click="gaiTian">切換天氣</button> <br>
提示: <h3>{{tip}}</h3>
</div>
</body>
<script>
const vm = new Vue({
el: '#app',
data: {
ishot: true,
tip: '多喝涼水',
},
computed: {
info() {
return this.ishot ? '炎熱' : '涼爽'
}
},
watch: {
ishot: {
immediate: true,//布爾值 初始化時是否執行函數
handler() { //這裡只能使用handler函數
console.log('ishot被修改了')
}
}
},
methods: {
gaiTian() {
if (this.ishot)
this.ishot = false; else this.ishot = true
}
},
})
// 另一種監視方法
/* vm.$watch('ishot', {//,前寫監視的對象 ,後寫函數和配置 監視對象不存在時不會報錯
immediate: true,//布爾值 初始化時是否執行函數
handler() { //這裡只能使用handler函數
console.log('ishot被修改了')
}
}) */
</script>
</html>
深度監視#
Vue 自身可以檢測對象內部值的改變,但 Vue 提供的 watch 默認不可以
根據實際情況覺得是否開啟 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>
<script src="./js/vue2.js"></script>
</head>
<body>
<div id="app">
<!-- <h2>今天天氣很{{ishot ? '炎熱' : '涼爽'}}</h2> -->
<h2>今天天氣很{{info}}</h2>
<br>
<button @click="gaiTian">切換天氣</button> <br>
<button @click="numbers.a++">點我讓a+1</button>
<h3>a的值是{{numbers.a}}</h3> <br>
<br>
<button @click="numbers.b++">點我讓b+1</button> <br>
<h3>b的值是{{numbers.b}}</h3>
</div>
</body>
<script>
const vm = new Vue({
el: '#app',
data: {
ishot: true,
numbers: {
a: 1,
b: 2
}
},
computed: {
info() {
return this.ishot ? '炎熱' : '涼爽'
}
},
watch: {
ishot: {
handler() { //這裡只能使用handler函數
console.log('ishot被修改了')
}
},
/* //監視多層結構中某個屬性的變化
'numbers.a': {// 該寫法是原始寫法
handler() {
console.log('a改變了')
}
} */
//監視多級結構中所有屬性的變化 不開啟只有numbers中所有值發生改變函數才會生效
numbers: {
deep: true,
handler() {
console.log('numbers的值改變了')
}
}
},
methods: {
gaiTian() {
if (this.ishot)
this.ishot = false; else this.ishot = true
}
},
})
</script>
</html>
監視的簡寫#
watch: {
/*ishot: { //正常寫法
handler(newValue, oldValue) { //這裡只能使用handler函數
console.log('ishot被修改了', newValue, oldValue)
}
}, */
ishot(newValue, oldValue) {
console.log('ishot被修改了', newValue, oldValue)
},
},
樣式綁定#
綁定 class 樣式#
<div id="app">
<div class ="basic" :class="a">
<!--最後上面這個div的class是"basic normal"-->
</div>
<!--添加多個樣式"-->
<div class ="basic" :class="addr">
<!--最後上面這個div的class是"basic class1 class2 class3"-->
</div>
</div>
<script>
new Vue({
el:'#app',
data:{
a:'normal',
addr:['class1','class2','class3']
},
methods: {
change:{
}
},
})
</script>
Math.floor(Math.random()*3) //隨機數 範圍0-3
//floor 四捨五入向下取整
//Math.random()生成0-1的數 不包含1 *3代表生成0-3的數 不包括3 生成的是小數
綁定 style 樣式#
<body>
<div id="app">
<div class="" :style="{fontSize: fsize + 'px'}">{{name}}</div>
<!--:style 表示等號後內容為表達式 上方代碼可改變字體大小"-->
</div>
</body>
<script>
new Vue({
el: '#app',
data: {
a: 'normal',
name: 'miaolme',
fsize: 40
},
})
</script>
另一種寫法
<body>
<div id="app">
<div class="" :style="styleObj">{{name}}</div>
<!--:style 表示等號後內容為表達式 上方代碼可改變字體大小"-->
</div>
</body>
<script>
new Vue({
el: '#app',
data: {
a: 'normal',
name: 'miaolme',
styleObj:{
fontSize:'40px',
backgroundColor: 'orange',
color: 'red'
}
},
})
</script>
數組寫法
<body>
<div id="app">
<div class="" :style="[styleObj,styleObj2]">{{name}}</div>
<!--:style 表示等號後內容為表達式 上方代碼可改變字體大小"-->
</div>
</body>
<script>
new Vue({
el: '#app',
data: {
a: 'normal',
name: 'miaolme',
styleObj: {
fontSize: '40px',
backgroundColor: 'orange',
color: 'red'
},
styleObj2: {
color: 'red'
}
},
})
</script>
條件渲染#
v-show 和 v-if#
<body>
<div id="app">
<!-- v-show等號後寫表達式 结果是布爾值
v-if和v-show用法一樣 -->
<!-- <h2 v-show="false">歡迎學習vue{{name}}</h2> -->
<!-- <h2 v-show="1===1">歡迎學習vue{{name}}</h2> -->
<h2 v-if="false">歡迎學習vue{{name}}</h2>
</div>
</body>
<script>
new Vue({
el: '#app',
data: {
name: 'miaolme'
}
})
</script>
v-else-if 和 v-else#
用法和常規編程的 else if 用法相同
if 執行後
else if 的代碼不執行
所有條件不滿足,執行 else 裡的代碼
v-show 適用於切換頻率高的場景
v-if 適用於切換頻率低的場景
可以嵌套 div 使用
列表渲染#
v-for#
<body>
<div id="app">
<h2>人員列表</h2>
<ul>
<!-- 根據persons數組長度生成li -->
<!-- key代表節點標識 -->
<li v-for="ren in persons" :key="ren.id">
<!-- in可以用of代替 -->
{{ren.name}}-{{ren.age}}
</li>
</ul>
</div>
</body>
<script>
new Vue({
el: '#app',
data: {
persons: [
{ id: '001', name: '張三', age: 18 },
{ id: '002', name: '李四', age: 19 },
{ id: '003', name: '王五', age: 20 }
]
}
})
</script>
<body>
<div id="app">
<h2>人員列表</h2>
<ul>
<!-- 根據persons數組長度生成li -->
<!-- key代表節點標識 -->
<!-- index可以用其他詞替換 是索引 可以拿到這個數據 -->
<li v-for="(ren,index) in persons" :key="ren.id">
<!-- in可以用of代替 -->
{{ren.name}}-{{ren.age}}-{{index}}
</li>
</ul>
</div>
</body>
v-for 可以遍歷其他數據
<body>
<div id="app">
<h2>人員列表</h2>
<ul>
<!-- 根據persons數組長度生成li -->
<!-- key代表節點標識 -->
<!-- index可以用其他詞替換 是索引 可以拿到這個數據 -->
<li v-for="(value,key) in neko" :key="key.id">
{{key}}-{{value}}
<!-- 類似鍵值對 -->
</li>
</ul>
</div>
</body>
<script>
new Vue({
el: '#app',
data: {
neko: {
mao: '粉毛',
eye: '大眼',
tile: '大尾巴'
}
}
})
</script>
v-for 可以遍歷字符串
<body>
<div id="app">
<h2>人員列表</h2>
<ul>
<!-- 根據persons數組長度生成li -->
<!-- key代表節點標識 -->
<!-- index可以用其他詞替換 是索引 可以拿到這個數據 -->
<li v-for="(char,index) in str" :key="index.id">
{{index}}-{{char}}
<!-- 類似鍵值對 -->
</li>
</ul>
</div>
</body>
<script>
new Vue({
el: '#app',
data: {
str: 'Hello'
}
})
</script>
用的少
v-for 可以遍歷指定次數
<body>
<div id="app">
<h2>人員列表</h2>
<ul>
<!-- 根據persons數組長度生成li -->
<!-- key代表節點標識 -->
<!-- index可以用其他詞替換 是索引 可以拿到這個數據 -->
<li v-for="(number,index) in 5" :key="index.id">
{{number}}-{{index}}
<!-- 類似鍵值對 -->
</li>
</ul>
</div>
</body>
key 的值必須唯一
列表功能#
过滤#
1 雙向綁定
2 判斷 + 改色
.indexOf()
該方法判斷點前的數是否包含 () 內的字符
包含會給出在第幾位,第一位是0
,不包含返回-1
this.persons = this.persons.filter((p) => {
return p.name.indexOf(val) !== -1
})
// filter 過濾方法
數組.filter((變量) => {
return 布爾值
})
//返回一個新數組
完整 watch 方法
<body>
<div id="app">
<div>
<input type="text" placeholder="請輸入名字" v-model="keyWord">
<button>這是按鈕</button>
<ul>
<li v-for="(p, index) in fillPersons" :key="p.id">
{{p.name}}-{{p.age}}-{{p.sex}}
</li>
</ul>
</div>
</div>
</body>
<script>
new Vue({
el: '#app',
data: {
persons: [
{ id: '001', name: '馬冬梅', age: 19, sex: '女' },
{ id: '002', name: '周冬雨', age: 20, sex: '女' },
{ id: '003', name: '周杰倫', age: 21, sex: '男' },
{ id: '004', name: '溫兆倫', age: 22, sex: '男' }
],
keyWord: '',
fillPersons: []
},
watch: {
keyWord: {
immediate: true,
handler(val) {
this.fillPersons = this.persons.filter((p) => {
return p.name.indexOf(val) !== -1
})
}
}
}
})
</script>
</html>
用 computed 實現
<body>
<div id="app">
<div>
<input type="text" placeholder="請輸入名字" v-model="keyWord">
<button>這是按鈕</button>
<ul>
<li v-for="(p, index) in fillPersons" :key="p.id">
{{p.name}}-{{p.age}}-{{p.sex}}
</li>
</ul>
</div>
</div>
</body>
<script>
new Vue({
el: '#app',
data: {
persons: [
{ id: '001', name: '馬冬梅', age: 19, sex: '女' },
{ id: '002', name: '周冬雨', age: 20, sex: '女' },
{ id: '003', name: '周杰倫', age: 21, sex: '男' },
{ id: '004', name: '溫兆倫', age: 22, sex: '男' }
],
keyWord: '',
},
computed: {
fillPersons() {
return this.fillPersons = this.persons.filter((p) => {
return p.name.indexOf(this.keyWord) !== -1
})
}
},
})
</script>
</html>
排序#
vue 的數據檢測原理#
懶得學
看這裡:
033_尚硅谷 Vue 技術_更新時的一個問題_哔哩哔哩_bilibili
看到 037
收集表單數據#
v-model 默認雙向綁定 value 值
<!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/vue2.js"></script>
</head>
<body>
<div id="app">
<form @submit.prevent="demo">
<!-- 點擊按鈕觸發表單提交 prevent阻止默認行為 -->
<!-- <label for="demo"> -->
<!-- label 和id可以連接兩個對象 -->
<!-- 賬號:<input type="text" id="demo"> -->
<!-- </label> -->
賬號: <input type="text" v-model="account"> <br>
密碼: <input type="password" v-model="password"> <br>
性別: <br>
男<input type="radio" name="sex" value="male" v-model="sex">
<!-- 通過name可以為radio單選框分組 -->
女<input type="radio" name="sex" value="femal" v-model="sex">
<br>
愛好: <br>
<!-- vue默認讀取多選框 checked的布爾值 -->
學習<input type="checkbox" v-model="hobby" value="study">
打遊戲<input type="checkbox" v-model="hobby" value="game">
吃飯<input type="checkbox" v-model="hobby" value="eat"> <br>
所屬校區 <br>
<select v-model="city">
<option value="">請選擇校區</option>
<option value="beijing">北京</option>
<option value="shenzhen">深圳</option>
<option value="shanghai">上海</option>
<option value="wuhan">武漢</option>
<br>
</select> <br>
其他信息: <br>
<textarea v-model="other"></textarea> <br>
<input type="checkbox" v-model="agree"> 閱讀並接收<a href="http://baidu.com">《用戶協議》</a> <br>
<button>提交信息</button>
</form>
</div>
</body>
<script>
new Vue({
el: "#app",
data: {
account: '',
password: '',
sex: 'femal',// 雙向綁定 會默認選中性別
hobby: [],//hobby所獲得的多選框的值是個字符串
city: '',
other: '',
agree: 'false',
},
methods: {
demo() {
alert(1)
}
},
})
</script>
</html>
vue 基礎#
过滤器#
效果:顯示格式化後的時間
現在是:2021-01-09
現在是:2021-01-09 22:53:47
意義不大,vue3 移除
<script src="./js/vue2.js"></script>
<script src="./js/dayjs.min.js"></script>
</head>
<body>
<!-- 準備好一個容器 -->
<div id="root">
<h2>顯示格式化後的時間</h2>
<h3>現在是{{fmtTime}}</h3>
</div>
</body>
<script>
new Vue({
el: '#root',
data: {
time: 1621561377603 //時間戳
},
computed: {
fmtTime() {
return dayjs(this.time).format('YYYY-MM-DD HH:mm:ss')
}
}
})
</script>
</html>
時間格式化可以借助第三方庫實現
內置指令#
學過的指令#
v-bind : 單向綁定解析表達式,可簡寫為:xxx
v-model : 雙向數據綁定
v-for : 遍歷數組 / 對象 / 字符串
v-on : 綁定事件監聽,可簡寫為 @
v-if : 條件渲染(動態控制節點是否存在)
v-else : 條件渲染(動態控制節點是否存在)
v-show : 條件渲染(動態控制節點是否展示)
v-text 指令#
<body>
<div id="app">
<div>{{name}}</div> <br>
<div v-text="name"></div> <!-- v-text會替換到整個div內容 -->
<!-- v-text插入文本 會替換節點內容 插值語法不會 -->
</div>
</body>
<script>
new Vue({
el: '#app',
data: {
name: '小貓'
}
})
</script>
v-html 指令#
用法:和 v-text 用法相同,但是可以解析帶標籤的字符串 如<h2>呵呵</h2>
<div v-html="name"></div>
安全性問題 用於輸入可無視屏蔽插入危險 html 語句
v-cloak 指令#
用在標籤中,在 vue 掛載後,標籤會消失
可單獨設置樣式 本質是一個 id 可以設置攜帶改 id 的內容不顯示 diskplay
,可以防止因網速過慢導致 vue 未加載產生{{}}
內容
v-once 指令#
1.v-once 所在節點在初次動態渲染後,就視為靜態內容了。
2. 以後數據的改變不會引起 v-once 所在結構的更新,可以用於優化性能。
標籤加入改內容 {{}}
內代表的內容只會顯示初始值
v-pre 指令#
1.v-prt. 除過其所在節點的編譯過程。
2. 可利用它跳過:沒有使用指令語法、沒有使用插值語法的節點,會加快編譯
自定義指令#
目前用不到
生命週期#
原理圖
下方所有字段都和 vue 中的data:{}
平級
new Vue({
el: '#app',
data: {
name: '小貓'
}
})
mounted#
mounted(){
// 此函數內的代碼只會在vue掛載完後執行
// 可以在內部添加定時器函數等用於初始化的代碼
}
template#
用法 1:不換行
template:'<h2>當前的n值是:{{n}}/h2><button@click="add">點我n+1</button>'
用法 2:換行
template:`<h2>當前的n值是:{{n}}/h2>
<button@click="add">點我n+1</button>`
作用,替換容器內容即 <div id="app">
內的所有內容
<div id="app">
<div>{{name}}</div> <br>
<div v-text="name"></div> <!-- v-text會替換到整個div內容 -->
<!-- v-text插入文本 會替換節點內容 插值語法不會 -->
</div>
vue 中使用 template 會覆蓋原有容器所有內容。
模板可為空,但是必須包含template
(根節點)
beforeUpdate#
更新流程前的函數
beforeUpdate(){
// 寫在內部的函數會在vue的值即將發生更新前執行
}
update#
update(){
// 寫在內部的函數會在vue的值發生更新後執行
}
beforeDestory#
beforeDestory(){
// 寫在內部的函數會在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>
<script src="./js/vue2.js"></script>
</head>
<body>
<!-- 定義容器 -->
<div id="app">
<h1>{{msg}}</h1>
<hr>
<school />
</div>
</body>
<script>
//定義組件
const school = Vue.extend({
template: `
<div>
<h2>我的學校:{{name}}</h2>
<h2>地址:{{address}}</h2>
</div>`,
data() {
return {
name: '喵校',
address: '喵娘樂園'
}
}
})
new Vue({
el: '#app',
data: {
msg: '你好Vue!'
},
//註冊組件 (局部)
components: {
school: school //調用<school/>標籤來使用 標籤的內容由:左側決定
}
})
</script>
</html>
全局註冊組件
//全局註冊組件
Vue.component('使用標籤名',定義的組件名)
全局註冊例子
Vue.component('xuexiao',school)
//使用<xuexiao/>即可調用改組件
const school = Vue.extend({
template: `
<div>
<h2>我的學校:{{name}}</h2>
<h2>地址:{{address}}</h2>
</div>`,
data() {
return {
name: '喵校',
address: '喵娘樂園'
}
}
})
局部註冊和全局註冊的區別:
局部註冊的組件只能在其所規定的容器可用,全局註冊的組件可用在任意的容器中調用組件。
組件可套娃
但是執行順序必須自上而下,否則報錯
構造函數#
057_尚硅谷 Vue 技術_VueComponent 構造函數_哔哩哔哩_bilibili
先跳過,以後學
腳手架#
安裝腳手架#
- 安裝 node.js
- 配置 淘寶源
npm config set registry=http://registry.npm.taobao.org
- 全局安裝腳手架
npm install -g @vue/cli
創建腳手架文件
vue create 文件名 #(自己自定義)最好不要出現中文,可能會出錯
單文件組件#
文件後綴.vue
起名規範
school.vue my-school.vue
School.vue MySchool.vue
結構
<template>
<!--組件的結構 -->
</template>
<script>
//組件交互相關代碼(數據、方法等)
</script>
<style>
/*組件的樣式*/
</style>
例子
<template>
<div class="demo">
<h2>我的學校:{{name}}</h2>
<h2>地址:{{address}}</h2>
</div>
</template>
<script>
const school = Vue.extend({
data() {
return {
name: '喵校',
address: '喵娘樂園'
}
}
})
</script>
<style>
.demo{
background-color: pink;
}
</style>
暴露方法
類似 public 公开訪問方法 共 3 種
<script>
export const school = Vue.extend({ //分別暴露
data() {
return {
name: '喵校',
address: '喵娘樂園'
}
}
})
</script>
<script>
const school = Vue.extend({
data() {
return {
name: '喵校',
address: '喵娘樂園'
}
}
})
export default school //默認暴露 常用
</script>
<script>
/*或者*/
export default {
name:'school',
data() {
return {
name: '喵校',
address: '喵娘樂園'
}
}
}
</script>
<script>
const school = Vue.extend({
data() {
return {
name: '喵校',
address: '喵娘樂園'
}
}
})
export {school} //統一暴露
</script>
App.vue 匯總組件
<template lang="">
<div>
<school></school>
</div>
</template>
<script>
//引入組件
import school from 'vue1/school'
export default {
name: 'App',
components: {
school: school
}
}
</script>
<style lang="">
</style>
vm main.js
import App from 'vue1/App'
new Vue({
template:'<App></App>',
el:'#root',
components:{App}
})
入口文件 index.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="root">
</div>
<script src="../js/vue2.js"></script>
<script src="./main.js"></script>
</body>
</html>
常用屬性#
render 函數#
main.js
import Vue from 'vue'
import App from './App.vue'
Vue.config.productionTip = false
new Vue({
render: h => h(App), // h可替換成其他內容 下方是例子
//render: test => test(App), 同樣的,App代表組件 也可以替換為模板結構
//render: test => test('h1','hello') 類似於template效果 不常用
}).$mount('#app') // 這個相當於 el:'#app'
ref 元素#
作用: 類似於 id 選擇器 用於獲取組件的 vm 對象或者是某個元素的對象
例子:
<h1 ref="sch">你好vue!</h1>
console.log(this.$refs.sch)
ref 屬性
被用來給元素或子組件註冊引用信息(id 的替代者)
被應用在 html 標籤上獲取的是真實 dom 元素,應用在組件上是組件實例對象 (vc)
props 配置#
用法:
props:['name','address','age']
用在 script 中與 data 平級
不能與 data 中值相同。用於外部數據傳入.
可以通過內部寫函數來控制傳入的數值.
num+(){
this.age++ //需要用到this
}
mixin 混入#
例子
mixin.js
// 分別暴露
export const mixin = {
methods: {
showName() {
alert(this.name)
}
},
}
MyStudent.vue
<template>
<div>
<h3 @click="showName">姓名:{{ name }}</h3>
<h3>地址:{{ address }}</h3>
<h3>年齡:{{ age }}</h3>
</div>
</template>
<script>
//引入 混合 mixin
import { mixin } from '../mixin'
export default {
name: 'MyStudent',
data() {
return {
name: '喵喵',
address: '櫻花校園',
age: '18'
}
},
//啟用混合 會自動根據結構判斷 進行調用自定義的mixin中的方法
mixins: [mixin],
methods: {
}
}
</script>
組件內的方法代碼執行優先
mounted 函數都會執行。 mixin 中的代碼優先執行
全局混合
只需要修改main.js
import Vue from 'vue'
import App from './App.vue'
Vue.config.productionTip = false
//引入混合
import { mixin } from './mixin'
//應用混合
Vue.mixin(mixin)
new Vue({
render: h => h(App),
}).$mount('#app')
作用域限制和插件#
作用域限制
scoped#
用於 style 中
<style scoped>
.title{
color: red;
}
</style>
作用:限制 style 內的樣式僅在當前組件生效。
vue 內的樣式會覆蓋組件的同名樣式
插件#
使用方法: script.js
定義插件
export default { //默認暴露
install(Vue,x,y){ //可接收傳入值x,y
//全局過濾器
Vue.filter('mySlice',function(value){...})
//定義全局指令
Vue.directive('fbind',{...})
//定義全局混合
Vue.mixin({...})
}
//給vue原型添加方法
Vue.prototype.hello = ()=>{alert('你好vue')}
}
應用插件在App.vue
<script>
//引入插件
import plugins from './plugins'
//使用插件
Vue.use(plugins)
</script>
組件信息交互#
全局事件總線#
沒學 084_尚硅谷 Vue 技術_全局事件總線 1_哔哩哔哩_bilibili
消息訂閱與發布#
1 訂閱消息 2 發布消息
安裝第三方庫
npm install [email protected]
引入 school.vue
<script>
import pubsub from 'pubsub-js'
//定義
mounted(){ //不寫箭頭函數需要把執行函數定義在methods中
this.pubId = pubsub.subscribe('hello',(msgName,data)=>{ //訂閱消息
console.log(this) //hello是消息名
})
}
//取消訂閱
beforeDestory(){
pubsub.unsubscribe(this.pubId)
}
</script>
另一種方式
<script>
import pubsub from 'pubsub-js'
methods(){
demo(data){...}
}
mounted(){ //不寫箭頭函數需要把執行函數定義在methods中
this.pubId = pubsub.subscribe('hello',this.demo) //訂閱消息
//檢測到 hello為事件名發布消息時會執行回調函數
}
//取消訂閱
beforeDestory(){
pubsub.unsubscribe(this.pubId)
}
</script>
發布消息
<script>
import pubsub from 'pubsub-js'
methods(){
sendStudentName(){
pubsub.publish('hello',666) //調用方法後會創建一個名為hello的消息,數據是666
}
}
</script>
methods: $nextTick
this.$nextTick(function(){
//會在dom節點更新完畢後執行 vue模板編譯完成後執行
this.$refs.inputTitle.focus()//自動獲取焦點
})
setTimeout(){
this.$refs.inputTitle.focus()//自動獲取焦點
//定時器函數會在vue模板編譯完成後執行
}
過度與動畫#
vue 動畫#
<template>
<div>
<!--isShow = !isShow代表按鈕切換isShow的true和false-->
<Button @click="isShow = !isShow">顯示/隱藏</Button>
<transition name="v" appear>
<!-- :appear="true" 等同於appear 加上後會在刷新後播放動畫 -->
<!-- 過渡標籤 設置好後自動播放來去的動畫 -->
<h1 v-show="isShow">你好啊!</h1>
</transition>
</div>
</template>
<script>
export default {
name: 'MyTest',
data() {
return {
isShow: true
}
}
}
</script>
<style scoped>
h1 {
background-color: pink;
}
/*come和夠為需要的元素添加class就可以播放設置的動畫*/
.come {
/*來時動畫*/
animation: dongHua 1s;
}
.go {
/*走時動畫*/
animation: dongHua 1s reverse;
/*reverse反轉*/
}
/*過度動畫標籤類型 v是動畫的name*/
.v-enter-active {
/*來時動畫*/
animation: dongHua 1s;
}
.v-leave-active {
/*走時動畫*/
animation: dongHua 1s reverse;
/*reverse反轉*/
}
@keyframes dongHua {
/*定義動畫關鍵幀 和動畫名*/
from {
transform: translateX(-100%);
/*單位是px*/
}
to {
transform: translateX(0px);
}
}
</style>
vue 過度#
例子
<div>
<!--isShow = !isShow代表按鈕切換isShow的true和false-->
<Button @click="isShow = !isShow">顯示/隱藏</Button>
<transition-group name="v">
<!-- :appear="true" 等同於appear 加上後會在刷新後播放動畫 -->
<!-- 過渡標籤 設置好後自動播放來去的動畫 -->
<h1 v-show="isShow" key="1">你好啊!</h1>
<h1 v-show="isShow" key="2">Vue</h1>
</transition-group>
</div>
group 中的所有元素必須有唯一的 key 值
name 用於區分不同類型動畫
集成第三方動畫#
animate.css - 第三方動畫 (npmjs.com)
安裝:
需要 cmd 進入在所需項目內執行
npm install animate.css --save
引入
<script>
import 'animate.css';
</script>
例子
<template>
<div>
<!--isShow = !isShow代表按鈕切換isShow的true和false-->
<Button @click="isShow = !isShow">顯示/隱藏</Button>
<transition-group
name="animate__animated animate__bounce"
appear
enter-active-class="animate__rubberBand"
leave-active-class="animate__bounceOut">
<!-- :appear="true" 等同於appear 加上後會在刷新後播放動畫 -->
<!-- 過渡標籤 設置好後自動播放來去的動畫 -->
<h1 v-show="isShow" key="1">你好啊!</h1>
<h1 v-show="isShow" key="2">Vue</h1>
</transition-group>
</div>
</template>
<script>
//引入動畫css
import 'animate.css'
export default {
name: 'MyTest2',
data() {
return {
isShow: true
}
}
}
</script>
<style scoped>
h1 {
background-color: pink;
}
</style>
enter-active-class=“”
和leave-active-class=“”
“” 內需要填入動畫庫所需動畫的名稱。 name=“”
必須填入 animate__animated animate__bounce
不同動畫庫的要求略有差別
group 中的所有元素必須有唯一的 key 值
插槽#
默認插槽#
使用方法:
- 組件寫雙標籤
- 標籤內填組件裡額外需添加的元素
- 在組件中用 slot 雙標籤標記所放置位置
slot 標籤內寫的內容會在組件雙標籤內的內容為空時展示
viedo 想播放必須添加 controls 標籤才能播放
具名插槽#
使用:
- 組件雙標籤內寫
solt="定義的name名稱"
solt
標籤中添加name=“自定義名稱”
屬性
不同元素使用相同的solt
名字不會發生覆蓋,會自動追加
另一種寫法
使用<template>
雙標籤包裹,類似於div
但是不會產生dom
結構
使用該標籤包裹後可以用 v-solt:自定義名稱
來定義dom
生成位置
作用域插槽#
104_尚硅谷 Vue 技術_作用域插槽_哔哩哔哩_bilibili
因為感覺沒啥用,先不學了
Vuex#
理解 vuex#
原理圖
vuex 是什麼#
1. 概念:專門在 Vue 中實現集中式狀態(數據)管理的一個 Vue 插件,對 vue 應用中
多個組件的共享狀態進行集中式的管理(讀 / 寫), 也是一種組件間通信的方式,且適
用於任意組件間通信。
2.Github 地址:https://github.com/vuejs/vuexe
什麼時候使用 Vuex#
1. 多個組件依賴於同一狀態
2. 來自不同組件的行為需要變更同一狀態
安裝 vuex#
npm i vuex@3
動態路由#
路由基本使用#
- 需安裝 vue-router3
npm i vue-router@3
插件庫
使用方法
main.js
import Vue from 'vue'
import App from './App.vue'
import VueRouter from 'vue-router'
//關閉Vuee生產提示
Vue.config.productionTip = false
//應用插件
Vue.use(VueRouter)
new Vue({
render: h => h(App),
}).$mount('#app')
創建路由#
router/index.js
// 改文件用於創建整個應用的路由器
import VueRouter from "vue-router";
//引入組件
import MyHome from "../comments/home"
import MyAbout from "../comments/about"
// 創建一個路由器並暴露在外部
export default new VueRouter({
routes: [
{
path: '/about',
component: MyAbout
},
{
path: '/home',
component: MyHome
}
]
})
引入路由器#
main.js
import Vue from 'vue'
import App from './App.vue'
import VueRouter from 'vue-router'
//引入路由器
import router from './router'
//關閉Vuee生產提示
Vue.config.productionTip = false
//應用插件
Vue.use(VueRouter)
new Vue({
render: h => h(App),
router: router //引入路由
}).$mount('#app')
調整App.vue
<template>
<div>
<div class="row">
<div class="col-xs-offset-2 col-xs-8">
<div class="page-header">
<h2>Vue Router Demo</h2>
</div>
</div>
</div>
<div class="row">
<div class="col-xs-2 col-xs-offset-2">
<div class="list-group">
<!-- 原始html中我們使用a標籤實現頁面的跳轉 -->
<!-- <a class="list-group-item active" href="./about.html">About</a>
<a class="list-group-item" href="./home.html">Home</a> -->
<!-- 路由跳轉 router-link 和 to 標籤 最終轉成a標籤 active-class 元素激活時的樣式-->
<router-link class="list-group-item" active-class="active" to="/about">About</router-link>
<router-link class="list-group-item" active-class="active" to="/home">Home</router-link>
</div>
</div>
<div class="col-xs-6">
<div class="panel">
<div class="panel-body">
<!-- 此處到底展示什麼組件,得看用戶點擊的是哪個導航項 -->
<!-- 指定組件的呈現位置 -->
<router-view></router-view>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
name: 'App',
data() {
return {
}
},
components: {
}
}
</script>
<style>
</style>
建議把路由組件放在單獨的文件夾中
嵌套(多級)路由#
router/index.js
// 改文件用於創建整個應用的路由器
import VueRouter from "vue-router";
//引入組件
import MyHome from "../comments/home"
import MyAbout from "../comments/about"
import MyNews from "../comments/news"
import MyMessage from "../comments/message"
// 創建一個路由器並暴露在外部
export default new VueRouter({
routes: [
{
path: '/about',
component: MyAbout
},
{
path: '/home',
component: MyHome,
//二級路由
children: [
{
path: 'news',
component: MyNews
},
{
path: 'message',
component: MyMessage
}
]
}
]
})
home.vue
<template>
<div>
<h2>Home組件內容</h2>
<div>
<ul class="nav nav-tabs">
<li>
<router-link class="list-group-item" active-class="active" to="/home/news">News</router-link>
</li>
<li>
<router-link class="list-group-item" active-class="active" to="/home/message">Message</router-link>
</li>
</ul>
<router-view></router-view>
</div>
</div>
</template>
<script>
export default {
name: 'MyHome'
}
</script>
<style>
</style>
路由傳參#
query 參數#
可以通過to
後寫?…
傳遞參數
跳轉路由並攜帶 query 參數,to 的字符串寫法
<router-link class="list-group-item" active-class="active" to="/home/message?id=666&title=你好啊!">Message</router-link>
取參數
{{$route.query.id}} //666
{{$route.query.title}} //你好啊!
使用v-if
可以插入指定內容
<li v-for="m in messageList" :key="m.id">
<router-link class="list-group-item" active-class="active" :to="`/home/message?id=${m.id}&title=${m.title}`">Message</router-link>
</li>
跳轉路由並攜帶 query 參數,to 的對象寫法
<li v-for="m in messageList" :key="m.id">
<router-link :to="{
path:'/home/message/detail',
query:{
id:m.id,
title:m.title
}
}"
</li>
命名路由#
添加方法 router/index.js
// 改文件用於創建整個應用的路由器
import VueRouter from "vue-router";
//引入組件
import MyHome from "../comments/home"
import MyAbout from "../comments/about"
import MyNews from "../comments/news"
import MyMessage from "../comments/message"
// 創建一個路由器並暴露在外部
export default new VueRouter({
routes: [
{
name:'guanyu', //給誰起名就在哪裡填寫name:
path: '/about',
component: MyAbout
},
{
path: '/home',
component: MyHome,
//二級路由
children: [
{
path: 'news',
component: MyNews
},
{
name:'xiangqing', //給誰起名就在哪裡填寫name:
path: 'message',
component: MyMessage
}
]
}
]
})
可以簡化操作
僅支持下列兩種
<li v-for="m in messageList" :key="m.id">
<router-link :to="{
name:'xiangqing',
query:{
id:m.id,
title:m.title
}
}"
</li>
<router-link class="list-group-item" active-class="active" :to="{name:'guanyu'}">關於</router-link>
params 參數#
配置路由
// 改文件用於創建整個應用的路由器
import VueRouter from "vue-router";
//引入組件
import MyHome from "../comments/home"
import MyAbout from "../comments/about"
import MyNews from "../comments/news"
import MyMessage from "../comments/message"
import MyDetail from "../comments/detail"
// 創建一個路由器並暴露在外部
export default new VueRouter({
routes: [
{
name:'guanyu', //給誰起名就在哪裡填寫name:
path: '/about',
component: MyAbout
},
{
path: '/home',
component: MyHome,
//二級路由
children: [
{
path: 'news',
component: MyNews
},
{
path: 'message',
component: MyMessage,
children:{
{
name:'xiangqing',
path:'detail/:id/:title'
component: MyDetail,
}
}
}
]
}
]
})
攜帶方式 1
<li v-for="m in messageList" :key="m.id">
<router-link class="list-group-item" active-class="active" :to="`/home/message/detail/${m.id}/${m.title}`">Message</router-link>
</li>
攜帶方式 2
不可使用path
<li v-for="m in messageList" :key="m.id">
<router-link :to="{
name:'xiangqing',
params:{
id:m.id,
title:m.title
}
}"
</li>
路由的 props 配置#
配套的Detail
組件
<template>
<ul>
<li>消息編號:{{ id }}</li>
<li>消息標題:{{ title }}</li>
</ul>
</template>
<script>
export default {
name: 'Detail',
props: ['id', 'title']
}
</script>
<style>
</style>
第二種寫法
// 改文件用於創建整個應用的路由器
import VueRouter from "vue-router";
//引入組件
import MyHome from "../comments/home"
import MyAbout from "../comments/about"
import MyNews from "../comments/news"
import MyMessage from "../comments/message"
// 創建一個路由器並暴露在外部
export default new VueRouter({
routes: [
{
path: '/about',
component: MyAbout
},
{
path: '/home',
component: MyHome,
//二級路由
children: [
{
path: 'news',
component: MyNews
},
{
path: 'message',
component: MyMessage,
//props的第二種寫法,值為布爾值,若布爾值為真,就會把該路由組件收到的所有params參數
//,以props的形式傳給Detail組件
props:true
}
]
}
]
})
另一種寫法
// 改文件用於創建整個應用的路由器
import VueRouter from "vue-router";
//引入組件
import MyHome from "../comments/home"
import MyAbout from "../comments/about"
import MyNews from "../comments/news"
import MyMessage from "../comments/message"
// 創建一個路由器並暴露在外部
export default new VueRouter({
routes: [
{
path: '/about',
component: MyAbout
},
{
path: '/home',
component: MyHome,
//二級路由
children: [
{
path: 'news',
component: MyNews
},
{
path: 'message',
component: MyMessage,
//props的第三種寫法,值為函數
//1.
/*props({ query: { id, title } }) {
return { id, title }
} */
//2.
/* props({ query }) {
return { id: query.id, title: query.title }
} */
//3.
props($route) {
return {
id: $route.query.id,
title: $route.query.title
}
}
}
]
}
]
})
編程式路由導航#
push 查看#
按鈕傳遞參數
<button> @click="pushShow(m)"push查看</button>
按鈕綁定點擊事件對應的函數
pushShow(m){ //m 是接收的參數
this.$router.push({
name:'xiangqing',
query:{
id:m.id,
title:m.title
}
})
}
replace 查看#
按鈕傳遞參數
<button> @click="replaceShow(m)"push查看</button>
按鈕綁定點擊事件對應的函數
replaceShow(m){ //m 是接收的參數
this.$router.replace({
name:'xiangqing',
query:{
id:m.id,
title:m.title
}
})
}
區別:
- push 查看瀏覽器可以回退,有歷史記錄
- replace 查看瀏覽器的記錄會被覆蓋,無法正常回退
前進和後退#
按鈕綁定下列對應函數就能實現前進和後退
back(){ //後退
this.$router.back()
}
forward(){ //前進
this.$router.forward()
}
test(){
this.$router.go() // ()內為正數前進對應步數,填寫負數則後退對應的步數.
}
緩存路由#
作用:可以防止在切換路由組件時導致填