1-watch偵聽器(監聽器)
- 本質: 一個特殊的函數
- 作用: 監視data中任意一個數據的改變, 從而實現一些特殊的業務處理
- 注意:
- 監視器函數的名字必須和要被監視的數據名稱保持一致
- 無需手動調用
- 語法
const vm = new Vue({
el: '#app',
data: {
msg:'hello',
user:{
name:'zs',
age:20,
sex:'男'
}
},
methods: {
updateMsg(){
this.msg='你好';
},
updateUser(){
this.user.name='張三';
// this.user={name:'張三'};
}
},
// watch監聽器
watch:{
// 監視器函數的名字必須和監視的數據名保持一致
msg(newVal,oldVal){
console.log(newVal,oldVal);
},
// 更新對象中某一個屬性的時候, 普通的監視器監聽不到屬性更新, 必須使用深度監聽
// 深度監聽
user:{
// 監聽方法
handler(newVal,oldVal){
console.log(newVal,oldVal);
},
// true表示要開啓深度監聽
deep:true
}
}
});
2-computed計算屬性
- 本質: 一種特殊的函數(當做數據調用)
- 作用: 可以根據已經存在的數據, 計算出來一個不存在的數據
- 注意:
- computed計算屬性函數必須有返回值
- 計算屬性函數名不能和data中的數據同名
- 調用的時候, 當做變量直接調用, 無需帶
()
- 特點: 計算屬性內部會有一些緩存機制
- 語法
<!--調用計算屬性-->
<h1>{{fullName}}</h1>
const vm = new Vue({
el: '#app',
data: {
firstName: '',
lastName: '',
},
methods: {
// 根據fistname和lastname計算一個fullname
fname(){
console.log('普通方法');
return this.firstName+this.lastName;
}
},
// computed計算屬性
computed:{
// 定義計算屬性
fullName:function(){
console.log('計算屬性方法');
return this.firstName+this.lastName;
}
}
});
3-filter過濾器
- 本質: 一種特殊的方法
- 作用: 對數據進行預處理
- 注意
- 過濾器處理函數必須至少有一個參數, 第一個參數永遠是待處理的數據, 由系統自動注入
- 過濾器處理函數必須有返回值
- 過濾器只能在插值表達式和v-bind指令中使用(其他指令中使用會報錯)
- 調用格式: 數據輸出的位置
{{msg | fn}}
3.1-全局過濾器
- 特點: 在所有的vue實例中都可以調用
- 語法格式
Vue.filter('過濾器的名稱',functoin(){ //進行數據預處理的函數 });
- 調用全局過濾器
<div id="app">
<!-- 調用過濾器 -->
<h1>{{msg | append}}</h1>
<hr>
<h1>{{msg | append1('***')}}</h1>
<hr>
<!-- 調用多個過濾器 -->
<h1>{{msg | append | append1('####')}}</h1>
</div>
- 定義全局過濾器
// params:系統自動注入的, input代表即將被處理的數據; params額外參數
Vue.filter('append', function (input) {
// 必須有返回值
return input+'~~~';
});
Vue.filter('append1', function (input,params) {
// 必須有返回值
return input + params;
});
### 3.2-私有過濾器
- 特點: 只能在當前vue實例中調用
- 書寫位置
```js
new Vue({
el:'#app',
// 私有過濾器
filters:{
// input:系統自動注入, 代表待處理的數據
fn(input){
// 必須有返回值
return ''
}
}
});
- 調用私有過濾器
<div id="app">
<!-- 調用私有過濾器 -->
<h1>{{msg | append}}</h1>
<hr>
<h1>{{msg | append('***')}}</h1>
<hr>
<h1>{{createTime | dateFmt}}</h1>
<h1>{{createTime | dateFmt('/')}}</h1>
<h1>{{createTime | dateFmt('.')}}</h1>
<h1>{{createTime | dateFmt('~')}}</h1>
</div>
- 定義私有過濾器
const vm = new Vue({
el: '#app',
data: {
msg: 'hello',
createTime:Date.now()
},
// 私有過濾器
filters:{
append(input,params='~~~'){
return `${input}${params}`
},
// 13位毫秒值=>yyyy-mm-dd HH:mm:ss
dateFmt(input,divider='-'){
// input: 時間戳: 13毫秒值
// 創建對應的日期對象
const date=new Date(input);
// 獲取年份
const y=date.getFullYear();
const m=date.getMonth()+1;
const d=date.getDate();
const h=date.getHours();
const mm=date.getMinutes();
const s=date.getSeconds();
return `${y}${divider}${m}${divider}${d} ${h}:${mm}:${s}`;
}
}
});
4-單元素過渡動畫
4.1-自定義過渡動畫類名
4.1.1-實現步驟
- 使用
<transition></transition>標籤包裹目標元素
<!-- 第一步: -->
<transition>
<h1 v-show="isShow">{{msg}}</h1>
</transition>
- 自定義過渡動畫類名的屬性
/* 第二步: 定義過渡動畫類名對應的屬性 */
/* 進入階段,離開階段 */
/* 進入前,離開後 */
.v-enter,.v-leave-to{
left:-400px;
}
/* 進入中,離開中 */
.v-enter-active,.v-leave-active{
position: relative;
transition: left 1s;
}
/* 進入後,離開前 */
.v-enter-to,.v-leave{
left:0;
}
4.1.2-自定義過渡類名前綴
- appear: 控制元素以過渡動畫的效果入場
- 第一步
/* 進入前,離開後 */
.slide-enter,.slide-leave-to{
left:-400px;
}
/* 進入中,離開中 */
.slide-enter-active,.slide-leave-active{
position: relative;
transition: left 1s;
}
/* 進入後,離開前 */
.slide-enter-to,.slide-leave{
left:0;
}
- 第二步
<!-- appear: 以過渡動畫的方式入場 -->
<transition appear name="slide">
<h1 v-show="isShow">{{msg}}</h1>
</transition>
4.2-使用第三方動畫類庫
- 下載並引入animate.css
<!-- 第一步: 引入動畫類庫 -->
<link rel="stylesheet" href="./libs/animate.css@3.5.1.css">
- 通過屬性引用動畫類名
- enter-active-class: 指定進入過程中的動畫類名
- leave-active-class: 指定離開過程中的動畫類名
<div id="app">
<!-- 第二步: 通過屬性引用動畫類名; animated是基礎動畫類名, tada是決定動畫方式的類名 -->
<transition appear enter-active-class="animated tada" leave-active-class="animated bounceOutRight">
<h1 v-show="isShow">{{msg}}</h1>
</transition>
<hr>
<transition appear enter-active-class="animated swing" leave-active-class="animated wobble">
<h1 v-show="isShow">{{msg}}</h1>
</transition>
<hr>
<button @click="toggle">切換顯示狀態</button>
</div>
5-列表過渡動畫
5.1-自定義動畫類名
- 使用
transition-group標籤包裹目標元素(列表元素)
- tag: 指定最終渲染的標籤名稱
<!-- tag: 指定transition-group解析時候的標籤 -->
<transition-group tag="ul" name="slide" appear>
<li v-for="item in list" :key="item.id">{{item.id}}-{{item.name}}</li>
</transition-group>
- 自定義過渡動畫類名
.slide-enter,.slide-leave-to{
top:-400px;
}
.slide-enter-active,.slide-leave-active{
position: relative;
transition: all 1s;
}
.slide-enter-to,.slide-leave{
top:0;
}
5.2-使用第三方動畫類庫
- 下載並引入animate動畫類庫
<!-- 1-引入animate.css -->
<link rel="stylesheet" href="./libs/animate.css@3.5.1.css">
- 通過屬性引用動畫類名
<!-- tag: 指定transition-group解析時候的標籤 -->
<transition-group tag="ul" appear
enter-active-class="animated tada"
leave-active-class="animated wodder"
>
<li v-for="item in list" :key="item.id">{{item.id}}-{{item.name}}</li>
</transition-group>
5-本地存儲localStorage複習
- 什麼是localStorage: 瀏覽器端一種數據存儲方案
- 數據存儲位置: 電腦的磁盤上
- 存儲數據量: 相對比較大
- 特點: localStorage中只能存儲字符串, 不能直接存儲數組和對象
相關的方法
- 讀取數據:
// 讀取出來的數據類型是字符串
localStorage.getItem('key')
- 寫入數據
localStorage.setItem('key','value');
- 刪除數據
localStorage.removeItem('key');
6-品牌管理案例
6.1-靜態模板
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="./libs/vue.js"></script>
<style>
*{
padding:0;
margin:0;
box-sizing: border-box;
}
#app{
width: 800px;
margin:20px auto;
}
tr{
height: 50px;
text-align: center;
}
.form-control{
height: 40px;
padding:10px;
width: 100%;
border:1px solid #DDD;
border-radius: 4px;
}
.btn{
border:1px solid #DDD;
width: 60px;
line-height: 30px;
text-align: center;
color:#555;
background: #EEE;
border-radius:6px;
cursor: pointer;
font-weight: 700;
outline: 0;
}
.active{
background-color: #EEE;
}
table,td{
border:1px solid #CCC;
/* 合併邊框 */
border-collapse: collapse;
}
.btn.danger{
background-color: #D9534F;
color:#FFF;
}
.btn.success{
background-color:#337AB7;
color:#FFF;
}
.line{
border-bottom:1px solid #DDD;
margin:10px 0;
}
</style>
</head>
<body>
<div id="app">
<h1>品牌管理</h1>
<div class="line"></div>
<div>
<input class="form-control" type="text" placeholder="請輸入品牌名稱">
</div>
<div class="line"></div>
<table cellpadding="0" cellspacing="0" width="100%">
<thead>
<tr class="active">
<td width="120">id</td>
<td>品牌名稱</td>
<td>添加時間</td>
<td>操作</td>
</tr>
</thead>
<tbody>
<tr v-for="item in 10" :key="item">
<td>id</td>
<td>品牌名稱-{{item}}</td>
<td>2020-11-18 16:23</td>
<td>
<button class="btn danger">刪除</button>
<button class="btn success">編輯</button>
</td>
</tr>
</tbody>
</table>
</div>
</body>
<script>
new Vue({
el:'#app',
data:{
},
methods:{
},
computed:{
}
});
</script>
</html>
6.2-已實現功能
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="./libs/vue.js"></script>
<style>
*{
padding:0;
margin:0;
box-sizing: border-box;
}
#app{
width: 800px;
margin:20px auto;
}
tr{
height: 50px;
text-align: center;
}
.form-control{
height: 40px;
padding:10px;
width: 100%;
border:1px solid #DDD;
border-radius: 4px;
}
.btn{
border:1px solid #DDD;
width: 60px;
line-height: 30px;
text-align: center;
color:#555;
background: #EEE;
border-radius:6px;
cursor: pointer;
font-weight: 700;
outline: 0;
}
.active{
background-color: #EEE;
}
table,td{
border:1px solid #CCC;
/* 合併邊框 */
border-collapse: collapse;
}
.btn.danger{
background-color: #D9534F;
color:#FFF;
}
.btn.success{
background-color:#337AB7;
color:#FFF;
}
.line{
border-bottom:1px solid #DDD;
margin:10px 0;
}
</style>
</head>
<body>
<div id="app">
<h1>品牌管理</h1>
<div class="line"></div>
<h3>品牌數量:{{brandCount}}</h3>
<div class="line"></div>
<div>
<input @keyup.enter="add" v-model="brandName" class="form-control" type="text" placeholder="請輸入品牌名稱">
</div>
<div class="line"></div>
<table cellpadding="0" cellspacing="0" width="100%">
<thead>
<tr class="active">
<td width="120">id</td>
<td>品牌名稱</td>
<td>添加時間</td>
<td>操作</td>
</tr>
</thead>
<tbody>
<tr v-for="item in list" :key="item.id">
<td>{{item.id}}</td>
<td>{{item.name}}</td>
<td>{{item.ctime|dateFmt}}</td>
<td>
<button class="btn danger" @click="del(item.id)">刪除</button>
<button class="btn success">編輯</button>
</td>
</tr>
</tbody>
</table>
</div>
</body>
<script>
new Vue({
el:'#app',
data:{
// 和輸入框進行綁定的數據
brandName:'',
// 品牌列表數組
list:[]
},
methods:{
// 實現品牌添加
add(){
// 1-將新增的品牌添加到品牌列表數組中
// 1.1-構造品牌對象
const obj={
id:this.list.length>0?this.list[0].id+1:1,
name:this.brandName,
ctime:Date.now()
}
// 1.2-將品牌對象, 添加到數組中
this.list.unshift(obj);
// 1.3-重置表單
this.brandName='';
// 2-將品牌列表數組存儲本地存儲localStorage中
localStorage.setItem('brandlist',JSON.stringify(this.list));
},
// 品牌刪除
del(id){
if(!confirm('確認刪除?')){
return false;
}
// 1-刪除頁存內存中的數據
// 通過id查找index索引
const index=this.list.findIndex(item=>item.id===id);
this.list.splice(index,1);
// 2-刪除本地存儲中的品牌數據
// 讀取本地存儲中的品牌列表
// const list=JSON.parse(localStorage.getItem('brandlist')||'[]');
const list=this.getBrandList();
// 刪除對應品牌
list.splice(index,1);
// 重新寫入
localStorage.setItem('brandlist',JSON.stringify(list));
},
// 從本地存儲中讀取品牌列表
getBrandList(){
const list=JSON.parse(localStorage.getItem('brandlist')||'[]');
return list;
}
},
computed:{
brandCount(){
return this.list.length;
}
},
created(){
// 1-讀取本地存儲中的品牌列表信息
// const list=JSON.parse(localStorage.getItem('brandlist')||'[]');
const list=this.getBrandList();
// 2-更新數據list
this.list=list;
},
filters:{
dateFmt(input){
const date=new Date(input);
const y=date.getFullYear();
const m=date.getMonth()+1;
const d=date.getDate();
const h=date.getHours();
const mm=date.getMinutes();
const s=date.getSeconds();
return `${y}-${m}-${d} ${h}:${mm}:${s}`;
}
}
});
</script>
</html>