根據B站黑馬程式員 VUE教程基礎學習
為了畢業設計做準備
Vue基礎
- 工具準備
-
- Vue的基本使用步驟
- vue模闆文法
-
- `v-cloak`指令用法
- 資料綁定指令
- 資料響應式
- 雙向資料綁定
- MVVM設計思想
- 事件綁定
- 事件修飾符
- 按鍵修飾符
- 案例:簡單電腦
-
- 屬性綁定
- 樣式綁定 class
- style樣式處理
- 分支循環結構
- Tab頁籤
- 常用特性
-
- 表單操作
- 自定義指令
- 計算屬性
- 過濾器
-
- 使用過濾器格式化日期
- 偵聽器
-
- 偵聽器案例:驗證使用者名是否可用
- 生命周期
- 圖書管理
- 元件化開發
-
- 元件注冊
- 元件命名方式
工具準備
Sublime text 3*連結:Sublime text 3
提取碼:5kk5
package controlpackage control
Vue的基本使用步驟
- 需要提供标簽用于填充資料
容器<div>
<div id="app">
<div>{{msg}}</div>
</div>
{{}}
插值表達式
;
2. 引入vue.js庫檔案
在官網上下載下傳開發版的vue.js檔案,官網位址:vue;
4. 可以使用vue的文法做功能了
提供一個變量存儲vue對象
var vm = new Vue({
el:'#app ',//告訴vue資料填充的位置,#代表id選擇器
data:{
msg:'Hello Vue'
}
});
;
5. 把vue提供的資料填充到标簽 ;
*[前端渲染]:
vue模闆文法
指令 (Directives) 是帶有 v- 字首的特殊 attribute。指令 attribute 的值預期是單個 JavaScript 表達式。指令的職責是,當表達式的值改變時,将其産生的連帶影響,響應式地作用于 DOM。
v-cloak
指令用法
v-cloak
插值表達式會出現“閃動”現象 (重新整理時會出現标簽之間的内容)
- 提供樣式
[v-cloak] {
display: none;
}
-
在插值表達式所在的标簽中添加v-cloak指令
背後原理:
先通過樣式隐藏内容,然後在記憶體中進行值的替換,替換好之後再顯示最終值
資料綁定指令
-
v-text
填充純文字
相比插值表達式更簡潔
-
v-html
填充Html片段
存在安全問題
本網站内部資料可以使用,來自第三方的資料不可使用
-
v-pre
填充原始資訊
顯示原始資訊,跳過編譯過程(分析編譯過程)
<div v-text='msg'></div>
<div v-html='msg1'></div>
<div v-pre>{{msg}}</div>
資料響應式
-
html5中的響應式
螢幕尺寸變化導緻樣式的變化 自适應
-
資料的響應式
資料的變化導緻頁面樣式的變化
-
資料綁定
将資料填充到标簽中
-
v-once
隻編譯一次
顯示内容之後不再具有響應式功能
如果顯示的資訊後續不需要再修改,可以使用,提高性能
雙向資料綁定
v-model
控制台和input表單資料改變時頁面内容也改變
MVVM設計思想
- M(model)
- V(view)
- VM(view-model)
事件綁定
事件處理:
v-on
指令
- 用法:
v-on:click
- 簡寫:
事件函數調用方式@click
- 直接綁定函數名稱調用:
如果事件直接綁定函數名稱,那麼預設會傳遞事件對象作為事件的第一個參數v-on:click='函數名'
- 調用函數:
如果事件綁定函數調用,那麼事件對象必須作為最後一個參數顯示傳遞,并且事件對象必須是v-on:click='say()'
事件函數參數傳遞$event
- 普通參數傳參對象
接收事件對象,function括号中不加美元符$event
事件标簽名稱event.target.tagName
事件内容event.target.innerHTML
事件修飾符
-
stop
阻止冒泡
冒泡:裡層出發的事件會傳遞到外層,并觸發外層事件
-
阻止預設行為,如跳轉prevent
- 阻止冒泡函數
event.stopPropagation()‘
- 阻止預設行為
event.preventDefault()‘
按鍵修飾符
按鍵後觸發事件函數
-
enter
Enter鍵
v-on:keyup.enter
-
delete
删除鍵
v-on:keyup.delete
-
自定義按鍵修飾符
全局
對象config.keyCodes
案例:簡單電腦
- 通過v-model指令實作數值a和數值b的綁定
- 給計算按鈕綁定事件,實作計算邏輯
- 将計算結果綁定到對應位置
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div id="app">
<h1>簡單電腦</h1>
<div>
<span>數值A:</span>
<span>
<input type="text" v-model='a'>
</span>
</div>
<div>
<span>數值B:</span>
<span>
<input type="text" v-model='b'>
</span>
</div>
<div>
<button v-on:click="handle">計算</button>
</div>
<div>
<span>計算結果:</span>
<span v-text="result"></span>
</div>
</div>
<script type="text/javascript" src="js/vue.js"></script>
<script type="text/javascript">
var vm = new Vue({
el:'#app',
data:{
a:'',
b:'',
result:''
},
methods:{
handle:function(){
//實作計算邏輯
this.result = parseInt(this.a) + parseInt(this.b);
//this.a 和 this.b中得到的是字元串,預設字元串拼接,是以要強制轉換
}
}
});
</script>
</body>
</html>
屬性綁定
-
雙向資料綁定v-bind
的低層實作原理分析 三種實作效果相同v-model
樣式綁定 class
- 對象綁定和數組綁定可以結合使用
- Class綁定的值可以簡化操作 放在data中的數組或者對象集合
style樣式處理
分支循環結構
-
v-if
-
v-else
-
v-else-if
-
v-show
v-if 和 v-show 的差別
- v-if 控制元素是否渲染到頁面
- v-show 控制元素是否顯示(已經渲染到了頁面)
循環結構
v-for
Tab頁籤
最重要的是用
currentIndex
進行判斷
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style type="text/css">
.tab ul{
overflow: hidden;
padding: 0;
margin: 0;
}
.tab ul li{
box-sizing: border-box;;
padding: 0;
float: left;
width: 100px;
height: 45px;
line-height: 45px;
list-style: none;
text-align: center;
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: 500px;
height: 300px;
display: none;
text-align: center;
font-size: 30px;
line-height: 300px;
border: 1px solid blue;
}
.tab div.current{
display:block;
}
</style>
</head>
<body>
<div id="app">
<div class="tab">
<ul>
<li v-on:click='change(index)' :class='currentIndex==index?"active":""' :key='item.id' v-for='(item,index) in list'>{{item.title}}</li>
</ul>
<div :class='currentIndex==index?"current":""' :key='item.id' v-for='(item,index) in list'>
<img :src="item.path">
</div>
</div>
</div>
<script type="text/javascript" src="js/vue.js"></script>
<script type="text/javascript">
var vm = new Vue({
el:'#app',
data:{
currentIndex: 0,//頁籤目前的索引
list:[{
id: 1,
title:'apple',
path:'img/apple.jpg'
},{
id: 2,
title:'orange',
path:'img/orange.jpg'
},{
id: 3,
title:'lemon',
path:'img/lemon.jpg'
}]
},
methods:{
change:function(index){
//在這裡實作頁籤切換操作
//通過currentIndex操作類名
this.currentIndex = index;
}
}
});
</script>
</body>
</html>
常用特性
表單操作
- Input 單行文本
- textarea 多行文本
- select 下拉多選
- radio 單選框
- checkbox 多選框
表單域修飾符
- number 轉化為數值 不再需要強制轉換
- trim 去掉開始和結尾的空格
- lazy 将input事件轉換為change事件 Input每次輸入觸發,change每次失去焦點觸發(常用于注冊使用者名驗證重複)
自定義指令
第一個參數:指令名稱
第二個參數,實作邏輯 el表示指令所綁定的元素
使用時候 v-focus
計算屬性
插值表達式裡直接寫函數名,不需要加()
基于data中的值進行處理
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div id="app">
<div>{{msg}}</div>
<div>{{reverseString}}</div>
</div>
<script type="text/javascript" src="js/vue.js"></script>
<script type="text/javascript">
var vm = new Vue({
el:'#app',
data:{
msg:'Hello'
},
computed:{
reverseString:function(){
return this.msg.split('').reverse().join('');
}
}
})
</script>
</body>
</html>
計算屬性與方法的差別
- 計算屬性基于它們的依賴進行緩存的(依賴:data中資料)
- 方法不存在緩存
- 方法要加括号,計算屬性直接用名稱不用加括号
- 方法可以傳參,計算屬性不行
過濾器
格式化資料,比如字元串格式化為首字母大寫,将日期格式化為指定的格等。
自定義過濾器可以全局使用
參數級聯使用,上一個參數的傳回值作為下一個參數的輸入值
計算屬性不能連續使用,過濾器可以
定義在Vue裡,隻有在本元件中使用
帶參數的過濾器,使用時format接收的參數是從第二個參數開始,第一個參數預設為
data
使用過濾器格式化日期
将時間格式化為yyyy-MM-dd格式
偵聽器
資料變化時執行異步或開銷較大的操作
偵聽器案例:驗證使用者名是否可用
需求:輸入框中輸入姓名,失去焦點時驗證是否存在,如果已經存在,提示重新輸入;如果不存在,提示可以使用。
- 通過v-model實作資料綁定
- 需要提供提示資訊
-
需要偵聽器監聽輸入資訊的變化
采用偵聽器監聽使用者名的變化
調用背景接口進行驗證
根據驗證的結果調整提示資訊
- 需要修改觸發事件
v-model.lazy
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div id="app">
<div>
<span>使用者名:</span>
<span> <input type="text" v-model.lazy='uname'>
</span>
<span>{{tip}}</span>
</div>
</div>
<script type="text/javascript" src="js/vue.js"></script>
<script type="text/javascript">
var vm = new Vue({
el:'#app',
data:{
uname:'',
tip:''
},
methods:{
checkName:function(uname){
//調用接口,可以選用定時任務的方式模拟接口調用
var that = this;//是以先用that緩存this
setTimeout(function(){
//模拟接口調用
//setTimeout中的this是windows
if(uname == 'admin'){
that.tip = '使用者名已經存在,請更換一個'
}else{
that.tip = '使用者名可以使用'
}
},2000);
}
},
watch:{
uname:function(val){
//調用背景接口驗證使用者名的合法性
this.checkName(val);
//修改提示資訊
this.tip = '正在驗證……';
}
},
});
</script>
</body>
</html>
生命周期
主要階段
圖書管理
替換數組傳回值一般要指派給新數組
使用索引修改的數組資料不會顯示在頁面,響應式
但是使用索引修改的對象資料可以顯示在頁面,非響應式,控制台修改資料頁面也不變化
修改響應式資料可以用于修改數組和對象資料
圖書清單
- 實作靜态清單效果
- 基于資料實作模闆效果
- 處理每行的操作按鈕
添加圖書
- 實作表單靜态效果
- 添加圖書表單域資料綁定
- 添加按鈕事件綁定
- 實作添加業務邏輯
修改圖書
- 修改資訊填充到表單
- 修改後重新送出表單
- 重用添加和修改方法
删除圖書
- 删除按鈕綁定事件處理方法
- 實作删除業務邏輯
箭頭函數中的
this
等于定義該函數的父級作用域中的
this
初始表格頁面
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style type="text/css">
.grid{
margin:auto;
width: 500px;
text-align: center;
}
.grid table{
width: 100%;
border-collapse: collapse;
}
.grid th,td{
padding: 10;
border: 1px dashed orange;
height: 35px;
line-height: 35px;
}
.grid th{
background-color: orange;
}
.grid .book{
padding-bottom:10px;
padding-top:5px;
background-color: #F3DCAB;
}
</style>
</head>
<body>
<div id="app">
<div class="grid">
<div>
<h1>圖書管理</h1>
<div class="book">
<div>
<label for="id">編号</label>
<input type="text" id="id">
<label for="name">名稱</label>
<input type="text" id="name">
<button>送出</button>
</div>
</div>
</div>
<table>
<thead>
<tr>
<th>編号</th>
<th>名稱</th>
<th>時間</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>JavaScript</td>
<td>2018-01-01</td>
<td>删除</td>
</tr>
<tr>
<td>1</td>
<td>JavaScript</td>
<td>2018-01-01</td>
<td>删除</td>
</tr>
<tr>
<td>1</td>
<td>JavaScript</td>
<td>2018-01-01</td>
<td>删除</td>
</tr>
</tbody>
</table>
</div>
</div>
<script type="text/javascript" src="js/vue.js"></script>
<script type="text/javascript">
var vm = new Vue({
el:'#app',
data:{
id:'',
name:'',
books:[{
id: 1,
name: '三國演義',
date: ''
},{
id: 2,
name: '水浒傳',
date: ''
},{
id: 3,
name: '紅樓夢',
date: ''
},{
id: 4,
name: '西遊記',
date: ''
}]
},
});
</script>
</body>
</html>
完整
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style type="text/css">
.grid{
margin:auto;
width: 500px;
text-align: center;
}
.grid table{
width: 100%;
border-collapse: collapse;
}
.grid th,td{
padding: 10;
border: 1px dashed orange;
height: 35px;
line-height: 35px;
}
.grid th{
background-color: orange;
}
.grid .book{
padding-bottom:10px;
padding-top:5px;
background-color: #F3DCAB;
}
.grid .total{
height: 30px;
line-height: 30px;
background-color: #F3DCAB;
border-top: 1px solid #C2D89A;
}
</style>
</head>
<body>
<div id="app">
<div class="grid">
<div>
<h1>圖書管理</h1>
<div class="book">
<div>
<label for="id">編号</label>
<input type="text" id="id" v-model="id" :disabled="flag">
<label for="name">名稱</label>
<input type="text" id="name" v-model="name">
<button @click="handle" disabled="submitFlag">送出</button>
</div>
</div>
</div>
<div class="total">
<span>圖書總數:</span>
<span>{{total}}</span>
</div>
<table>
<thead>
<tr>
<th>編号</th>
<th>名稱</th>
<th>時間</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<tr :key='item.id' v-for='item in books'>
<td>{{item.id}}</td>
<td>{{item.name}}</td>
<td>{{item.date | format('yyyy-MM-dd hh:mm:ss')}}</td>
<td>
<a href="" @click.prevent='toEdit(item.id)'>修改</a>
<!---禁止a标簽的預設行為,不會跳轉--->
<span></span>
<a href="" @click.prevent='deleteBook(item.id)'>删除</a>
</td>
</tr>
</tbody>
</table>
</div>
</div>
<script type="text/javascript" src="js/vue.js"></script>
<script type="text/javascript">
Vue.directive('focus', {
inserted: function (el) {
el.focus();
}
});
Vue.filter('format', function(value, arg) {
function dateFormat(date, format) {
if (typeof date === "string") {
var mts = date.match(/(\/Date\((\d+)\)\/)/);
if (mts && mts.length >= 3) {
date = parseInt(mts[2]);
}
}
date = new Date(date);
if (!date || date.toUTCString() == "Invalid Date") {
return "";
}
var map = {
"M": date.getMonth() + 1, //月份
"d": date.getDate(), //日
"h": date.getHours(), //小時
"m": date.getMinutes(), //分
"s": date.getSeconds(), //秒
"q": Math.floor((date.getMonth() + 3) / 3), //季度
"S": date.getMilliseconds() //毫秒
};
format = format.replace(/([yMdhmsqS])+/g, function(all, t) {
var v = map[t];
if (v !== undefined) {
if (all.length > 1) {
v = '0' + v;
v = v.substr(v.length - 2);
}
return v;
} else if (t === 'y') {
return (date.getFullYear() + '').substr(4 - all.length);
}
return all;
});
return format;
}
return dateFormat(value, arg);
})
var vm = new Vue({
el:'#app',
data:{
flag: false,
submitFlag: false,
id:'',
name:'',
books:[]
},
methods:{
handle:function(){
if(this.flag == true){
//編輯操作
//根據目前的id去更新數組中對應的資料
this.books.some((item) => {
if(item.id == this){
item.name = this.name;
//完成更新操作後,需要終止循環
return true;
}
});
this.flag = false;
}else{
//添加圖書
var book = {};
book.id = this.id;
book.name = this.name;
book.date = '';
this.books.push(book);
//清空表單
this.id = '';
this.name = '';
}
//送出成功後清空表單
this.id = '';
this.name = '';
},
toEdit:function(id){
//禁止修改id
this.flag = true;
console.log(id)
//根據id查詢要編輯的資料
var book = this.books.filter(function(item){
return item.id == id;
});
console.log(book)
//把擷取到的資訊填充到表單
this.id = book[0].id;
this.name = book[0].name;
},
deleteBook:function(id){
//删除圖書
//根據id從數組中查找元素索引
var index = this.books.findIndex(function(item){
return item.id == id;
});
//根據索引删除數組元素
this.books.splice(index,1);
//方法二:
//通過filter方法進行删除
//排除要删除的剩下就是删除後的内容,是以判斷傳回id不相等的那部分就是删除後的内容
//this.books = this.books.filter(function(item){
//return item.id != id;
//});
}
},
computed: {
total: function(){
// 計算圖書的總數
return this.books.length;
}
},
watch: {
name: function(val) {
// 驗證圖書名稱是否已經存在
var flag = this.books.some(function(item){
return item.name == val;
});
if(flag) {
// 圖書名稱存在
this.submitFlag = true;
}else{
// 圖書名稱不存在
this.submitFlag = false;
}
}
},
mounted: function(){
// 該生命周期鈎子函數被觸發的時候,模闆已經可以使用
// 一般此時用于擷取背景資料,然後把資料填充到模闆
var data = [{
id: 1,
name: '三國演義',
date: 2525609975000
},{
id: 2,
name: '水浒傳',
date: 2525609975000
},{
id: 3,
name: '紅樓夢',
date: 2525609975000
},{
id: 4,
name: '西遊記',
date: 2525609975000
}];
this.books = data;
}
});
</script>
</body>
</html>
元件化開發
元件注冊
名稱有要求
資料通過return傳回值,每個元件資料獨立
局部元件隻能在注冊他的父元件中使用
元件命名方式
如果使用駝峰式命名元件,在使用元件時候,隻能在字元串模闆中用駝峰的方式使用