vue基础学习之组件化开发和注意事项

组件化开发:就是把一类功能的元素组合到一起,将css(样式)/js(功能)/html(结构)包装到一起,供后续复用

Vue组件注册语法:

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

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

<div id="app">
  <button-counter>button-counter>
div>

例如:


<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Documenttitle>
head>

<body>
    <div id="app">
        <compiles>compiles>
    div>
body>
<script src="./js/vue.js">script>
<script>
    Vue.component('compiles', {
        data: () => {
            return {
                sum: 0
            }
        },
        template: ''
    })
    var vm = new Vue({
        el: '#app'
    })
script>

html>

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

组件注册注意事项:

  • data必须是函数,并且返回一个对象
    • 因为我们的组件定义出来后,是可能被多次使用的,如果是一个对象,我们知道,对象是属于复杂数据类型,在内存中是一小块内存(栈)指向一大块内存(堆),那么在复用时,多个组件实例之间的data是共享的,也就是说会互相影响,为了避免这个问题,必须使用函数,每次返回一个新的对象,就能保证每个组件实例有自己独立的data数据,互不影响
  • template必须只有一个根元素包裹,我们惯用的做法就是用一个div包裹所有元素
  • template优先用模板字符串(后面我们学了单文件组件之后,就不需要关心了)
  • 组件在命名时使用大驼峰命名法(和我们之后学习的单文件组件配套,如:HelloWorld.vue),但是在html中需要使用短横线的方式,如:
  • 默认情况下,组件内不可以使用父组件中的data数据(父子组件之间的作用域不同)
    注册局部组件:
new Vue({
  el: '#app',
  components: {
    HelloWorld: {
      data: () => ({ }),
      template: ``
    }
  }
})
  • 注意:局部组件只能在注册它的父组件的HTML模板中使用,其他任何地方都不能用
  • 对于全局组件来说:组件的父子关系,在注册组件时是不能确定的,在写HTML结构时才能确定(看的就是HTML结构),比如:A组件写在B组件的HTML模板中,那么A组件就是B组件的子组件

组件之间的数据交互:
通过 Prop 向子组件传递数据
Prop 是你可以在组件上注册的一些自定义属性。当一个值传递给一个 prop 属性 的时候,它就变成了那个组件实例的一个属性。为了给组件传递一个标题,我们可以用一个 props 选项将其包含在该组件可接受的 prop 列表中:

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

{{ title }}

'
})
<blog-post title="My journey with Vue">blog-post>
<blog-post title="Blogging with Vue">blog-post>
<blog-post title="Why Vue is so fun">blog-post>

补充说明:

  • props在定义时使用小驼峰命名法,和组件的命名保持一致
  • props在使用时:
    • JS中或Vue的模板语法中用小驼峰
    • 普通HTML中用短横线

props在定义时,可以指定固定的类型

Vue.component('User', {
  props: {
    name: String,
    age: {
      type: Number,
      default: 18, // 默认值
      required: true, // 是否必传
    },
    isMarry: Boolean, // 这个布尔值有点特殊,只要你在HTML中加了这个属性,就是true,反之false
  },
})

// 在HTML中使用时
// 

子向父传值:

  • 单向数据流:不能直接在组件中修改父组件传递过来的数据(这是一个开发规范,并不是语法要求,这个规范是我们的老猿惨痛的教训总结出来的),这是为了统一管理我们的数据变更,不然,当有多个子组件并且业务复杂度到达一定程度时,就不会知道到底是那个儿子改了我的数据?我的数据时通过怎样的逻辑修改的?当项目业务功能逐渐复杂时,将难以维护

鉴于存在单向数据流的规范,我们子组件向父组件进行数据交互时,就不能直接操作,需要借助事件机制来通知父组件,让父组件自己操作自己的数据:

  • 子组件触发事件:vm. e m i t ( ′ 自 定 义 事 件 名 称 ′ ) , 调 用 v m . emit('自定义事件名称'),调用vm. emit()vm.emit方法可以触发自定义事件
  • 父组件监听事件:,跟我们监听@click="onClick()"是一个意思

范例(带事件参数):


<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Documenttitle>
head>

<body>

  <div id="app">

    <user-name-input @name-send="onNameSend($event)">user-name-input>
    <br>
    {{ msg }}
  div>


  <script src="./js/vue.js">script>
  <script>


    Vue.component('UserNameInput', {
      data: () => ({ name: '' }),
      methods: {
        send() {
          // 触发自定义事件,用来通知父组件
          this.$emit('name-send', this.name)
          // 如果需要传递多个数据,可以使用数据或对象的形式
          // this.$emit('name-send', [this.name, 'hehe', 123, 456])
        }
      },
      template: `
        
`
, }) new Vue({ el: '#app', data: { msg: '', }, methods: { onNameSend(eventData) { console.log(' 子组件 触发了 name-send 事件', eventData); this.msg = `hello, ${eventData} ~` } } })
script> body> html>

补充说明:

  • e v e n t 在 标 准 的 D O M 事 件 中 是 标 准 的 事 件 对 象 , 在 通 过 event在标准的DOM事件中是标准的事件对象,在通过 eventDOMemit触发的自定义事件中是事件数据
  • $emit(‘自定义事件类型’, 事件数据)只能携带一个事件数据,如果想要传递多个,怎么办?用数据或对象即可

兄弟或(祖孙)组件传值:

  • 兄弟之间传递数据需要借助于事件中心,通过事件中心传递数据
  • 提供事件中心 var hub = new Vue()
  • 传递数据方,通过一个事件触发hub.$emit(方法名,传递的数据)
  • 接收数据方,通过mounted(){} 钩子中 触发hub.$on()方法名
  • 销毁事件 通过hub.$off()方法名销毁之后无法进行传递数据
 <div id="app">
    <div>父组件div>
    <div>
      <button @click='handle'>销毁事件button>
    div>
    <test-tom>test-tom>
    <test-jerry>test-jerry>
  div>
  <script type="text/javascript" src="js/vue.js">script>
  <script type="text/javascript">
    /*
      兄弟组件之间数据传递
    */
    //1、 提供事件中心
    var hub = new Vue();

    Vue.component('test-tom', {
      data: function(){
        return {
          num: 0
        }
      },
      template: `
        
TOM:{{num}}
`
, methods: { handle: function(){ //2、传递数据方,通过一个事件触发hub.$emit(方法名,传递的数据) 触发兄弟组件的事件 hub.$emit('jerry-event', 2); } }, mounted: function() { // 3、接收数据方,通过mounted(){} 钩子中 触发hub.$on(方法名 hub.$on('tom-event', (val) => { this.num += val; }); } }); Vue.component('test-jerry', { data: function(){ return { num: 0 } }, template: `
JERRY:{{num}}
`
, methods: { handle: function(){ //2、传递数据方,通过一个事件触发hub.$emit(方法名,传递的数据) 触发兄弟组件的事件 hub.$emit('tom-event', 1); } }, mounted: function() { // 3、接收数据方,通过mounted(){} 钩子中 触发hub.$on()方法名 hub.$on('jerry-event', (val) => { this.num += val; }); } }); var vm = new Vue({ el: '#app', data: { }, methods: { handle: function(){ //4、销毁事件 通过hub.$off()方法名销毁之后无法进行传递数据 hub.$off('tom-event'); hub.$off('jerry-event'); } } });
script>

你可能感兴趣的:(vue学习,vue.js,javascript,es6)