说到自定义组件,我们先来了解下什么是组件。

组件
组件传值

组件

组件(Component)是 Vue.js 最强大的功能之一。组件可以扩展 HTML 元素,封装可重用的代码。在较高层面上,组件是自定义元素, Vue.js 的编译器为它添加特殊功能。在有些情况下,组件也可以是原生 HTML 元素的形式,以 is 特性扩展。

使用组件
想要使用组件,就需要先注册一个组件。而组件又分为全局组件和局部组件。

全局注册

到目前为止,我们只用过 Vue.component 来创建组件:

Vue.component('my-component-name', {
  // ... 选项 ...
})

这些组件是全局注册的。也就是说它们在注册之后可以用在任何新创建的 Vue 根实例 (new Vue) 的模板中。比如:

Vue.component('component-a', { /* ... */ })
Vue.component('component-b', { /* ... */ })
Vue.component('component-c', { /* ... */ })

new Vue({ el: '#app' })
<div id="app">
  <component-a></component-a>
  <component-b></component-b>
  <component-c></component-c>
</div>

在所有子组件中也是如此,也就是说这三个组件在各自内部也都可以相互使用。

局部注册

全局注册往往是不够理想的。比如,如果你使用一个像 webpack 这样的构建系统,全局注册所有的组件意味着即便你已经不再使用一个组件了,它仍然会被包含在你最终的构建结果中。这造成了用户下载的 JavaScript 的无谓的增加。

在这些情况下,你可以通过一个普通的 JavaScript 对象来定义组件:

var ComponentA = { /* ... */ }
var ComponentB = { /* ... */ }
var ComponentC = { /* ... */ }

然后在 components 选项中定义你想要使用的组件:

new Vue({
  el: '#app',
  components: {
    'component-a': ComponentA,
    'component-b': ComponentB
  }
})

对于 components 对象中的每个属性来说,其属性名就是自定义元素的名字,其属性值就是这个组件的选项对象。

注意局部注册的组件在其子组件中不可用。

data必须是一个函数

当我们定义这个 <button-counter> 组件时,你可能会发现它的 data 并不是像这样直接提供一个对象:

data: {
  count: 0
}

取而代之的是,一个组件的 data 选项必须是一个函数,因此每个实例可以维护一份被返回对象的独立的拷贝:

data: function () {
  return {
    count: 0
  }
}

如果 Vue 没有这条规则,点击一个按钮就可能会影响到其它所有实例,即点击一个按钮,其它按钮出现同样的效果。

Prop

Prop类型

到这里,我们只看到了以字符串数组形式列出的 prop:

props: ['title', 'likes', 'isPublished', 'commentIds', 'author']

但是,通常你希望每个 prop 都有指定的值类型。这时,你可以以对象形式列出 prop,这些属性的名称和值分别是 prop 各自的名称和类型:

props: {
  title: String,
  likes: Number,
  isPublished: Boolean,
  commentIds: Array,
  author: Object,
  callback: Function,
  contactsPromise: Promise // or any other constructor
}

这不仅为你的组件提供了文档,还会在它们遇到错误的类型时从浏览器的 JavaScript 控制台提示用户。

Prop验证

我们可以为组件的 prop 指定验证要求,例如你知道的这些类型。如果有一个需求没有被满足,则 Vue 会在浏览器控制台中警告你。这在开发一个会被别人用到的组件时尤其有帮助。

为了定制 prop 的验证方式,你可以为 props 中的值提供一个带有验证需求的对象,而不是一个字符串数组。例如:

Vue.component('my-component', {
  props: {
    // 基础的类型检查 (`null` 和 `undefined` 会通过任何类型验证)
    propA: Number,
    // 多个可能的类型
    propB: [String, Number],
    // 必填的字符串
    propC: {
      type: String,
      required: true
    },
    // 带有默认值的数字
    propD: {
      type: Number,
      default: 100
    },
    // 带有默认值的对象
    propE: {
      type: Object,
      // 对象或数组默认值必须从一个工厂函数获取
      default: function () {
        return { message: 'hello' }
      }
    },
    // 自定义验证函数
    propF: {
      validator: function (value) {
        // 这个值必须匹配下列字符串中的一个
        return ['success', 'warning', 'danger'].indexOf(value) !== -1
      }
    }
  }
})

当 prop 验证失败的时候,(开发环境构建版本的) Vue 将会产生一个控制台的警告。

template

template属性

template组件的模板html,属性值拼接字符串
template中可以调用简单的可以直接返回的一元运算符,并且能直接返回数据的,也可以调用js的全局方法比如,Date.now(),但是不能调用自己在全局定义的变量

template标签
template标签,HTML5提供的新标签,更加规范和语义化 ;
可以把列表项放入template标签中,然后进行批量渲染;
在vue中template节点在html生成的时候不会显示出来 ;
可以使用v-for把想要多次出现的内容重复出现,却不会出现<template></template>标签。

<template v-for="i in 5">
    <h5>我是一个h5标签</h5>
    <p>我是一个p标签</p>
</template>

组件传值

对于组件传值,有父组件向子组件传值、子组件向父组件传值、非相关组件之间传值。

1. 父组件向子组件传值

父组件向子组件传值 ,使用props

父组件部分:Parent.vue

这是父组件
**子组件部分:Child.vue**
<template>
  <div>
    <ul>
      <li v-for="(item,index) in nameList" :key="index">{{item.name}}</li>
    </ul>
  </div>
</template>
<script>
  export default {
    props: ["nameList"]
  };
</script>

2. 子组件向父组件传值

子组件向父组件传值 ,使用事件派发 ($emit)

父组件部分:Parent.vue

 <template>
	<div>
		<div>这是父组件</div>
		<child :name-list='names' @emitData='getData'></child>  
	</div>
</template>
<script>
    import child from './child.vue'
    export default {
		components:{
			child
		},
		data(){
			return{
				names:[
					{name:'柯南'},
					{name:'小兰'},
					{name:'工藤新一'}
				]
			}
		},
		methods:{
			getData(data){
				console.log(data); //123
			}
		}
    }
</script>

子组件部分:Child.vue

<template>
    <div>
        <ul>
            <li v-for='(item,index) in nameList' :key='index'>{{item.name}}</li>
        </ul>
        <Button @click='toParent'>点击我</Button>
    </div>
</template>
<script>
    export default {
        props:['nameList'],
        methods:{
            toParent(){
                this.$emit('emitData',123)
        }
      }
    }
</script>

3. 非相关组件之间传值

非相关组件之间传值,使用事件总线(Bus)
如何实现非父子组件间的通信,可以通过实例一个vue实例Bus作为媒介,要相互通信的兄弟组件之中,都引入Bus,之后通过分别调用Bus事件触发和监听来实现组件之间的通信和参数传递。

首先需要在任意地方添加一个bus.js

    import Vue from 'vue'
    export default new Vue;

在需要通信的组件都引入Bus.js    

如果你的bus.js是自定义一个bus的文件那from后面就改成你的所放的位置

    import Bus from './bus.js'

 接下来就是要组件通信了

 添加一个 触发 #emit的事件按钮
<template>
    <div id="emit">
        <button @click="bus">按钮</button>
    </div>
 </template> 

import Bus from './bus.js' 
export default { 
    data() {
        return {
            message: ''"
        }
     },
  methods: {
       bus () {
          Bus.$emit('msg', '我要传给兄弟们组件,你收到没有')
       }
    }
}

打开要和$emit通信的另外一个组件 添加

import Bus from './bus.js'

在钩子函数中监听msg事件

<template>
    <div id="on">
            <p>{{message}}</p>
    </div>
</template>

import Bus from './bus.js'
export default {
    data() {
      return {
        message:  ''
      }
    },
    mounted() {
    let self = this
       Bus.$on('msg', (e) => {
         self.message = e
     console.log(`传来的数据是:${e}`)
       })
     }
   }

最后p会显示来自$emit传来的信息

Logo

前往低代码交流专区

更多推荐