vue复习之组件基础,组件定义,父子相互传参,插槽,动态组件

本文参考自官方文档,并加入自己的理解和例子

两种组件的注册类型:全局注册局部注册
全局注册基本示例

// 定义一个名为 button-counter 的新组件
Vue.component('button-counter', {
     
  data: function () {
     
    return {
     
      count: 0
    }
  },
  template: ''
})

组件是可复用的 Vue 实例,且带有一个名字:在这个例子中是 ``。我们可以在一个通过 new Vue 创建的 Vue 根实例中,把这个组件作为自定义元素来使用:

<div id="app">
  <button-counter>button-counter>
div>
new Vue({ el: '#app' })

因为组件是可复用的 Vue 实例,所以它们与 new Vue 接收相同的选项,例如 datacomputedwatchmethods 以及生命周期钩子等。仅有的例外是像 el 这样根实例特有的选项。

data 必须是一个函数

局部注册定义在components属性内,在父组件的template使用

components: {
     
  navBarChild:{
     
   template:'

Child!!

'
} }

通过 Prop 向子组件传递数据

一个组件默认可以拥有任意数量的 prop,任何值都可以传递给任何 prop。能够在组件实例中访问这个值,就像访问 data 中的值一样。

Vue.component('blog-post', {
     
  props: ['title'],
  template: '

{ { title }}

'
})

一个 prop 被注册之后,你就可以像这样把数据作为一个自定义 attribute 传递进来:

<blog-post title="My journey with Vue">blog-post>

可以使用 v-bind 来动态传递 prop

<blog-post :title="某定义在data中的变量">blog-post>

每个组件必须只有一个根元素

监听子组件事件

父级组件可以像处理 native DOM 事件一样通过 v-on 监听子组件实例的任意事件

<blog-post
  ...
  @enlarge-text="postFontSize += 0.1"
>blog-post>

同时子组件可以通过调用内建的 $emit方法并传入事件名称来触发一个事件enlarge-text

<button @click="$emit('enlarge-text')">
  Enlarge text
button>

使用事件抛出一个值

<button v-on:click="$emit('enlarge-text', 0.1)">
  Enlarge text
button>

然后当在父级组件监听这个事件的时候,我们可以通过 $event 访问到被抛出的这个值:

<blog-post
  ...
  v-on:enlarge-text="postFontSize += $event"
>blog-post>

或者,如果这个事件处理函数是一个方法:

<blog-post
  ...
  v-on:enlarge-text="onEnlargeText"
>blog-post>

那么这个值将会作为第一个参数传入这个方法:

methods: {
     
  onEnlargeText: function (enlargeAmount) {
     
    this.postFontSize += enlargeAmount
  }
}

父子相互传参案例,画图加深理解
vue复习之组件基础,组件定义,父子相互传参,插槽,动态组件_第1张图片
props属性验证
Number,String,Boolean,Array,Object,Function,null(不限制)

html

<div id="app" :style="{
        fontSize:postFontSize+'em'}">
    
  <button-counter :title="a">button-counter>
  文章内容
    
  <button-enlarge @enlarge-text='enlargeFun'>button-enlarge>
  
  
 div>

js

// 全局定义,父向子传参
Vue.component('button-counter', {
     
   props: {
     title:String,},//可以进行属性验证
   data: function () {
     
   	return {
     
        count: 0
    }
},
template:''})

//改变父组件的东西,子触发父事件且传参
Vue.component('button-enlarge',{
     
  data:function(){
     
    return {
     
      size:0
    }
},
template:`
`
}) new Vue({ el: '#app', data: { a:1, postFontSize:1 }, methods:{ enlargeFun:function(size){ this.postFontSize +=size } } })

v-model的内在奥秘

<input v-model="myText">{
    {myText}}
上下效果相同
<input :value="myText" @input="myText = $event.target.value">{
    {myText}}


<input v-model.lazy="myTextLazy">{
    {myTextLazy}}
上下效果相同
<input :value="myTextLazy" @change="myTextLazy = $event.target.value">{
    {myTextLazy}}

当用在组件上时,v-model 则会这样:

Vue.component('model-input',{
     
   props:['value'],
   template:`
{ {value}}
`
})

父组件调用

<model-input :value="myText" @input="myText=$event">model-input>{
    {myText}}

一个组件上的 v-model

默认会利用名为 value 的 prop 和名为 input 的事件,但是像单选框、复选框等类型的输入控件可能会将 value attribute 用于不同的目的。model 选项可以用来避免这样的冲突:

  model: {
     
    prop: 'checked',
    event: 'change'
  },

slot插槽

通过插槽分发内容,和 HTML 元素一样,我们经常需要向一个组件传递内容,像这样:

<nav-bar>
	<button  slot="btn">触发button>
	<div slot="div">aaaadiv>
nav-bar>
可以利用Vue 自定义的 <slot> 元素,进行插入内容
Vue.component('navBar', {
     
  template: `
navBar
`
})

在这里插入图片描述
可以指定slot的名字,进行指定插槽
例如:

<nav-bar>
	<button  slot="btn">触发button>
	<div slot="div">aaaadiv>
nav-bar>
Vue.component('navBar', {
     
  template: `
navBar
`
})

在这里插入图片描述

## 动态组件
在不同组件之间进行动态切换是非常有用的
上述内容可以通过 Vue 的` `元素加一个特殊的 is attribute 来实现:
```html


在上述示例中,currentTabComponent 可以包括

  • 已注册组件的名字,
  • 一个组件的选项对象

请留意,这个 attribute 可以用于常规 HTML 元素,但这些元素将被视为组件,这意味着所有的 attribute 都会作为 DOM attribute 被绑定。对于像 value 这样的 property,若想让其如预期般工作,你需要使用 .prop 修饰器。

下面例子,参考自:https://www.cnblogs.com/xiaohuochai/p/7395694.html

让多个组件使用同一个挂载点,并动态切换,这就是动态组件。
两种写法:

  1. 通过使用保留的 元素,动态地绑定到它的 is 特性,可以实现动态组件
<div id="example">
  <button @click="change">切换页面button>
  <component :is="currentView">component>
div>
<script>
var home = {
      template:'
我是主页
'
}; var post = { template:'
我是提交页
'
}; var archive = { template:'
我是存档页
'
}; new Vue({ el: '#example', components: { //局部组件 home, post, archive, }, data:{ index:0, arr:['home','post','archive'], }, computed:{ currentView(){ return this.arr[this.index]; } }, methods:{ change(){ this.index = (++this.index)%3; } } })
script>
  1. 也可以直接绑定到组件对象上
<div id="example">
  <button @click="change">切换页面button>
  <component :is="currentView">component>
div>
<script>
new Vue({
      
  el: '#example',
  data:{
      
    index:0,
    arr:[
      {
      template:`
我是主页
`
}, { template:`
我是提交页
`
}, { template:`
我是存档页
`
} ], }, computed:{ currentView(){ return this.arr[this.index]; } }, methods:{ change(){ this.index = (++this.index)%3; } } })
script>

注意:动态组件,切换的时候是删掉原来组件,而不是隐藏,要保持原来的状态,避免重新渲染,用keep-alive包裹

<keep-alive>
     <component :is="who">component>
keep-alive>

解析 DOM 模板时的注意事项

有些 HTML 元素,诸如

      、 和