Vue组件化开发

组件基础

注册组件的基本步骤

  • 创建组件构造器
    • 调用Vue.extend()方法
  • 注册组件
    • 调用Vue.component()方法
  • 使用组件
    • 在Vue实例的作用范围内使用组件

案例:全局组件的基本使用

<div id=app>
<!--  使用组件-->
<my-cpn></my-cpn>
<my-cpn></my-cpn>
<my-cpn></my-cpn>
</div>
<script>

<!--创建组件构造器-->
  const cpnC = Vue.extend({
    template: `
      <div>
        <h2>我是标题</h2>
        <p>我是内容,哈哈哈</p>
        <p>我是内容,嘻嘻嘻</p>
      </div>
    `
  })

  //注册组件-全局组件
  Vue.component('my-cpn',cpnC)
  const app = new Vue({
    el: '#app',
    data: {
      message: 'Hello Vue'
    }
  })
</script>

全局组件与局部组件

  • 全局组件可以在多个Vue实例中使用

  • 局部组件只能在注册了这个组件的Vue实例中使用

  • 局部组件的基本使用

<div id=app>
  <!--  使用组件-->
  <my-cpn></my-cpn>
  <my-cpn></my-cpn>
  <my-cpn></my-cpn>
</div>
<script>

  <!--创建组件构造器-->
  const cpnC = Vue.extend({
    template: `
      <div>
        <h2>我是标题</h2>
        <p>我是内容,哈哈哈</p>
        <p>我是内容,嘻嘻嘻</p>
      </div>
    `
  })

  //注册组件-全局组件
  // Vue.component('my-cpn', cpnC)

  const app = new Vue({
    el: '#app',
    data: {
      message: 'Hello Vue'
    },
    //注册局部组件
    components: {
      myCpn: cpnC
    }
  })
</script>

父子组件

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
  <title>Document</title>
</head>
<body>
<div id=app>
  <cpn2></cpn2>
</div>
<script>

  const cpn1 = Vue.extend({
    template: `
      <div>
        <h2>我是标题1</h2>
        <p>我是内容,哈哈哈</p>
      </div>
    `
  })

  const cpn2 = Vue.extend({
    template: `
      <div>
        <cpn1></cpn1>
        <h2>我是标题2</h2>
        <p>我是内容,嘻嘻嘻</p>
      </div>
    `,
    components: {
      cpn1
    }
  })

  const app = new Vue({
    el: '#app',
    data: {
      message: 'Hello Vue'
    },
    //注册局部组件
    components: {
      cpn2
    }
  })
</script>
</body>
</html>

父子组件,其实就是组件的嵌套关系

组件注册语法糖

  • 全局组件
  //注册组件-全局组件
  Vue.component('my-cpn', {
    template: `
      <div>
        <h2>我是标题</h2>
        <p>我是内容,哈哈哈</p>
        <p>我是内容,嘻嘻嘻</p>
      </div>
    `
  })
  • 局部组件
  const app = new Vue({
    el: '#app',
    data: {
      message: 'Hello Vue'
    },
    //注册局部组件
    components: {
      cpn2: {
        template: `
      <div>
        <cpn1></cpn1>
        <h2>我是标题2</h2>
        <p>我是内容,嘻嘻嘻</p>
      </div>
    `,
        components: {
          cpn1
        }
      }
    }
  })

  • 抽离出模板
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
  <title>Document</title>
</head>
<body>

<template id="cpn2">
  <div>
    <h2>我是标题1</h2>
    <p>我是内容,哈哈哈</p>
  </div>
</template>

<div id=app>
  <cpn2></cpn2>
</div>
<script>

  Vue.component('cpn2',{
    template: '#cpn2'
  })

  const app = new Vue({
    el: '#app',
    data: {
      message: 'Hello Vue'
    },
    //注册局部组件
    components: {
    }
  })
</script>
</body>
</html>

为什么组件中的data必须是函数

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
  <title>Document</title>
</head>
<body>

<template id="cpn2">
  <div>
    <h2>{{title}}</h2>
    <p>我是内容,哈哈哈</p>
  </div>
</template>

<div id=app>
  <cpn2></cpn2>
</div>
<script>

  Vue.component('cpn2', {
    template: '#cpn2',
    data() {
      return {
        title: '我是标题111'
      }
    }
  })

  const app = new Vue({
    el: '#app',
    data: {
      message: 'Hello Vue'
    },
    //注册局部组件
    components: {}
  })
</script>
</body>
</html>

答案非常简单,因为组件是需要被复用的,我们必须保证每次使用的时候,都有自己的一个数据空间。

相当于,因为data是一个函数,每次创建组件使用的时候,才能够使用一份单独的数据,不让同一个组件的不同实例产生影响。

父子间通讯

父传子:props

  • 子组件中,props使用数组声明接收的数据名称
  const cpn = {
    template: `
      <div>
        <h2>{{title}}</h2>
        <p>{{cmovies}}</p>
      </div>
    `,
    props: ['cmovies'],
    data() {
      return {
        title: '我是标题111'
      }
    }
  }
  • 注册子组件
  const app = new Vue({
    el: '#app',
    data: {
      message: 'Hello Vue',
      movies: ['电影1', '电影2', '电影3']
    },
    //注册局部组件
    components: {
      cpn
    }
  })
  • 传递数据
<div id=app>
  <cpn :cmovies="movies"></cpn>
</div>

扩展

上例中,props的值是一个数组类型,还可以使用对象类型,这样可以指定变量的类型和默认值

  const cpn = {
    template: `
      <div>
        <h2>{{title}}</h2>
        <p>{{cmovies}}</p>
      </div>
    `,
    props: {
      cmovies: Array,
      cmessage: {
        type: String,
        required: false,
        default: '111aa'
      },
      cc: {
        default: function () {
//默认值是对象的话必须使用function返回
          return {
            a: 'aaa'
          }
        }
      }
    },
    data() {
      return {
        title: '我是标题111'
      }
    }
  }

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GtvbLVKh-1584459683921)(http://tuchuang.zhangln.com/uQ9qko.png)]

子传父:自定义事件

  • 基本案例
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
  <title>Document</title>
</head>
<body>
<div id=app>
<!--  Step 2:父组件中监听子组件中的自定义事件 并设置处理函数-->
  <cpn @title-changed="updateTitle"></cpn>
  <h2>{{title}}</h2>
</div>
<script>


  <!--  子组件 -->
  const cpn = Vue.extend({
    template: `
      <div>
        <h1 @click="changeTitle">{{title}}</h1>
      </div>
    `,
    data() {
      return {
        title: "Vue.js Demo"
      }
    },
    methods: {
      changeTitle() {
        console.log("子组件向父组件发送消息");
        //Step 1:子组件触发自定义事件,并传递参数
        this.$emit("title-changed", "子向父组件传值");
      }
    }
  })

  //父组件
  const app = new Vue({
    el: '#app',
    data: {
      title: 'Hello Vue',
    },
    methods: {
      //Step 3:父组件中定义函数处理子组件传递过来的数据
      updateTitle(e) {
        console.log("父组件收到子组件消息:" + e);
        this.title = e;
      }
    },
    //注册局部组件
    components: {
      cpn
    }
  })
</script>
</body>
</html>

父子间访问

父子组件内部,可以使用下面的方式,获取到父子组件的引用

父访问子

方式:this.$childrenthis.$refs

子访问父

方式:this.$parent

插槽

基本使用

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
  <title>Document</title>
</head>
<body>
<div id=app>
  <!--  使用组件-->
  <my-cpn>
    <button>按钮</button>
  </my-cpn>
  <my-cpn></my-cpn>
  <my-cpn></my-cpn>
</div>
<script>

  <!--创建组件构造器-->
  const cpnC = Vue.extend({
    template: `
      <div>
        <h2>我是标题</h2>
        <p>我是内容,哈哈哈</p>
        <p>我是内容,嘻嘻嘻</p>
        <slot></slot>
      </div>
    `
  })

  const app = new Vue({
    el: '#app',
    data: {
      message: 'Hello Vue'
    },
    //注册局部组件
    components: {
      myCpn: cpnC
    }
  })
</script>
</body>
</html>

在组件模板中,使用<slot>添加插槽

父组件使用带有插槽的子组件的时候,通过在组件中添加额外的html元素,替换子组件中原先插槽的位置

  • 设置插槽的默认值
        <slot><button>
            按钮
            </button></slot>

具名插槽

当需要替换多个内容的时候,就会用到多个插槽,多个插槽之间使用name标识

<div id="solt">
        <app-layout>
            <p slot="footer">这个是footer</p>
            <h1 slot="header">这个是header</h1>
            <p>这个什么都没有,只是一个P标签A</p>
            <p>这个什么都没有,只是另一个P标签B</p>
            <p slot="footer">这个是footer</p>
            <p>这个什么都没有,只是另一个P标签C</p>
        </app-layout>
    </div>
    <script>
        Vue.component('app-layout', {
            template: `
                    <div class="container">
                    <header>
                        <slot name="header"></slot>
                    </header>
                    <main>
                        <slot></slot>
                    </main>
                    <footer>
                        <slot name="footer"></slot>
                    </footer>
                    </div>
                    `,
        })

        new Vue({
            el: '#solt'
        })

编译作用域

<div id=app>
  <!--  使用组件-->
  <my-cpn v-show="isShow">
    <button>按钮</button>
  </my-cpn>
  <my-cpn></my-cpn>
  <my-cpn></my-cpn>
</div>

这里isShow,会从app实例中的去查找,而不是my-cpn这个组件

父组件模板的所有东西都会在父级作用域内编译;子组件模板的所有东西都会在子级作用域内编译

作用域插槽

父组件替换插槽的标签,但是内容由子组件来提供;

在作用域插槽内,父组件可以拿到子组件的数据。子组件可以在slot标签上绑定属性值

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BLsmA8iW-1584459683923)(http://tuchuang.zhangln.com/Smblgn.png)]

参考:https://www.jianshu.com/p/e10baeff888d

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值