Vue.js—组件化

组件化的实现和使用步骤

组件化:
如果我们将一个页面所有的处理逻辑全部放在一起,处理起来就会变得非常复杂,而且不利用后续的管理以及扩展
但如果我们将整个页面拆分为一个个小的功能块,每个功能块完成属于自己这部分的功能,那么之后整个页面的管理和维护就简易多了

组件化是是Vue.js的重要思想:
□ 它提供了一种抽象,让我们可以开发出一个个复用的小组件来构造应用
□ 任何的应用都会被抽象成组件树

1.1 注册组件的基本步骤

组件的使用分为三个步骤:
1.创建组件构造器 (调用Vue.extend()方法创建组件构造器)
2.注册组件 (调用Vue.component()方法注册组件)
3.使用组件 (在Vue实例的作用范围内使用组件)

■ 1.Vue.extend():
调用Vue.extend()创建一个组件构造器
在构建组件构造器时,传入template代表我们自定义组件的模板
该模板是在使用到组件的 地方要显示的HTML代码
■ 2.Vue.component():
调用Vue.component()是将刚才的组件构造器注册为一个组件,并且给它起一个组件的标签名称。
所以需要传递两个参数:1、注册组件的标签名 2、组件构造器
■ 3.组件必须挂载在某个Vue实例下,否则它不会生效。

1.2 组件化的基本使用

组件名不能用myCpn类似名

<!DOCTYPE html>
<html lang="en">

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

<body>
  <div id="app">
    <my-cpn></my-cpn>
  </div>
  <script src="/js/vue.js"></script>
  <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: '你好啊'
      }
    })
  </script>
</body>

</html>

在这里插入图片描述

全局组件和局部组件

全局组件
当我们通过Vue.component()注册组件时,组件的注册是全局的
意味着该组件可以在任何Vue示例下使用
局部组件
如果我们创建的组件是挂载到某个实例上,组件的注册是局部的

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  <div id="app">
    <my-cpn></my-cpn>
  </div>
  <div id="app2">
    <my-cpn></my-cpn>
  </div>
  <script src="/js/vue.js"></script>
  <script>
    // 构建组件构造器
    const cpnC = Vue.extend({
      template: `
      <div>
        <p>哈哈哈</p>
        <h4>i am good</h4>
      </div>
      `
    })
    // 注册组件(全局组件)
    // Vue.component('my-cpn',cpnC)
    const app = new Vue({
      el: '#app',
      // 局部组件
      components: {
        'my-cpn': cpnC
      }
    })
    const app2 = new Vue({
      el: '#app2'
    })
  </script>
</body>
</html>

父组件和子组件

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  <div id="app">
    <cpn1></cpn1>
    <cpn2></cpn2>
  </div>
  <script src="/js/vue.js"></script>
  <script>
    // 创建组件构造器
    const cpnC1 = Vue.extend({
      template: `
      <div>
        <p>这里显示的是:11111</p>
        <p>这里显示的是:22222</p>
      </div>
      `
    })
    const cpnC2 = Vue.extend({
      template:`
      <div>
        <h4>cpn2显示</h4>
        <p>这里显示:444</p>
        <cpn1></cpn1>
      </div>
      `,
      component: {
        cpn1: cpnC1,
      }
    })
    // 注册组件
    Vue.component('cpn1',cpnC1)
    const app = new Vue({
      el: "#app",
      components: {
        cpn2: cpnC2
      }
    })
  </script>
</body>
</html>

在这里插入图片描述

注册组件语法糖

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  <div id="app">
    <my-cpn></my-cpn>
  </div>
  <script src="/js/vue.js"></script>
  <script>
    const app = new Vue({
      el: "#app",
      components: {
        "my-cpn": {
          template: `
          <div>
            <p>辣辣辣</p>
            <p>甜甜甜</p>
          </div>
          `
        }
      }
    })
  </script>
</body>
</html>

在这里插入图片描述

组件模块抽离方法

将HTML分离出来,挂载到对应组件上
有两种方式,一种用script标签,一种用template标签

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  <div id="app">
    <cpn></cpn>
  </div>
  <!-- 1.使用<script>标签 -->
  <!-- <script type="x-template" id="cpn1">
    <div>
      <p>你的名字是</p>
      <h4>吕狗蛋</h4>
    </div>
  </script> -->

  <!-- 2.使用template标签 -->
  <template id="cpn1">
    <div>
      <p>你的名字是</p>
      <h4>吕狗蛋</h4>
    </div>
  </template>
  <script src="/js/vue.js"></script>
  <script>
    Vue.component('cpn',{
      template: "#cpn1"
    })
    const app = new Vue({
      el: "#app"
    })
  </script>
</body>
</html>

组件数据的存放

组件是一个单独封装的模块,这个模块有属于自己的HTML模板,也有属于自己的数据data
在组件中,不能直接访问Vue实例中的data
Vue组件应该有保存自己数据的地方

■ 组件数据的存放:
□ 组件对象有一个data属性,也有methods等属性
□ data属性必须是函数
□ 函数返回一个对象,对象中保存着数据

数据存放在组建的data中

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  <div id="app">
    <cpn></cpn>
  </div>
  <!-- 1.使用<script>标签 -->
  <!-- <script type="x-template" id="cpn1">
    <div>
      <p>你的名字是</p>
      <h4>吕狗蛋</h4>
    </div>
  </script> -->

  <!-- 2.使用template标签 -->
  <template id="cpn1">
    <div>
      <p>你的名字是</p>
      <h4>吕狗蛋</h4>
      <h5>{{message}}</h5>
    </div>
  </template>
  <script src="/js/vue.js"></script>
  <script>
    Vue.component('cpn',{
      template: "#cpn1",
      // data函数
      data() {
        return {
          message: "lyf"
        } 
      }
    })
    const app = new Vue({
      el: "#app"
    })
  </script>
</body>
</html>

在这里插入图片描述

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

■ 首先,如果不是一个函数,Vue直接就会报错。
■ 其次,原因是在于Vue让每个组件对象都返回一个新的对象,因为如果是同一个对象的,组件在多次使用后会相互影响。

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  <div id="app">
    <cpn></cpn>
  </div>
  <script src="/js/vue.js"></script>
  <template id="cpn1">
    <div>
      <p>是我想太多</p>
      <p>我总这样说</p>
      <p>而你却没有</p>
      <p>真的心疼我</p>
    </div>
    <!-- 计算器 -->
    <h4>{{number}}</h4>
    <button @click="decrement">-</button>
    <button @click="increment">+</button>
  </template>
  <script>
    Vue.component('cpn',{
      template: "#cpn1",
      data() {
        return {
          number: 0
        }
      },
      methods: {
        decrement() {
          this.number--
        },
        increment() {
          this.number++
        }
      }
    })
    const app = new Vue({
      el: "#app"
    })
  </script>
</body>
</html>

父子组件的通信

子组件是不能引用父组件或者Vue实例的数据的
但是,在开发中,往往一些数据确实需要从上层传递到下层:
比如在一个页面中,我们从服务器请求到了很多的数据。
其中一部分数据,并非是我们整个页面的大组件来展示的,而是需要下面的子组件进行展示。
这个时候,并不会让子组件再次发送一个网络请求,而是直接让大组件(父组件)将数据传递给小组件(子组件)
父子组件通信方式:
1.通过props向子组件传递信息
2.通过事件向父组件传递消息

父传子props驼峰标识

props下的对象需用驼峰写法,v-bind不能使用驼峰命名

<!DOCTYPE html>
<html lang="en">

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

<body>
  <div id="app">
    <!-- v-bind不能使用驼峰命名 -->
    <cpn :c-info="info"></cpn>
  </div>
  <template id="cpn">
    <h3>{{cInfo}}</h3>
    <!-- <div>
      <p>zzy</p>
      <p>my love</p>
    </div> -->
  </template>
  <script src="/js/vue.js"></script>
  <script>
    const cpn = {
      template: "#cpn",
      props: {
        cInfo: {
          type: Object,
          default() {
            return {}
          }
        }
      }
    }
    const app = new Vue({
      el: "#app",
      data: {
        info: {
          name: 'zzy',
          age: 18,
          hobby: 'shopping'
        }
      },
      components: {
        cpn
      }
    })
  </script>
</body>

</html>

在这里插入图片描述

子传父

子组件传递数据或事件到父组件中,我们需要用自定义事件完成
何时需要 自定义事件:
当子组件需要向父组件传递数据时,就可以用到自定义事件
v-on不仅可以用来监听DOM事件,也可以用于组件间的自定义事件
自定义事件的流程:
在子组件中,通过$emit()来触发事件
在父组件中,通过v-on来监听子组件事件

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  <div id="app">
    <cpn @item-click="cpnClick"></cpn>
  </div>
  <template id="cpn">
    <div>
      <button v-for="item in categories" @click=btnClick(item)>{{item.name}}</button>
    </div>
  </template>
  <script src="/js/vue.js"></script>
  <script>
    const cpn = {
      template: "#cpn",
      data() {
        return {
          categories: [
            {id:"aaa", name:"热门推荐"},
            {id:"bbb", name:"手机数码"},
            {id:"ccc", name:"家用电器"},
            {id:"ddd", name:"电脑办公"},
          ]
        }
      },
      methods: {
        btnClick(item) {
          this.$emit('item-click',item)
        }
      }
    }
    const app = new Vue({
      el: "#app",
      data: {
        message: ''
      },
      components: {
        cpn
      },
      methods: {
        cpnClick() {
          console.log('cpnClick',item);
          
        }
      }
    })
  </script>
</body>
</html>

在这里插入图片描述

父子组件通信—结合双向绑定案例

<!DOCTYPE html>
<html lang="en">

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

<body>
  <div id="app">
    <cpn :number1="num1" :number2="num2" @num1change="num1change" @num2change="num2change"/>
  </div>
  <template id="cpn">
    <div>
      <p>props: {{number1}}</p>
      <p>data: {{dnumber1}}</p>
      <input type="text" :value="dnumber1" @input="num1Input"> 
      <p>props: {{number2}}</p>
      <p>data: {{dnumber2}}</p>
      <input type="text" :value="dnumber2" @input="num2Input">
    </div>
  </template>
  <script src="/js/vue.js"></script>
  <script>
    const app = new Vue({
      el: "#app",
      data: {
        num1: 1,
        num2: 0
      },
      methods: {
        num1change(value) {
          this.num1 = parseFloat(value)
        },
        num2change(value){
          this.num2 = parseFloat(value)
        }
      },
      components: {
        cpn: {
          template: "#cpn",
          props: {
            // 确定类型
            number1: Number,
            number2: Number
          },
          data() {
            return {
              dnumber1: this.number1,
              dnumber2: this.number2
            }
          },
          methods: {
            num1Input(event) {
              // 将input中的value值赋值到dnumber中
              this.dnumber1 = event.target.value;
              // 为了让父组件的值可以修改,发出一个事件
              this.$emit('num1change',this.dnumber1)
              // 让number2的值对应改变
              this.dnumber2 = this.dnumber1*100
              this.$emit('num2change',this.dnumber2)
            },
            num2Input(event) {
              this.dnumber2 = event.target.value;
              this.$emit('num2change',this.dnumber2)
              this.dnumber1 = this.dnumber2 / 100
              this.$emit('num1change',this.dnumber1)
            }
          }
        }
      }
    })
  </script>
</body>

</html>

在这里插入图片描述

父子组件访问

父访问子 children-refs

$children
$refs 引用

子访问父 parent-root

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值