本文的意义在于总结一些因为版本的更迭导致比较常见的地方引起错误,具体说明可以参考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
];