本文的意義在于總結一些因為版本的更迭導致比較常見的地方引起錯誤,具體說明可以參考vue官網
目錄
1、組件模板寫法
2、組件定義
3、生命周期
4、重復數據循環
5、自定義鍵盤指令
6、filter過濾器
7、組件通信
8、動畫
9、vue-router
1、組件模板寫法變更
vue2.0不在支持片段代碼,例如以下
//下邊的組件寫法在vue1.0可以正常執行,但vue2.0會給出警告,必須給他一個根節點,也就是唯一父級
//[Vue warn]: Component template should contain exactly one root element:
<script>
Vue.component('my-aaa',{
template:'<h3>我是組件</h3><strong>我是加粗標簽</strong>'
});
</script>
//推薦此種方式寫組件,必須有根元素,包裹住所有的代碼
<script>
Vue.component('my-aaa',{
template:'#aaa'
});
</script>
<body>
<template id="aaa">
<div>
<h3>我是組件</h3>
<strong>我是加粗標簽</strong>
</div>
</template>
</body>
2、組件定義
//使用組件必須注冊
//[Vue warn]: Unknown custom element: <my-aaa> - did you register the component correctly? For recursive components, make sure to provide the "name" option.
<script>
var Home={ //這是2.0組件
template:'#aaa'
}; //Vue.extend()
Vue.component('my-aaa',Home); //注冊方式1
</script>
<body>
<template id="aaa">
<div>
<h3>我是組件</h3>
<strong>我是加粗標簽</strong>
</div>
</template>
<div id="box">
<my-aaa></my-aaa>
</div>
</body>
//第二種方式
<script>
var Home={ //這是2.0組件
template:'#aaa'
}; //Vue.extend()
window.onload=function(){
new Vue({
el:'#box',
components:{ //注冊方式2
'aaa':Home
}
});
};
</script>
<body>
<template id="aaa">
<div>
<h3>我是組件</h3>
<strong>我是加粗標簽</strong>
</div>
</template>
<div id="box">
<my-aaa></my-aaa>
</div>
</body>
3、生命周期
vue1.0生命周期:
init
created
beforeCompile
compiled
ready √ -> mounted
beforeDestroy
destroyed
vue2.0生命周期:
beforeCreate 組件實例剛剛被創建,屬性都沒有
created 實例已經創建完成,屬性已經綁定
beforeMount 模板編譯之前
mounted 模板編譯之后,代替之前ready *
beforeUpdate 組件更新之前
updated 組件更新完畢 *
beforeDestroy 組件銷毀前
destroyed 組件銷毀后
<script>
new Vue({
el:'#box',
beforeCreate(){
console.log('組件實例剛剛被創建');
},
created(){
console.log('實例已經創建完成');
},
beforeMount(){
console.log('模板編譯之前');
},
mounted(){
console.log('模板編譯完成');
},
beforeUpdate(){
console.log('組件更新之前');
},
updated(){
console.log('組件更新完畢');
},
beforeDestroy(){
console.log('組件銷毀之前');
},
destroyed(){
console.log('組件銷毀之后');
}
});
</script>
4、重復數據循環
//[Vue warn]: Duplicate value found in v-for="val in list": "background". Use track-by="$index" if you are expecting duplicate values.
//vue1.0循環重復數據會受限制,vue2.0正常
<script>
window.onload=function(){
new Vue({
el:'#box',
data:{
list:['width','height','border']
},
methods:{
add(){
this.list.push('background');
}
}
});
};
</script>
<div id="box">
<input type="button" value="添加" @click="add">
<ul>
<li v-for="val in list"> //vue1.0循環需要添加 track-by="$index"
{{val}}
</li>
//[Vue warn]: Property or method "$key" is not defined on the instance but referenced during render. Make sure to declare reactive data properties in the data option.
<li v-for="val in list">
{{$index}} {{$key}} //vue2.0去掉了隱式一些變量 $index $key
</li>
<li v-for="(index,val) in list"> //vue1.0循環寫法v-for="(index,val) in array"
{{val}} {{index}}
</li>
<li v-for="(val,index) in list"> //vue2.0循環寫法 v-for="(index,val) in array"
{{val}} {{index}} // 傾向于js原生forEach,先寫val再寫index
</li>
</ul>
</div>
//提高循環性能 track-by="id" 變成 :key="index"
<script>
window.onload=function(){
new Vue({
el:'#box',
data:{
list:{
a:'apple',
b:'banana',
c:'cell'
}
}
});
};
</script>
<div id="box">
<ul>
<li v-for="(val,key) in list" :key="index">
{{val}} {{key}}
</li>
</ul>
</div>
5、自定義鍵盤指令
<script>
window.onload=function(){
new Vue({
el:'#box',
data:{
},
methods:{
change(){
alert('改變了');
}
}
});
//Vue.directive('on').keyCodes.ctrl=17; //vue1.0寫法
Vue.config.keyCodes.ctrl=17; //vue2.0寫法
};
</script>
<div id="box">
<input type="text" @keyup.ctrl="change">
</div>
6、filter過濾器
vue1.0系統就自帶很多過濾,例如currency/json等等。到了vue2.0,作者刪除全部內置過濾器,保留了自定義過濾器,但自定義過濾器傳參格式有點區別。
<script>
Vue.filter('toDou',function(n,a,b){
alert(a+','+b);
return n<10?'0'+n:''+n;
});
window.onload=function(){
new Vue({
el:'#box',
data:{
msg:9
}
});
};
</script>
<div id="box">
{{msg | toDou '12' '5'}} //vue1.0寫法
{{msg | toDou('12','5')}} //vue2.0寫法
</div>
7、組件通信
子級獲取父級的數據,通過props
//vue1.0寫法,子組件可以更改父組件信息,可以是同步sync
<script>
window.onload=function(){
new Vue({
el:'#box',
data:{
a:'我是父組件數據'
},
components:{
'child-com':{
props:['msg'],
template:'#child',
methods:{
change(){
this.msg='被更改了'
}
}
}
}
});
};
</script>
<template id="child">
<div>
<span>我是子組件</span>
<input type="button" value="按鈕" @click="change">
<strong>{{msg}}</strong>
</div>
</template>
<div id="box">
父級: ->{{a}}
<br>
<child-com :msg.sync="a"></child-com> //需要同步更改父級需要加上.sync
</div>
//[Vue warn]: Avoid mutating a prop directly since the value will be overwritten whenever the parent component re-renders. Instead, use a data or computed property based on the prop's value. Prop being mutated: "msg"
//vue2.0寫法跟vue1.0有點區別,不然會報以上警告。 不允許直接給父級的數據,做賦值操作
//處理方式 a). 父組件每次傳一個對象給子組件, 對象之間引用,推薦 b). 只是不報錯, mounted中轉
//方式a
<script>
window.onload=function(){
new Vue({
el:'#box',
data:{
giveData:{
a:'我是父組件數據'
}
},
components:{
'child-com':{
props:['msg'],
template:'#child',
methods:{
change(){
this.msg.a='被改了';
}
}
}
}
});
};
</script>
<template id="child">
<div>
<span>我是子組件</span>
<input type="button" value="按鈕" @click="change">
<strong>{{msg.a}}</strong>
</div>
</template>
<div id="box">
父級: ->{{giveData.a}}
<br>
<child-com :msg="giveData"></child-com>
</div>
//方式b
<script>
window.onload=function(){
new Vue({
el:'#box',
data:{
a:'我是父組件數據'
},
components:{
'child-com':{
data(){
return {
b:''
}
},
props:['msg'],
template:'#child',
mounted(){
this.b=this.msg;
},
methods:{
change(){
this.b='被改了';
}
}
}
}
});
};
</script>
<template id="child">
<div>
<span>我是子組件</span>
<input type="button" value="按鈕" @click="change">
<strong>{{b}}</strong>
</div>
</template>
<div id="box">
父級: ->{{a}}
<br>
<child-com :msg.sync="a"></child-com>
</div>
//注意如果是父子級可以通過以上方式處理。如果是同級組件之間想傳遞數據,也就是單一事件管理,通過vm.$emit()傳遞,vm.$on()接收。類似vuex實現原理。
格式參考:
var Event=new Vue();
Event.$emit(事件名稱, 數據)
Event.$on(事件名稱,function(data){
//data
}.bind(this));
//具體實現
<script>
//準備一個空的實例對象
var Event=new Vue();
var A={
template:`
<div>
<span>我是A組件</span> -> {{a}}
<input type="button" value="把A數據給C" @click="send">
</div>
`,
methods:{
send(){
Event.$emit('a-msg',this.a);
}
},
data(){
return {
a:'我是a數據'
}
}
};
var B={
template:`
<div>
<span>我是B組件</span> -> {{a}}
<input type="button" value="把B數據給C">
</div>
`,
data(){
return {
a:'我是b數據'
}
}
};
var C={
template:`
<div>
<h3>我是C組件</h3>
<span>接收過來的A的數據為: {{a}}</span>
</div>
`,
data(){
return {
a:'',
b:''
}
},
mounted(){
//var _this=this;
Event.$on('a-msg',function(a){
this.a=a;
}.bind(this));
}
};
window.onload=function(){
new Vue({
el:'#box',
components:{
'com-a':A,
'com-b':B,
'com-c':C
}
});
};
</script>
<div id="box">
<com-a></com-a>
<com-b></com-b>
<com-c></com-c>
</div>
8、動畫
動畫如果有結合animate,相關配置參數和效果查看可以參考animate官網
vue1.0寫法,transition是屬性
<p transition="fade"></p>
處理好fade相關樣式就可以實現動畫效果
.fade-transition{}
.fade-enter{}
.fade-leave{}
vue2.0寫法,transition變成了組件,需要把要做動畫的包起來,一般是包router-view
<transition name="fade">
運動東西(元素,屬性、路由....)
</transition>
class定義:
.fade-enter-active,.fade-leave-active{transition:1s all ease;}
.fade-enter{} //初始狀態
.fade-enter-active{} //變化成什么樣 -> 當元素出來(顯示)
.fade-leave{}
.fade-leave-active{} //變成成什么樣 -> 當元素離開(消失)
動畫可以配合animate.css使用,把fade和name去掉。給transition加enter-active-class="zoomInleft" leave-active-class="zoomOutRight",給運動的元素本身加class="animated"。
<transition enter-active-class="animated zoomInLeft" leave-active-class="animated zoomOutRight">
<p v-show="show"></p>
</transition>
多個元素運動需要使用transition-group,并且把每個運動元素加個:key="index":
<transition-group enter-active-class="" leave-active-class="">
<p :key=""></p>
<p :key=""></p>
</transition-group>
9、vue-router
vue1.0寫法:
<a v-link="{path:'/home'}">我是主頁</a>
router.rediect //重定向 2.0廢棄了
subRoutes //路由嵌套用subRoutes,配置跟父級一樣是json
vue2.0寫法:
<router-link to="/home">我是主頁</router-link> 它會自動解析成a v-link形式
const routes = [ //配置路由
{path:'/home',component:Home},
{path:'*',redirect:'/home'} //重定向
...一個個json
];
children //路由嵌套用children,配置跟父級一樣是json
路由實例方法:
router.push({path:'home'}); //直接添加一個路由,表現切換路由,本質往歷史記錄里面添加一個
router.replace({path:'news'}) //替換路由,不會往歷史記錄里面添加
帶有參數的路由配置
<ul>
<li><router-link to="/user/strive/age/10">Strive</router-link></li>
<li><router-link to="/user/blue/age/80">Blue</router-link></li>
<li><router-link to="/user/eric/age/70">Eric</router-link></li>
</ul>
//配置路由
const routes=[
{path:'/home', component:Home},
{
path:'/user',
component:User,
children:[
{path:':username/age/:age', component:UserDetail}
]
},
{path:'*', redirect:'/home'} //找不到的頁面全部重定向到home,相當于404
];