Vue 框架学习(七) 组件化开发

一、组件通信

(一)传值(两结合使用详见案例)

  1、父传子:props(注意4个名字两两成对)

父组件:使用绑定把值传给子组件

子组件:通过props获取父组件传入的值(可以进行类型限制或默认值)

<body>
  <div id="app">
    <!-- 只能有一个root对象,所以数据的使用必须在一个div里面 -->
    <cpn :cmovies="moviese" :cmessage="message"></cpn>
  </div>

  <template id="cpn">
    <div>
      <ul>
        <li v-for="movie in cmovies">
          {{movie}}
        </li>
      </ul>
      <h2>{{cmessage}}</h2>
    </div>
  </template>

  <script>
    // 父传子: props
    const cpn = {
      template: '#cpn',
      // props: ['cmovies', 'cmessage'],
      props: {
        // 类型限制
        // cmovies: Array,
        // cmessage: String

        // 提供默认值,以及毕传值,数组不能传空数组
        cmovies: {
          type: Array,
          default: ['Default', 'Default'],
        },
        cmessage: {
          type: String,
          default: 'Default',
          request: true,
        }
      },
      data() {
        return {}
      },
    }

    //创建Vue实例,得到 ViewModel
    const app = new Vue({
      el: '#app',
      data: {
        message: 'Smallstars',
        moviese: ['海王', '火影']
      },
      methods: {},
      computed: {},
      components: {
        cpn
      },
    });
  </script>
</body>
View Code

 

  2、子传父

子组件:通过监听点击事件,然后使用$emit发射事件

父组件:监听子组件的发射事件

<body>
  <!-- 父组件模板 -->
  <div id="app">
    <!-- 监听子组件发射的事件,传给父组件操作 -->
    <cpn @itemclick="cpnclick"></cpn>
  </div>

  <!-- 子组件模板 -->
  <template id="cpn">
    <div>
      <button v-for="item in categories" @click="btnClick(item)">{{item.name}}</button>
    </div>
  </template>

  <script>
    // 子组件
    const cpn = {
      template: '#cpn',
      data() {
        return {
          categories: [{
              id: 1,
              name: '热门推荐'
            },
            {
              id: 2,
              name: '手机数码'
            },
            {
              id: 3,
              name: '家用家电'
            },
            {
              id: 4,
              name: '电脑办公'
            },
          ]
        }
      },

      methods: {
        btnClick(item) {
          // 发射事件
          this.$emit('itemclick', item)
        }
      },
    }

    //创建Vue实例,得到 ViewModel
    const vm = new Vue({
      el: '#app',
      data: {},
      methods: {
        // 父组件对子组件传来的事件进行操作
        cpnclick(item) {
          console.log('cpnclick', item);
        }
      },
      computed: {},
      components: {
        cpn
      },
    });
  </script>

</body>
View Code

 

(二)访问

  1、父访子

 $children数组、$refs

<body>
  <div id="app">
    <cpn></cpn>
    <cpn></cpn>
    <cpn ref="aaa"></cpn>
    <button @click="btnClick">按钮</button>
  </div>

  <template id="cpn">
    <div>子组件</div>
  </template>

  <script>
    //创建Vue实例,得到 ViewModel
    const vm = new Vue({
      el: '#app',
      data: {
        message: '你好啊',
      },
      methods: {
        btnClick() {
          // 调用子组件的方法
          // 1.$children
          // console.log(this.$children);
          // this.$children[0].showMessage();

          // 2.$refs
          console.log(this.$refs.aaa);

        }
      },
      computed: {},
      components: {
        cpn: {
          template: '#cpn',
          methods: {
            showMessage() {
              console.log('showMessage');
            }
          },
        }
      },
    });
  </script>

</body>
View Code

 

  2、子访父

$parent、$root(访问根组件)

<body>
  <div id="app">
    <cpn></cpn>
  </div>

  <template id="cpn">
    <div>
      <h2>cpn子组件</h2>
      <ccpn></ccpn>
    </div>

  </template>

  <template id="ccpn">
    <div>
      <h2>ccpn子组件</h2>
      <button @click="btnClick">按钮</button>
    </div>
  </template>

  <script>
    //创建Vue实例,得到 ViewModel
    const vm = new Vue({
      el: '#app',
      data: {
        message: '你好啊我是Vue',

      },
      methods: {

      },
      computed: {},
      components: {
        cpn: {
          template: '#cpn',
          data() {
            return {
              name: 'cpnName'
            }
          },
          components: {
            ccpn: {
              template: '#ccpn',
              methods: {
                btnClick() {
                  // 1.访问父组件
                  console.log(this.$parent);
                  console.log(this.$parent.name);

                  // 2. 访问根组件
                  console.log(this.$root.message);
                }
              },
            }
          }
        }
      },
    });
  </script>

</body>
View Code

 

(三)事件总线

(四)Vuex

  详见Vuex专题

二、插槽

(一)普通插槽

<body>
  <div id="app">
    <cpn></cpn>
    <cpn>
      <p>cpn2</p>
    </cpn>
    <cpn><span>cpn3</span></cpn>
    <cpn><input type="text">
      <p>cpn4</p>
    </cpn>
  </div>

  <template id="cpn">
    <div>
      <p>我是cpn</p>
      <slot><button>默认按钮</button></slot>
    </div>
  </template>

  <script>
    //创建Vue实例,得到 ViewModel
    const vm = new Vue({
      el: '#app',
      data: {},
      methods: {},
      computed: {},
      components: {
        cpn: {
          template: '#cpn'
        }
      },
    });
  </script>

</body>
View Code

 

(二)具名插槽

<body>
  <div id="app">
    <cpn><span>没有name属性会把所有没有名字的插槽都替换</span></cpn>
    <cpn><button slot="left">返回</button></cpn>
    <cpn><span slot="center">使用slot使用相应的插槽</span></cpn>

  </div>

  <template id="cpn">
    <div>
      <slot>没有name</slot>

      <slot name="left"></slot>
      <slot name="center"></slot>
      <slot name="right"></slot>
      <slot>没有name</slot>

    </div>
  </template>
  <script>
    //创建Vue实例,得到 ViewModel
    const vm = new Vue({
      el: '#app',
      data: {},
      methods: {},
      computed: {},
      components: {
        cpn: {
          template: '#cpn'
        }
      },
    });
  </script>

</body>
View Code

 

(三)编译作用域(父组件和子组件的属性相同)

<body>
  <div id="app">
    <!-- 先看在那个模板里面,直接去app找 -->
    <cpn v-show="isShow"></cpn>
  </div>

  <template id="cpn">
    <div>
      <h2>我是子组件</h2>
      <!-- 模板中去自己模板中找 -->
      <button v-show="!isShow">按钮</button>
    </div>
  </template>
  <script>
    //创建Vue实例,得到 ViewModel
    const vm = new Vue({
      el: '#app',
      data: {
        message: 'Smallstars',
        isShow: true,
      },
      methods: {},
      computed: {},
      components: {
        cpn: {
          template: '#cpn',
          data() {
            return {
              isShow: false,
            }
          },
        }
      },
    });
  </script>

</body>
View Code

 

(四)作用域插槽(父组件替换插槽的内容,但内容是子组件决定。由于编译作用域的原因,父组件本不能直接访问子组件的值)

<body>
  <div id="app">
    <cpn></cpn>
    <!-- 父组件想对子组件的数据进行操作,但是不能直接拿(前一章作用域问题) -->
    <!-- 获取子组件数据用不同方式展示 -->
    <cpn>
      <template slot-scope="slot">
        <!-- <span v-for="item in slot.data">{{item}} - </span> -->
        <span>{{slot.data1.join('-')}}</span>

      </template>

    </cpn>

    <cpn>
      <template slot-scope="slot">
        <span v-for="item in slot.data1">{{item}} * </span>
      </template>

    </cpn>

  </div>

  <template id="cpn">
    <div>
      <!-- 作用域插槽,在这里绑定数据好在父组件使用 -->
      <slot :data1="pLanguages">
        <ul>
          <li v-for="item in pLanguages">{{item}}</li>
        </ul>
      </slot>
    </div>
  </template>
  <script>
    //创建Vue实例,得到 ViewModel
    const vm = new Vue({
      el: '#app',
      data: {
        message: 'Smallstars',
      },
      methods: {},
      computed: {},
      components: {
        cpn: {
          template: '#cpn',
          data() {
            return {
              pLanguages: ['Python', 'JavaScript', 'C++', 'C#']
            }
          },
        }
      },
    });
  </script>

</body>
View Code

 

posted @ 2020-08-15 16:20  北冥雪  阅读(216)  评论(0编辑  收藏  举报