浅谈Vue组件

1. 什么是组件

image.png

组件化就是把页面拆分成一块块的,后期维护很简单
组件其实也是vue的实例,组件是可以反复使用的vue实例

  • 全局注册组件
    就是把组件用Vue.component()注册
<body>
  <div id="app">
    <!-- 3、使用组件 -->
    <my-header></my-header>
  </div>
</body>
<script src="vue.js"></script>
<script>
  // 全局注册组件

  // 1、定义组件
  const MyHeader = { 
    template: `<header>头部</header>`, 
  }

  // 2、全局注册组件
  Vue.component('my-header', MyHeader)

  new Vue({
    el: '#app'
  })
</script>
  • 局部注册组件
    就是把组件注册在某个Vue实例中,用components:{}注册
<body>
  <div id="app">
    <!-- 3、使用组件 -->
    <my-header></my-header>
  </div>
</body>
<script src="vue.js"></script>
<script>
  // 局部注册组件
  // 1、定义组件
  const MyHeader = { 
    template: `<header>头部</header>`, 
  }
  new Vue({
    el: '#app',
    // 2、局部注册组件
    components: {
      'my-header': MyHeader
    }
  })
</script>

2. 组件间的传值

1. 父组件给子组件传值
  • 父组件在调用子组件的地方需要添加一个属性<my-content test = "测试"/>
  • 属性的值”测试”就是你要传递给子组件的值
  • 在子组件定义的地方添加一个选项叫props:{}
  • 在props里放父组件传递的属性名,也就是test就可以了,要注意的是,如果父组件传递给子组件的值是变量,Number或者布尔值就需要v-bind了!props内存放值有两种方式
  • 第一种:数组:props:[‘test’],之后就可以在子组件中使用了
  • 第二种:对象:props:{test:String},这是写法一用来验证传递数据的有效性,因为父子组件可能不是一个人写的,如果数据类型不对,就会警告,可以及时调整。
  • Props:{test:{type:String,default:’默认值’}}这是第二种写法,既要验证数据类型也要设置默认值,如果默认值是对象或者函数,则默认值需要时一个有返回值的函数function () {return {}}
<body>
  <div id="app">
    <!-- <my-content test = "测试" :count="100" :flag="true" :tip="tip"/> -->
    <my-content :count="100" :flag="true" :tip="tip"/>
  </div>
</body>
<template id="content">
  <div>
    我这里是内容区域 --- {{ test }} -- {{ count }} --- {{ flag }} --- {{ tip }}
  </div>
</template>
<script src="vue.js"></script>
<script>
  // 组件的名称不能和模板的id同名
  const Content = {
    template: '#content',
    // props: ['test', 'count', 'flag', 'tip']
    // props: {
    //   test: String,
    //   count: Number,
    //   flag: Boolean,
    //   tip: String
    // }
    props: {
      test: {
        type: String,
        default: '测试数据了' // 如果父组件有这个属性,那么就用父组件的值,没有这个属性,直接使用这个值
      }
    }
  }
  new Vue({
    el: '#app',
    data: {
      tip: '提示'
    },
    components: {
      'my-content': Content
    }
  })
</script>
2. 子组件给父组件传值
  • 子组件给父组件传值时,需要在父组件调用子组件的地方,给它绑定一个自定义事件,事件后面不要加(),例:<my-content @myevent="getData"/>
  • 在父组件选项methods中使用这个getData(val){},其中参数val是默认传递的,传递的就是子组件传递给父组件的值
  • 而在子组件如何传递呢?如下!
  • 在子组件种。你可以通过生命周期的钩子函数,也可以是组件自己的事件去触发父组件中的自定义事件myevent,使用固定语法emit来传递例:this.$emit('myevent', 10000),这样就把名字为myevent的参数名,参数为10000的整个值广播出去了,父组件只要接受myevent就可以了!
<body>
  <div id="app">
    <my-content @myevent="getData"/>
  </div>
</body>
<template id="content">
  <div>
    我这里是内容区域
  </div>
</template>
<script src="vue.js"></script>
<script>
  /**
   * 父组件调用子组件的地方,给他绑定一个自定义的事件, 事件不要加()
   *      <my-content @myevent="getData"/>
   * 在父组件选项methods中实现此事件,默认参数为你将从子组件得到的值
   *    methods: {
          getData (val) { // val为从子组件中获取到的值
            console.log(val)
          }
        },
      
      在子组件中,可以是生命周期钩子函数,也可以是组件自己的事件 去 触发 父组件中的自定义事件
          this.$emit('myevent', 10000)
   **/
  const Content = {
    template: '#content',
    mounted () {
      this.$emit('myevent', 10000)
    }
  }

  new Vue({
    el: '#app',
    data: {},
    methods: {
      getData (val) { // val为从子组件中获取到的值
        console.log(val)
      }
    },
    components: {
      'my-content': Content
    }
  })
</script>
3. 非父子组件间传值
  • 中央事件总线传值const bus = new Vue()他就类似于一个快递员的身份,需要确保数据有人接受的情况下,就可以接受参数然后传递参数给需要的人!
  • 第一步:给需要这个参数的组件,定义bus.$on(‘参数名’,(val)={对收到的val做手脚}),一般写在钩子函数mounted中。还要注意这里尽量使用箭头函数避免this指向出现问题
  • 第二步:在确定了有接受的组件时,就可以给要发送的组件设置了!在发送参数的组建中的methods中添加一个自定义函数,在里面定义bus.emit(‘参数名’,参数),当触发了bus.emit时,像外广播了一个参数名,然后另一个组件通过bus.$on接收到了参数名相同的参数值,这样就形成了非父子组件之间的值传递
<body>
  <div id="app">
    <my-list></my-list>
    <my-count></my-count>
  </div>
</body>
<template id="list">
  <ul>
    <li>111<button @click="add">+1</button></li>
    <li>222<button @click="add">+1</button></li>
    <li>333<button @click="add">+1</button></li>
    <li>444<button @click="add">+1</button></li>
    <li>555<button @click="add">+1</button></li>
  </ul>
</template>
<template id="count">
  <div>
    总量是:{{ num }}
  </div>
</template>
<script src="vue.js"></script>
<script>
  /**
   *  非父子组件传值 ---- 兄弟组件传值                   (邮差与信的故事)
   *  ------------------ 中央事件总线传值  1. const bus = new Vue()
   * 
   *  先要确保 收信 的那个人是存在的
   *  然后写信的人 写信 给邮差
   *  邮差给送
   * 
   *  // 此处一定要注意this指向,可以使用 => 
   *  2.在接收端通过 bus.$on('收信信号', function (val) {
   * 
   *  })
   * 
   *  3.在发送端通过 bus.$emit('收信信号', val)
   * */
const bus = new Vue()

const List = {
  template: '#list',
  methods: {
    add () {
      bus.$emit('count-event', 1)
    }
  }
}
const Count = {
  template: '#count',
  data () {
    return {
      num: 0
    }
  },
  mounted () { // 一般情况下接收都使用 生命周期钩子函数
    bus.$on('count-event', (val) => { // 此处一定要注意this指向,可以使用 =>
      console.log(val)
      this.num += val
    })
  }
}
new Vue({
  el: '#app',
  components: {
    'my-list': List,
    'my-count': Count
  }
})
</script>
4. 动态组件

<component is="组件名称"></component>

概述:让当前画面在几个组件中来回切换,类似你的手机屏幕,同一个屏幕可以打开不同的app显示不同的内容。

使用:一般在页面只写一个类似于<component :is="tem"></component>的组件,页面有按钮操控tem在data中的值,一旦改变值,在components中注册名称为改变得值得组件,就可以在页面中显示出所对应的组件了。

但是随之的问题就出现了,每次切换回前一个组件时,上次的操作就会被清除,所以需要用keep-alive把components包裹起来

keep-alive:保留组件的状态,避免组件的重新渲染 --- 类似于手机软件使用中按了home键之后应用程序的状态
但是有些时候就是需要切换回页面数据清除,所以只需要给keep-alive添加一个include属性就可以了,后面的属性值是在组件注册时定义的名称name的值。添加上的组件就会保存之前的信息,而没有添加的组件name就会数据消失

动态组件生命周期钩子函数

每个组件都会有两个钩子函数activated()---正在用的,deactivated()---后台的,如果该组件在keep-alive的include内,那么该组件再被切换时,会触发deactivated()钩子函数类似于后台运行,在使用时会触发activated()钩子函数

<body>
  <div id="app">
    <button @click="tem='my-a'">AAA</button>
    <button @click="tem='my-b'">BBB</button>
    <button @click="tem='my-c'">CCC</button>
    <keep-alive include="a,b">
      <component :is="tem"></component>
    </keep-alive>
    
  </div>
</body>
<template id="acom">
  <div>
    <input type="text" placeholder="a组件">
  </div>
</template>
<template id="bcom">
  <div>
    <input type="text" placeholder="b组件">
  </div>
</template>
<template id="ccom">
  <div>
    <input type="text" placeholder="c组件">
  </div>
</template>
<script src="vue.js"></script>
<script>
  /**
   * keep-alive 
   *  保留组件的状态,避免组件的重新渲染  ---  类似于手机软件使用中按了home键之后应用程序的状态
   *  添加include 可以 只给部分组件保留状态,需要定义组件时添加name属性
   * 
   * 每个组件都会有 两个生命周期钩子函数
   *    activated()     正在用的
   *    deactivated()   后台的
   * */
const Acom = {
  name: 'a',
  template: '#acom',
  activated () {
    console.log(' a 正在被使用')
  },
  deactivated () {
    console.log(' a 被雪藏了')
  }
}
const Bcom = {
  name: 'b',
  template: '#bcom',
  activated () {
    console.log(' b 正在被使用')
  },
  deactivated () {
    console.log(' b 被雪藏了')
  }
}
const Ccom = {
  template: '#ccom',
  activated () {
    console.log(' c 正在被使用')
  },
  deactivated () {
    console.log(' c 被雪藏了')
  }
}

new Vue({
  el: '#app',
  data: {
    tem: 'my-a'
  },
  components: {
    'my-a': Acom,
    'my-b': Bcom,
    'my-c': Ccom
  }
})
</script>
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 组件(Component)是Vue.js最核心的功能,也是整个架构设计最精彩的地方,当然也是最难掌握的。...
    六个周阅读 10,936评论 0 32
  • Vue 实例 属性和方法 每个 Vue 实例都会代理其 data 对象里所有的属性:var data = { a:...
    云之外阅读 6,666评论 0 6
  • 40、React 什么是React?React 是一个用于构建用户界面的框架(采用的是MVC模式):集中处理VIE...
    萌妹撒阅读 4,693评论 0 1
  • 一、了解Vue.js 1.1.1 Vue.js是什么? 简单小巧、渐进式、功能强大的技术栈 1.1.2 为什么学习...
    蔡华鹏阅读 8,654评论 0 3
  • 前言 开发一个React应用,更多的是在编写组件,而React组件最小的单位就是React元素,编写组件的最大的好...
    itclanCoder阅读 4,884评论 0 1