一、脚手架搭建的项目中组件使用
1、定义组件
-
在components目录下新建xxx.vue文件
-
在xxx.vue文件下写入代码
Myhead.vue中
<template>
<div>
这个是myhead组件
</div>
</template>
<script>
export default {
}
</script>
2、使用组件
①引入组件,②注入到components,③页面调用
// 组件模板
<template>
<div>
我的第一个vue项目
<!-- 3:调用 -->
<Myhead></Myhead>
</div>
</template>
// js
<script>
// 1:引入
import Myhead from './components/Myhead'
export default {
components:{
//2:注入
Myhead
}
}
</script>
二、组件数据通信
父向子传值 | 子向父传值 | 非父子传值 |
---|---|---|
1.父组件调用子组件,给子组件自定义属性;并在父组件中定义要传的数据值 | 1.父组件调用子组件时,给子组件自定义事件 | 1.main.js中定义一个公共区域 (新的vue实例) |
2.子组件通过props接收父组件传来的自定义属性 | 2.在父组件中的methods中定义自定义事件对应的函数 | 2.在A组件中给公共区域自定义事件.$on(‘事件名’,function(v){})–自定义接收值 |
3.子组件视图上直接使用该自定义属性 | 3.在子组件中定义要传的数据值,并通过this.$emit(‘事件名’,参数)触发自定义事件传值 | 3.在B组件中触发公共区域的自定义事件.$emit(‘事件名’,参数)–触发传值 |
1、父向子通信
-
1.父组件调用子组件,给子组件自定义属性
vue是单向数据流,子组件不能修改props中的属性,但是在父组件中修改,传到子组件的数据也会跟着变化
//父组件
<子组件 自定义属性1="值" 自定义属性2="值"></子组件>
//绑定属性
<子组件 :自定义属性1="变量"></子组件>
- 2.子组件通过props接收父组件传来的自定义属性
<script>
export default {
props:['自定义属性属性1','自定义属性属性2']
}
</script>
- 3.子组件视图上直接使用该自定义属性
{
{属性1}}
<li v-for="item in 属性1"></li>
父组件
// 组件模板
<template>
<div>
<!-- 1 自定义属性 -->
<Myhead :mycon="num" :mycom="flag" :dataarr="arr[0]"></Myhead>
<Myhead :dataarr="arr[1]"></Myhead>
<hr/>
<Myhead v-for="(item,index) in arr" :key="index" :dataarr="item"></Myhead>
</div>
</template>
// js
<script>
import Myhead from './components/Myhead'
export default {
data(){
return {
flag:true,
num:25,
arr:[
{
title:"title1",
list:[
'父组件中的数据1',
'父组件中的数据11'
]
},
{
title:"title1",
list:[
'父组件中的数据2',
'父组件中的数据22'
]
}
]
}
},
components:{
Myhead
}
}
</script>
// css
<style>
</style>
子组件
<template>
<div>
<div class="list">
<!-- 3:直接使用属性 -->
{
{
mycon}} ----{
{
mycom}}
<h3>{
{
dataarr.title}}</h3>
<ul>
<li v-for="(item,index) in dataarr.list" :key="index">
{
{
item}}
</li>
</ul>
</div>
</div>
</template>
<script>
export default {
props:['mycon','mycom','dataarr'], //2:通过props接收父组件传来的数据
data(){
return {
arr:[]
}
}
}
</script>
<style>
</style>
props验证
-
为了使组件内部使用数据的可靠性,我们对外部传递进来的数据进行校验
-
实现校验- 方式1
//方式1
props:['属性1','属性2']
- 实现校验- 方式2
//方式2 (String,Number,Boolean,Array,Object Date Function Symbol)
props:{
属性1:类型 , //只有类型检测
属性2:[类型1,类型2]
}
- 实现校验- 方式3
//方式3
props:{
属性1:{
type:类型 ,
default:默认值,
required:true/false,
validator:function(val){
//validator函数一定要有返回值,返回true表示验证通过,false验证不通过 控制台有警告
}
}
}
2、子向父通信
- 1.父组件调用子组件时,给子组件自定义事件
//父组件
<Child @自定义事件名="函数"></Child>
- 2.在父组件中的methods中定义自定义事件对应的函数
//父组件
methods:{
函数名(){}
}
- 3.在子组件中通过this.$emit(‘事件名’,参数)触发自定义事件
//子组件
this.$emit('事件名',参数)
父组件
<template>
<div>
{
{m}}
<hr/>
<!-- 1:自定义事件 @abc="函数名" -->
<Child @abc="fn"></Child>
</div>
</template>
<script>
import Child from './components/Child'
export default {
data(){
return {
m:""
}
},
components:{
Child
},
methods:{
fn(val){
//2:父组件中定义自定义事件对应的函数fn
console.log("wo 被触发了")
// val就是触发abc事件传递过来的参数
this.m=val;
}
}
}
</script>
子组件
<template>
<div>
{
{msg}}
<button @click="change">触发abc</button>
</div>
</template>
<script>
export default {
data(){
return {
msg:"子组件==成都"
}
},
created(){
// 3:触发自定义事件的
// this.$emit('事件名',参数)
// console.log(this)
// this.$emit('abc',this.msg)
},
methods:{
change(){
this.$emit('abc',this.msg)
}
}
}
</script>
3、非父子通信
- 中央事件总线:eventbus
需求:非父子组件A和B,从B组件向A组件传值
- 1.main.js中定义一个公共区域 (新的vue实例)
// 1:创建公共区域(新的vue实例)
var eventbus=new Vue();
// 2:公共区域挂载到Vue的原型上面(每一个vue实例都可以访问它原型上的成员)
Vue.prototype.$bus=eventbus;
- 2.在A组件中给公共区域自定义事件–自定义接收值
<template>
<div>
{
{m}}
</div>
</template>
<script>
export default {
data(){
return {
m:"123"
}
},
created(){
// // console.log(this,111)
// var that=this;
// // 公共区域自定义事件--接收值
// this.$bus.$on('abc',function(v){
// console.log("我被触发了",v)
// console.log(this)
// that.m=v
// })
//--------------
// console.log(this,111)
// 公共区域自定义事件--接收值
this.$bus.$on('abc',(v)=>{
console.log("我被触发了",v)
console.log(this)
this.m=v
})
}
}
</script>
- 3.在B组件中触发公共区域的自定义事件–触发传值
<template>
<div>
<button @click="fn">传值</button>
</div>
</template>
<script>
export default {
data(){
return {
msga:"a向b传值"
}
},
methods:{
fn(){
// 触发公共区域的自定义事件传值
this.$bus.$emit('abc',this.msga)
}
}
}
</script>
三、ref
- ref 被用来给元素或子组件注册引用信息
ref 注册在普通dom元素上 | ref加载子组件上 | ref加载循环渲染 |
---|---|---|
获取到的是dom元素 | 可以获取或使用组件的所有数据和方法 | 利用v-for和ref获取一组数组 |
- 利用v-for和ref获取一组数组
注意:
1:ref需要在dom渲染完成后才会有,使用的时候确保dom已经渲染完成,比如
mounted钩子函数中可以使用
2:ref如果是循环出来的,ref的值是一个数组,要拿到单个的ref只需要循环就可以了
<template>
<div>
<!--1 ref加在普通的dom元素上 -->
<h2 ref="myh2">成都</h2>
<input type="text" ref="myinput" />
<button @click="fn">获取h2</button>
<!--2 ref应用在循环渲染 -->
<ul>
<li ref="list" v-for="(item,index) in arr" :key="index">
{
{
item}}
</li>
</ul>
<button @click="fn1">获取li元素</button>
<!-- 3ref设置在子组件上 -->
<Myref ref="myref"></Myref>
<button @click="fn2">获取子组件</button>
</div>
</template>
<script>
import Myref from './components/Myref'
export default {
data(){
return {
arr:['aaa','bbb','cccc']
}
},
methods:{
fn(){
// 所有的ref的注册信息都会注册到组件的$refs对象上
console.log(this.$refs)
console.log(this.$refs.myh2.innerHTML)
},
fn1(){
// ref注册到循环渲染的元素上,得到的是一个数组[li,li,li]
console.log(this.$refs.list[0].innerHTML)
},
fn2(){
console.log(this.$refs.myref.msg)
this.$refs.myref.msg="hello 晋老师"
}