主要内容
1.解决vue组件渲染的bug
2.组件引用
3.父子组件间的值传递
4.组件的参数校验及非props特性
5.给父组件绑定原生事件
6.组件间的数据传递处理
7插槽的使用
8.作用域插槽
9.动态组件及v-one指令
Vue组件引发的bug及解决方案:
<div id="app">
<table>
<tbody>
<row></row>
<row></row>
<row></row>
</tbody>
</table>
</div>
<script>
Vue.component("row",{
template:"<tr><td>this is a row</td></tr>"
})
var vm = new Vue({
el:'#app'
});
当我们使用这种方式使用组件的时候浏览器由于H5的规范 tbody下面必须是tr和td, 而不识别row,所以会引发渲染的问题,如下是渲染之后的结果,tr和td在tbody之外了
解决方案 用tr取代掉组件标签 并在tr中 加入is属性 值为组件名 ul->li,ol->li,select ->option 中同理
<tr is="row"></tr>
2.在子组件中定义data,data必须是一个函数,因为子组件会被调用多次,每一个子组件都拥有一个独立的数据空间,互不影响
Vue.component("row",{
data:function(){
return {
content:"hello world"
}
},
template:"<tr><td>{{content}}</td></tr>"
})
3.引用: 当我们不得不对dom元素进行操作的时候,我们需要用引用来实现对dom的操作,比如动画效果等等
this.$refs:指的是所有的vue中的引用
<div ref="hello"
@click="handleClick">
hello world
</div>
methods:{
handleClick:function(){
alert(this.$refs.hello.innerHTML);
}
}
组件引用:
<div id="app">
<!--组件引用-->
<count ref="count1" @change="handleChange"></count>
<count ref="count2" @change="handleChange"></count>
<div>{{total}}</div>
</div>
<script>
Vue.component("count", {
template: "<div @click='changeNumber'>{{number}}</div>",
data: function () {
return {
number: 0
}
},
methods: {
changeNumber: function () {
this.number++;
// 向父组件添加监听方法
this.$emit('change');
}
}
})
var vm = new Vue({
el: '#app',
data: {
total: 0
},
methods: {
handleChange: function () {
this.total = this.$refs.count1.number + this.$refs.count2.number;
}
}
});
4.父子组件中的数据传递
父组件向子组件中通过属性进行传值
单向数据流 :父组件可以随意向子组件传递参数,但是子组件不能随意修改父组件传递过来的参数,只能使用,因为修改父组件的值可能会影响到其他的子组件的使用。
子组件通过事件向父组件中传值
<div id="app">
<counter :count="2" @change="handleChange"></counter>
<counter :count="3" @change="handleChange"></counter>
<div>{{total}}</div>
</div>
<script>
var counter={
props:['count'],
data:function(){
return{
// 根据单向数据流的规则,不能直接修改父组件传递过来的参数值,而是用一个独立的数据空间用来存储父组件传递过来的值,然后进行操作
number:this.count
}
},
template:"<div @click='handleClick'>{{number}}</div>",
methods:{
handleClick:function(){
this.number+=2;
this.$emit("change",2); //可以传递多个参数
}
}
}
var vm = new Vue({
el:'#app',
data:{
total:5
},
components:{
counter:counter
},
methods:{
handleChange:function(step){
this.total=this.total+step;
}
}
});
5.组件参数校验与非props特性
Vue.component("son", {
// props:{
content:Number
content:[String,Number] 可以同时允许多个值
// content:{
type:String,
required:true,
default:"default value",
// validator:function(value){
// return value.length>5 && value.length<10;
// }
// }
// },
template: "<div>{{content}}</div>"
})
var vm = new Vue({
el: '#app'
});
6.给组件绑定原生事件
<div id="app">
<child @click.native="handleClick"></child>
</div>
<script>
Vue.component("child", {
//这才是子组件中的原生事件
// template:"<div @click='childClick'>hello world</div>",
template: "<div>hello world</div>"
// methods:{
// childClick:function(){
// alert("child click");
// this.$emit("click");
// }
// }
})
var vm = new Vue({
el: '#app',
methods: {
handleClick: function () {
alert("click");
}
}
});
7.组件间的传值
1.vuex框架
2.bus 总线,发布订阅模式,观察者模式
<div id="app">
<child content="wuhen"></child>
<child content="yegucheng"></child>
</div>
<script>
Vue.prototype.bus = new Vue();
Vue.component("child", {
data: function () {
return {
selfContent: this.content
}
},
props: {
content: String
},
template: "<div @click='handleClick'>{{selfContent}}</div>",
methods: {
handleClick: function () {
// 给bus中添加监听事件并传递需要传递的值,在需要使用的函数中监听该事件便可以获取到该值
this.bus.$emit("change", this.selfContent);
},
},
//mounted :当组件被装载的时候调用
mounted: function () {
var _this = this;
this.bus.$on("change", function (msg) {
_this.selfContent = msg;
})
}
})
var vm = new Vue({
el: '#app'
});
9.在Vue中使用插槽
父组件传递的标签会被转义,而不会被解析
<child>
<!--直接在父组件中传递标签 插槽的使用-->
<h1 slot="one">hello</h1>
<h1 slot="two">world</h1>
</child>
</div>
<script>
Vue.component("child", {
props: ['content'],
data: function () {
return {
selfContent: this.content
}
},
template: "<div>" +
'<slot name="one"></slot>' +
'<slot name = two></slot>' +
"</div>"
})
var vm = new Vue({
el: '#app'
});
10:作用域插槽:
<div id="app">
<child>
<!-- props 用来接收子组件传递过来的参数-->
<template slot-scope="props">
<h1>{{props.item}}</h1>
</template>
</child>
</div>
<script>
Vue.component("child",{
data:function(){
return{
list:[1,2,3,4]
}
},
//:item= item 向父组件传值 插槽循环调用
template:'<div>' +
"<slot v-for='item of list' :item=item></slot>"+
'</div>'
})
var vm = new Vue({
el:'#app'
});
</script>
11:动态组件 和 v-once 指令
当我们切换组件的时候Vue会帮我们销毁之前的组件,然后创建一个新的组件。这种操作会消耗大量性能。我们可以将组件的标签加上v-once ,这样就会将我们的子组件放到内存中,下次再使用的时候就不用重新创建了,而是直接从内存中去获取,可以提高我们对静态资源的显示效率。
<div id="app">
<!-- 没用动态组件的时候的实现方式-->
<!--<child-one v-if="type==='child-one'"></child-one>-->
<!--<child-two v-if="type==='child-two'"></child-two>-->
<!-- 动态组件的实现方式-->
<component :is="type"></component>
<button @click="handleChange">change</button>
</div>
<script>
Vue.component("child-one",{
//v-once 会将之前使用过的组件加载到内存中,下次使用的时候就能直接使用,提高静态资源的加载效率
template:'<div v-once>child-one</div>'
})
Vue.component("child-two",{
template:'<div v-once>child-two</div>'
})
var vm = new Vue({
el:'#app',
data:{
type:'child-one'
},
methods:{
handleChange:function(){
this.type= this.type==='child-one'? 'child-two':'child-one';
}
}
});