可复用性的组件详解
1.使用组件的原因
2.组件的使用方法
-
全局注册
Vue.component('my-component',{ template:'<div>我是组件的内容</div>' }) 优点:所有的nue实例都可以用 缺点:权限太大,容错率降低
-
全局注册
let app = new Vue({ el: "#app", components: { "my-component": { template: "<div>我是组件的内容</div>", }, }, });
注:
vue组件的模板在某些情况下会受到html标签的限制,
比如table
中只能含有<tr><td>
这些元素, 所以直接在table中使用组件是无效的,此时可以使用is属性来挂载组件
<table>
<tbody is="my-component">
</tbody>
</table>
3.组件使用的奇淫技巧
- 推荐使用小写字母加进行命名(必须) child, my-componnet命名组件
- template中的内容必须被一个DOM元素包括 ,也可以嵌套
- 在组件的定义中,除了template之外的其他选项—data,computed,methods
- data必须是一个方法
4.使用props传递数据 父亲向儿子传递数据
-
在组件中使用props来从父亲组件接收参数,
注意:在props中定义的属性,都可以在组件中直接使用
-
propps来自父级,而组件中data return的数据就是组件自己的数据,两种情况作用域就是组件本身,可以在template,computed,methods中直接使用
-
props的值有两种,一种是字符串数组,一种是对象,本节先只讲数组
-
可以使用vbind动态绑定父组件来的内容
5. 单向数据流
解释
通过 props 传递数据是单向的流, 也就是父组件数据变化时会传递给子组件,但是反过来不行。
目的
是尽可能将父子组件解耦,避免子组件无意中修改了父组件的状态。
应用场景
业务中会经常遇到两种需要改变 prop 的情况
<div id="app">
<my-comp init-count="666"></my-comp>
</div>
<script>
var app = new Vue({
el: "#app",
components: {
"my-comp": {
props: ["init-count"],
template: "<div>{{init-count}}</div>",
data: function () {
return {
count: this.initCount,
};
},
},
},
});
</script>
<div id="app">
<inputtype="text" v-model="width">
<my-comp :width="width"></my-comp>
</div>
let app = new Vue({
el:'#app',
data:{
width:''
},
components:{
'my-comp':{
props:['width'],
template:'<div :style="style">{{init-count}}</div>',
computed:{
style:function () {
return{
width:this.width+'px',
background:'red'
}
}
}
}
}
})
数据验证
总结:除了在html里 都用驼峰就完事了。
类型
- String
- Number
- Boolean
- Object
- Array
- Function
Vue.component ('my-compopent',{
props : {
//必须是数字类型
propA : Number ,
//必须是字符串或数字类型
propB : [String , Number] ,
//布尔值,如果没有定义,默认值就是 true
propC: {
type : Boolean ,
default : true
},
//数字,而且是必传
propD: {
type: Number ,
required : true
},
//如果是数组或对象,默认值必须是一个函数来返回
propE: {
type : Array ,
default : function () {
return [] ;
}
},
//自定义一个验证函数
propF: {
validator : function (value) {
return value > 10;
}
}
}
})
7.组件通信
组件关系可分为父子组件通信、兄弟组件通信、跨级组件通信
1. 自定义事件—子组件给父组件传递数据
使用v-on除了监昕 DOM 事件外,还可以用于组件之间的自定义事件。
JavaScript 的设计模式 一一观察者模式,dispatchEvent 和 addEventListener这两个方法。
Vue组件也有与之类似的一套模式,子组件用emit()来触发事件,父组件用on()来 监昕子组件的事件 。
直接甩代码
第一步:自定义事件
第二步: 在子组件中用$emit触发事件,第一个参数是事件名,后边的参数是要传递的数据
第三步:在自定义事件中用一个参数来接受
<template>
<div id="app">
<p>您好,您现在的银行余额是{{ total }}元</p>
<btn-compnent @change="handleTotal"></btn-compnent>{{ myString }}
</div>
</template>
<script>
export default {
name: "App",
components: {
"btn-compnent": {
template:
'<div>\
<button @click="handleincrease">+1</button> \
<button @click="handlereduce">-1</button>\
</div>',
data: function () {
return {
count: 0,
myString1: "俺又赚钱了,哈哈哈哈哈哈哈",
myString2: "俺又赔钱了,呜呜呜呜呜",
};
},
methods: {
handleincrease: function () {
this.count += 1;
this.$emit("change", this.count, this.myString1);
},
handlereduce: function () {
this.count--;
this.$emit("change", this.count, this.myString2);
},
},
},
},
data() {
return {
total: 0,
myString: "",
};
},
methods: {
handleTotal: function (total, string) {
this.total = total;
this.myString = string;
},
},
};
</script>
<style>
</style>
2.在组件中使用vmode
$emit的代码,这行代码实际上会触发一个 input事件, 'input'后的参数就是传递给vmodel绑定的属性的值
vmodel 其实是一个语法糖,这背后其实做了两个操作
- v-bind 绑定一个value属性
- v-on 指令给当前元素绑定 input 事件
要使用vmodel,要做到:
- 接收一个 value 属性。
- 在有新的 value 时触发 input 事件
<div id="app">
<p>您好,您现在的银行余额是{{total}}元</p>
<btn-compnent v-model="total"></btn-compnent>
</div>
<script>
var app = new Vue({
el: "#app",
data: {
total: 0
},
components: {
"btn-compnent": {
template:
'<div>\
<button @click="handleincrease">+1</button> \
<button @click="handlereduce">-1</button>\
</div>',
data: function () {
return {
count: 0
};
},
methods: {
handleincrease: function () {
this.count++;
--------注意观察.这一行,emit的是input事件---------
this.$emit("input", this.count);
},
handlereduce: function () {
this.count--;
this.$emit("input", this.count);
}
}
}
},
methods: {
/* handleTotal:function (total) {
this.total = total;
}*/
}
});
</sciprt>
3.非父组件之间的通信
有时候两个组件也需要通信,(非父子关系)。
在简单的场景下,可以使用一个空的Vue实例作为中央时间总线
图案实例
<div id="app" >
<my-acomponent></my-acomponent>
<my-bcomponent></my-bcomponent>
</div>
components: {
"my-acomponent": {
template:
'<div><button @click="handle">点击我向B组件传递数据</button></div>',
data: function () {
return {
aaa: "我是来自A组件的内容",
};
},
methods: {
handle: function () {
this.$root.bus.$emit("lala", this.aaa);
},
},
},
"my-bcomponent": {
template: "<div></div>",
created: function () {
//A组件在实例创建的时候就监听事件---lala事件
this.$root.bus.$on("lala", function (value) {
alert(value);
});
},
},
},
父链:this.$parent
Vue.component("child-component", {
template: '<button @click="setFatherData">通过点击我修改父亲的数据</button>',
methods: {
setFatherData: function () {
this.$parent.msg = "数据已经修改了";
}
}
});
子链:this.$refs
提供了为子组件提供索引的方法,用特殊的属性ref为其增加一个索引
let app = new Vue({
el: "#app",
data: {
//bus中介
bus: new Vue(),
msg: "数据还未修改",
formchild: "还未拿到"
},
methods: {
getChildData: function () {
//用来拿子组件中的内容 ---- $refs
this.formchild = this.$refs.c.msg;
}
}
});
4.使用slot分发内容
1.什么是slot(插槽)
为了让组件可以组合,我们需要一种方式来混合父组件的内容与子组件自己的模板。
这个过程被称为内容分发,Vue.js 实现了一个内容分发 API,
使用特殊的 'slot'元素作为原始内容的插槽。
2.编译的作用域
在深入内容分发 API 之前,我们先明确内容在哪个作用域里编译。假定模板为:
<child-component>
{{ message }}
</child-component>
message 应该绑定到父组件的数据,还是绑定到子组件的数据?
答案是父组件。
组件作用域简单地说是:
父组件模板的内容在父组件作用域内编译;
子组件模板的内容在子组件作用域内编译。
3.插槽的用法
父组件的内容与子组件相混合,从而弥补了视图的不足
混合父组件的内容与子组件自己的模板
单个插槽:
<div id="app">
<my-component>
<p>我是父组件的内容</p>
</my-component>
</div>;
Vue.component("my-component", {
template:
"<div>\
<slot>\
如果父组件没有插入内容,我就作为默认出现\
</slot>\
</div>"
});
具名插槽:
<name-component>
<h3 slot="header">我是标题</h3>
<p>我是正文内容</p>
<p>正文内容有两段</p>
<p slot="footer">我是底部信息</p>
</name-component>
Vue.component("name-component", {
template:
'<div>\
<div class="header">\n' +
' <slot name="header">\n' +
" \n" +
" </slot>\n" +
"</div>\n" +
'<div class="contatiner">\n' +
" <slot>\n" +
" \n" +
" </slot>\n" +
"</div>\n" +
'<div class="footer">\n' +
' <slot name="footer">\n' +
"\n" +
" </slot> \n" +
"</div>" +
" </div>"
});
4.作用域插槽
作用域插槽是一种特殊的slot,
使用一个可以复用的模板来替换已经渲染的元素
从子组件获取数据
template模板是不会被渲染的
Vue.component("my-component", {
template:
'<div>\
<slot text="我是来自子组件的数据" ss="fdjkfjlsd" name="abc">\
</slot>\
</div>'
});
5.访问slot
通过this.$slots.(NAME)
mounted:function () {
//访问插槽
let header = this.$slots.header;
let text = header[0].elm.innerText;
let html = header[0].elm.innerHTML;
console.log(header)
console.log(text)
console.log(html)
}
5.组件高级用法–动态组件
VUE给我们提供 了一个元素叫component
作用是:用来动态的挂载不同的组件
实现:使用is特性来进行实现的
常见问题FAQ
- 免费下载或者VIP会员专享资源能否直接商用?
- 本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
- 提示下载完但解压或打开不了?
- 找不到素材资源介绍文章里的示例图片?
- 模板不会安装或需要功能定制以及二次开发?
发表评论
还没有评论,快来抢沙发吧!