vue(2)

作者: 晚月川 | 来源:发表于2020-06-16 07:57 被阅读0次

Vue组件化开发

  • 组件化开发的思想
  • 组件的注册
  • 组件间的数据交互
  • 组件插槽的用法
  • Vue调试工具的用法

组件开发思想

  • 标准
  • 分治
  • 重用
  • 组合

组件化规范:Web Components(并非所有的浏览器都支持)

  • 我们希望尽可能多的重用代码
  • 自定义组件的方式不太容易(html、css和js)
  • 多次使用组件可能导致冲突

Web Components通过创建封装好功能的定制元素解决上述问题(Vue部分实现了上述规范)

组件注册

Vue.component('组件名称',{
    // 组件内容
    data: '组件数据',
    template: '组件模板内容'
})
<!-- 组件使用 -->
<div id="app">
    <h1>{{name}}</h1>
    <button-count></button-counter>
    <!-- 组件是可以重用的 -->
    <button-count></button-counter>
    <button-count></button-counter>
</div>
<script>
    // 定义一个名为 button-counter 的新组件
    Vue.component('button-counter', {
        data: function() {
            return {
                count: 0
            }
        },
        template: '<button v-on:click="count++">点击{{count}}次</button>'
    })
</script>

组件注册注意事项:

  1. data必须是一个函数 => 分析函数和普通对象的对比
  2. 组件模板内容必须是单个根元素 => 分析演示实例的效果
  3. 组件模板内容可以是模板字符串 => 模板字符串需要浏览器提供支持(ES6语法)
  4. 组建的命名方式
  • 短横线方式Vue.component('my-component',{ /*...*/ }
  • 驼峰式Vue.component('myComponent',{ /*...*/ }
  • 如果使用驼峰式命名组件,那么在使用组件的时候,只能在字符串模板中使用驼峰的方式命名组件,但是在普通的标签模板中,必须使用短横线的方式命名组件

局部组件注册

var ComponentA = { /* ... */ }
var ComponentB = { /* ... */ }
var ComponentC = { /* ... */ }
new Vue({
    el: '#app',
    components: {
        'component-a' :componentA,
        'component-b' :componentB,
        'component-c' :componentC
    }
})
// 局部组件只能在其父组件中使用

Vue调试工具

  1. 克隆仓库
  2. 安装依赖包
  3. 构建
  4. 打开Chrome扩展页面
  5. 选中开发者模式
  6. 加载已解压的扩展,选择shells/chrome

组件间的数据交互

  1. 父组件向子组件传值

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

      Vue.component('menu-item', {
          props: ['title'],
          template: '<div>{{title}}</div>'
      })
      
    • 父组件通过属性将值传递给子组件

      <menu-item title="来自父组件传递的数据"></menu-item>
      <menu-item :title="title"></menu-item>
      
    • props属性名规则

      • props中使用驼峰形式,模板中则需要使用短横线的形式
      • 字符串形式的模板中则没有这个限制
      <menu-item menu-title="hello"></menu-item>
      <script>
          Vue.component('menu-item', {
              // 在JavaScript中是驼峰式的
              props: ['menuTitle'],
              template: `<div>{{menuTitle}}`
          })
      </script>
      
      <div id="app">
          <h1>{{name}}</h1>
          <div>{{pmsg}}</div>
          <menu-item :menu-title="ptitle" content='hello'></menu-item>
      </div>
      <script>
          Vue.component('third-com', {
              props:['testTitle'],
              template:'<div>{{testTitle}}</div>'
          });
          Vue.component('menu-item', {
              props:['menuTitle'],
              template:'<div>{{menuTitle}}<third-com testTitle="hello"></third-com></div>'
          });
          let vm = new Vue({
              el:'#app',
              data:{
                  name:"myVue",
                  pmsg:'父组件的内容',
                  ptitle:'动态绑定的属性'
              },
              methods: {
      
          }
          });
      </script>
      
    • props属性值类型

      • 字符串 String
      • 数值 Number
      • 布尔值 Boolean
      • 数组 Array
      • 对象 Object
      <div id="app">
          <h1>{{name}}</h1>
          <div>{{pmsg}}</div>
          <!-- 不带引号为字符串类型 -->
          <menu-item :pstr="pstr" :pnum="13" :pboo="true" :parr="parr" :pobj="pobj"></menu-item>
      </div>
      <script>
          Vue.component('menu-item', {
              props: ['pstr','pnum','pboo','parr','pobj'],
              template:`
                  <div>
                      <div>{{pstr}}</div>
                      <div>{{12 + pnum}}</div>
                      <div>{{pboo}}</div>
                      <ul>
                          <li :key="index" v-for="(item,index) in parr">{{item}}</li>
                      </ul>
                      <div>
                          <span>{{pobj.name}}</span>
                          <span>{{pobj.age}}</span>
                          <span>{{pobj.sex}}</span>
                      </div>
                  </div>`
          });
          let vm = new Vue({
              el: '#app',
              data: {
                  name: "myVue",
                  pmsg: '父组件的内容',
                  pstr: 'hello',
                  parr:['苹果','香蕉','哈密瓜'],
                  pobj:{
                      name:'张三',
                      age:19,
                      sex:'男'
                  }
              },
              methods: {
      
              }
          });
      </script>
      
  2. 子组件向父组件传值

    • 子组件通过自定义事件向父组件传递消息
      <button v-on:click='$emit("enlarge-text")'>扩大字体</button>

    • 父组件监听子组件事件
      <menu-item v-on:enlarge-text='fontSize += 0.1'></menu-item>

      <div id="app">
          <h1>{{name}}</h1>
          <div :style="{fontSize: fontSize + 'px'}">{{pmsg}}</div>
          <menu-item @enlarge-text="handle"></menu-item>
      </div>
      <script>
      /* 
      子组件向父组件传递数据-基本用法
          props传递数据原则:单项数据绑定
      */
      Vue.component('menu-item', {
          template:`
              <div>
                  <button @click="$emit('enlarge-text')">扩大字体</button>
              </div>`
      });
      let vm = new Vue({
          el: '#app',
          data: {
              name: "myVue",
              pmsg: '父组件的内容',
              fontSize: 10
          },
          methods: {
              handle:function() {
                  // 扩大字体大小
                  this.fontSize+=10;
              }
          }
      });
      </script>
      
    • 子组件通过自定义事件向父组件传递信息
      <button v-on:click='$emit("enlarge-text", 0.1)'>扩大字体</button>

    • 父组件监听子组件事件
      <menu-item v-on:enlarge-text='fontSize += $event'></menu-item>

      <div id="app">
          <h1>{{name}}</h1>
          <div :style="{fontSize: fontSize + 'px'}">{{pmsg}}</div>
          <!-- 不带引号为字符串类型 -->
          <menu-item @enlarge-text="handle($event)"></menu-item>
      </div>
      <script>
          /* 
          子组件向父组件传递数据-基本用法
              props传递数据原则:单项数据绑定
          */
          Vue.component('menu-item', {
              template:`
                  <div>
                      <button @click="$emit('enlarge-text',5)">扩大字体</button>
                      <button @click="$emit('enlarge-text',-5)">减小字体</button>
                  </div>`
          });
          let vm = new Vue({
              el: '#app',
              data: {
                  name: "myVue",
                  pmsg: '父组件的内容',
                  fontSize: 10
              },
              methods: {
                  handle:function(val) {
                      // 扩大字体大小
                      this.fontSize+=val;
                  }
              }
          });
      </script>
      
  3. 非父子组件间传值(兄弟间组件传值)

    • 单独的事件中心管理组件间的通信 var eventHub = new Vue()

    • 监听事件与销毁事件

      eventHub.$on('add-todo', addTab)
      eventHub.off('add-todo')
      
    • 触发事件eventHub.$emit('add-todo', id)

    <div id="app">
        <h1>{{name}}</h1>
        <div>
            <button @click="handle">销毁事件</button>
        </div>
        <text-tom></text-tom>
        <text-jerry></text-jerry>
    </div>
    <script type="text/javascript">
        // 兄弟组件间数据传递
        // 提供事件中心
        var hub = new Vue();
        Vue.component('text-tom', {
            data: function () {
                return {
                    num: 0
                }
            },
            template: `
                <div>
                    <div>Tom:{{num}}</div>
                    <div>
                        <button @click="handle">点击</button>
                    </div>
                </div>`,
            methods: {
                handle: function () {
                    hub.$emit('jerry-event', 2)
                }
            },
            mounted: function () {
                // 监听事件
                hub.$on('tom-event', (val) => {
                    this.num += val;
                })
            }
        });
        Vue.component('text-jerry', {
            data: function () {
                return {
                    num: 0
                }
            },
            template: `
                <div>
                    <div>Jerry:{{num}}</div>
                    <div>
                        <button @click="handle">点击</button>
                    </div>
                </div>`,
            methods: {
                handle: function () {
                    // 触发兄弟组件的事件
                    hub.$emit('tom-event', 1)
                }
            },
            mounted: function () {
                // 监听事件
                hub.$on('jerry-event', (val) => {
                    this.num += val;
                })
            }
        });
        let vm = new Vue({
            el: '#app',
            data: {
                name: "myVue"
            },
            methods: {
                handle: function() {
                    hub.$off('tom-event');
                    hub.$off('jerry-event');
                }
            }
        });
    </script>
    

组件插槽

  • 父组件向子组件传递内容

插槽基本用法

  1. 插槽位置

    <div id="app">
        <h1>{{name}}</h1>
        <alert-box>有bug!</alert-box>
        <alert-box>有一个警告!</alert-box>
        <alert-box></alert-box>
    </div>
    <script>
        Vue.component('alert-box', {
            template: `
                <div class="demo-alert-box">
                    <strong>Error!</strong>
                    <slot></slot>
                </div>`
        })
        let vm = new Vue({
            el: '#app',
            data: {
                name: "myVue"
            },
            methods: {
    
            }
        });
    </script>
    
  2. 具名插槽用法

    <!-- 插槽定义 -->
    <div class="container">
        <header>
            <slot name="header"></slot>
        </header>
        <main>
            <slot></slot>
        </main>
        <footer>
            <slot name="footer"></slot>
        </footer>
    </div>
    <!-- 插槽内容 -->
    <base-layout>
        <h1 slot="header">标题内容</h1>
    
        <p>主要内容1</p>
        <p>主要内容2</p>
    
        <p slot="footer">底部内容</p>
    </base-layout>
    
    <div id="app">
        <h1>{{name}}</h1>
        <base-layout>
            <p slot="header">标题信息</p>
            <p>主要内容1</p>
            <p>主要内容2</p>
            <p slot="footer">底部信息</p>
        </base-layout>
        <base-layout>
            <template slot="header">
                <p slot="header">标题信息</p>
                <p slot="header">标题信息</p>
            </template>
            <p>主要内容1</p>
            <p>主要内容2</p>
            <template slot="footer">
                <p slot="header">尾部信息1</p>
                <p slot="header">尾部信息2</p>
            </template>
        </base-layout>
    </div>
    <script type="text/javascript">
        Vue.component('base-layout', {
            template: `
                <div>
                    <header>
                        <slot name="header"></slot>
                    </header>
                    <main>
                        <slot></slot>
                    </main>
                    <footer>
                        <slot name="footer"></slot>
                    </footer>
                </div>`
        });
        let vm = new Vue({
            el: '#app',
            data: {
                name: "myVue"
            },
            methods: {
    
            }
        });
    </script>
    
  3. 作用域插槽

  • 应用场景:父组件对子组件的内容进行加工处理

    <!-- 插槽定义 -->
    <ul>
        <li v-for="item in list" v-bind:key="item.id">
            <slot v-bind:item="item">
                {{item.name}}
            </slot>
        </li>
    </ul>
    <!-- 插槽内容 -->
    <fruit-list v-bind:list="list">
        <template slot-scope="slotProps">
            <strong v-if="slotProps.item.current">
                {{slotProps.item.text}}
            </strong>
        </template>
    </fruit-list>
    

相关文章

网友评论

      本文标题:vue(2)

      本文链接:https://www.haomeiwen.com/subject/jixlxktx.html