Vue 组件化开发

全局组件注册

Vue.component('first-component', {
  data: function () {
    return {
      count: 0
    }
  },
  template: '<button @click="count++">{{ count }}</button>'
})
  • data 必须是一个函数

  • 组件模板内容必须是单个根元素

  • 组件模板内容可以是模板字符串

  • 全局组件可以嵌套全局组件

  • 组件命名方式

    • Vue.component('first-component', {/* .... */})
      
    • // 普通标签模板中不能使用驼峰, 只能在template中使用驼峰方式
      Vue.component('firstComponent', {/* .... */})
      

局部组件注册

局部注册的组件只能在父组件中使用 ;

var vm = new Vue({
  components: {
    'hello-world': {
      data: function () {
        return {
          msg: 'hello world'
        }
      },
      template: '<div>{{ msg }}</div>'
    }
  }
})

父组件向子组件传值

props 传递数据原则 : 单向数据流

组件内部通过 props 接收传递过来的值

Vue.component('son-com', {
	props: ['msg', 'parentMsg']
    template: '<div>{{msg + "---" + parentMsg}}</div>'
})

父组件通过属性将值传递给子组件

<son-com msg="父组件的值" :parent-msg="bind绑定的父组件的值"></son-com>

props 属性名规则

  • 在props中使用驼峰形式, 模板中需要使用短横线的形式 ; html 对大小写的不敏感的
  • 字符串中没有这个限制

props 传递类型

<div id="app">
  <son-com
    :str="pstr"
    :num="pnum" <!-- 注意如果不用 v-bind 则获取不到准确的属性值 -->
    :boolean="pboolean"
    :arr="parr"
    :obj="pobj"
  >
  </son-com>
</div>
Vue.component('son-com', {
  props: ['str', 'num', 'boolean', 'arr', 'obj'],
  template: `
    <div>
      <div>{{ str }}</div>
      <div>{{ num }}</div>
      <div>{{ boolean }}</div>
      <ul>
        <li :key="index" v-for="(item, index) in arr">{{ item }}</li>
      </ul>
      <div>
        <span>{{ obj.name }}</span>
        <span>{{ obj.age }}</span>
      </div>
    </div>
  `
})
var vm = new Vue({
  el: '#app',
  data: {
    pstr: 'hello Vue',
    pnum: 12,
    pboolean: true,
    parr: ['apple', 'banner', 'orange'],
    pobj: {name: 'zs', age: 22}
  }
})

子组件向父组件传值

子组件通过自定义事件向父组件传值 $emit()

Vue.component('son-com', {
  template: `
    <div>
      <button @click="$emit('parent')">点击放大父组件字体</button>
      传值从第二个参数开始
	  <button @click="$emit('parent', 10)">点击放大父组件字体</button>
    </div>
  `
})

父组件监听子组件事件

<div id="app">
  <div>父组件</div>
  <son-com @parent="handle"></son-com>
  <!-- 接收值为固定 $event-->
  <son-com @parent="handle($event)"></son-com>
</div>
var vm = new Vue({
  el: '#app',
  data: {
    font: 10
  },
  methods: {
    handle: function (val) {
      this.font += 5
      this.font += val // 此时的val就是 子组件传递过来的值
    }
  },
})

非父子组件传值

单独的事件中心管理组件之间的通信

// 创建事件中心
var hub = new Vue()
// 在 mounted 中监听事件
hub.$on('eventName', fn)
hub.$off('eventName') // 销毁事件
// 在 methods 中处理事件
hub.$emit('eventName', param)

兄弟组件传值示例

component 1 修改 component 2 的值

// component - 1
Vue.component('com-one', {
  template: `
	<div>
      1, 绑定事件
	  <button @click="handle">修改com-two的数据</button>
	</div>
  `,
  methods:{
    // 2, 定义事件名称, 传递过去一个数据
    handle: function () {
      bus.$emit('event', 'com-one自身的数据')
    }
  }
})
// component - 2
Vue.component('com-two', {
  data() {
    return {
      msg: '我是 com-two'
    }
  },
  template: `
	<div>
	  <button>{{ msg }}</button>
	</div>
  `,
  mounted() {
     // 在mounted钩子中 监听 事件名, 并且接受下来进行操作
     bus.$on('event', el => {
        this.msg = el
     })
  }
})

组件插槽

<tmp-com>
  <!-- 只能匹配一个标签 -->
  <p slot="header">程序错误</p>
  <div>我是没有匹配的内容</div>
  <!-- 可以匹配多个标签 -->
  <template slot="footer">
    <p>匹配页脚一次</p>
    <p>匹配页脚两次</p>
  </template>
</tmp-com>
Vue.component('tmp-com', {
  template: `
    <div>
      <header>
        <slot name="header"></slot>
      </header>
      <div>
        如果上面没有匹配到对应的标签就会展示默认内容
        <slot></slot>
      </div>
      <footer>
        <slot name="footer"></slot>
      </footer>
    </div>
  `
})

作用域插槽

应用场景 : 父组件对子组件的数据进行加工处理

<fruit-list :fruit="fruit">
  <!-- 组件内部用 template 特殊语法 slot-scope 特殊属性接收  -->
  <template slot-scope="slotProps">
    <!-- {{ slotProps.info }} 就是下面组件中的 item 可以再父组件中进行相应的操作-->
    <strong v-if="slotProps.info.id == 2" class="current">{{ slotProps.info.name }}</strong>
    <span v-else="slotProps.info.name">{{ slotProps.info.name }}</span>
  </template>
</fruit-list>
Vue.component('fruit-list', {
  props: ['fruit'],
  template: `
    <div>
      <ul>
        <li 
          :key="item.id" 
          v-for="item in fruit"
        >
		slot 包裹内容 同时绑定内容 info为自定义, item 为for循环的item
        <slot :info="item">{{ item.name }}</slot>
        </li>
      </ul>
    </div>
  `
})
posted @ 2020-05-13 00:07  计算机相关人员  阅读(247)  评论(0编辑  收藏  举报