vue教程——08 组件化开发

一 组件化开发的概念。

所谓组件化,就是把页面拆分成多个组件,每个组件依赖的 CSS、JS、模板、图片等资源放在一起开发和维护。

因为组件是资源独立的,所以组件在系统内部可复用,组件和组件之间可以嵌套,如果项目比较复杂,可以极大简化代码量,并且对后期的需求变更和维护也更加友好。

二 全局组件和局部组件

组件的注册方式有两种,一种是全局组件一种是局部组件。

  1. 全局注册,通过 Vue.component
  2. 局部注册,通过 components:{cpnc:cpnc}
  <div id="app">
    <h2>全局组件</h2>
    <my-cpn></my-cpn>
    <h2>局部组件</h2>
    <cpnc></cpnc>
  </div>
  <script src="https://cdn.jsdelivr.net/npm/vue@2.6.10/dist/vue.js"></script>
  <script>
    // 1.创建组件构造器对象
    const cpnc = Vue.extend({
      template:`
        <div>
          <h2>标题</h2>
          <p>内容1</p>
          <p>内容2</p>
        </div>`
    })
    // 2.注册组件(全局组件,可以在多个vue实例中使用)
    Vue.component('my-cpn', cpnc)

    const app = new Vue({
      el:"#app",
      components:{//局部组件创建
        cpnc:cpnc
      }
    })
  </script>

注册组件的语法糖:注册组件时候可以不实例化组件对象,直接在注册的时候实例化。{}就是一个组件对象。

  <div id="app">
    <cpn1></cpn1>
    <cpn2></cpn2>
  </div>
  <script src="https://cdn.jsdelivr.net/npm/vue@2.6.10/dist/vue.js"></script>
  <script>
    // 1.注册全局组件语法糖
    Vue.component('cpn1', {
      template:`
        <div>
          <h2>全局组件语法糖</h2>
          <p>全局组件语法糖</p>
        </div>`
    })

    const app = new Vue({
      el:"#app",
      components:{//局部组件创建
        cpn2:{
          template:`
        <div>
          <h2>局部组件语法糖</h2>
          <p>局部组件语法糖</p>
        </div>`
        }
      }
    })
  </script>

三 父组件向子组件传值,props

3.1 用 法 : 3.1 用法: 3.1
1 在 父 组 件 的 d a t a 中 定 义 值 1 在父组件的data中定义值 1data
2 在 父 组 件 中 引 用 子 组 件 2 在父组件中引用子组件 2
3 父 组 件 的 值 绑 定 给 子 组 件 v − b i n d 3 父组件的值绑定给子组件 v-bind 3vbind
4 子 组 件 通 过 p r o p s 接 受 父 组 件 传 过 来 的 值 4 子组件通过props接受父组件传过来的值 4props

3.2 详 解 : 3.2 详解: 3.2
p r o p s 可 以 是 数 组 或 对 象 , 用 于 接 受 来 自 父 组 件 的 数 据 。 p r o p s 可 以 是 简 单 的 数 组 , 或 者 使 用 对 象 作 为 替 代 , 对 象 允 许 props 可以是数组或对象,用于接受来自父组件的数据。props 可以是简单的数组,或者使用对象作为替代,对象允许 propsprops使 配 置 高 级 选 项 , 如 类 型 检 测 、 自 定 义 验 证 和 设 置 默 认 值 。 配置高级选项,如类型检测、自定义验证和设置默认值。

类 型 : A r r a y < s t r i n g > ∣ O b j e c t 类型:Array<string> | Object Array<string>Object

你 可 以 基 于 对 象 的 语 法 使 用 一 下 选 项 : 你可以基于对象的语法使用一下选项: 使

1 type:可以是下列原生构造函数中的一种:String、Number、Boolean、Array、Object、Data、Function、Symbol、任何自定义的构造函数、或上述内容组成的数组。会检查一个prop是否是给定的类型,否则抛出警告。

2 default:any
为该prop指定一个默认值。如果该prop没有传入,则换做用这个值。对象或数组的默认值必须从一个工厂函数返回。

3 required:Boolean
定义该prop是否是必填项。是非生产环境中,如果这个值truthy且该prop没有被传入,则会被控制台抛出一个警告。

4 validator:Function
自定义验证函数会将该prop的值作为唯一的参数带入。在非生产环境下,如果该函数返回一个falsy的值(也就是验证失败),控制台将会抛出一个警告。

3.3 V u e 在 内 部 会 对 p r o p s 选 项 进 行 处 理 , 无 论 开 发 时 使 用 了 哪 种 语 法 , V u e 都 会 将 其 规 范 化 为 对 象 的 形 式 。 3.3 Vue在内部会对 props 选项进行处理,无论开发时使用了哪种语法,Vue都会将其规范化为对象的形式。 3.3Vueprops使Vue
具体规范方式见Vue源码 src/core/util/options.js 文件中的 normalizeProps 函数.

3.4 V u e 父 子 组 件 传 值 中 ‘ . s y n c ‘ 的 理 解 3.4 Vue父子组件传值中 `.sync` 的理解 3.4Vue.sync
由于父组件向子组件传值是单向的,子组件不能修改父组件的值,修改了会报错,所以出现了 .sync

可以理解为以下操作:
1 子组件在props中声明,与父组件商量好的传值暗号xxx(用来作为传递值的别名)
2 子组件通过触发一个事件来告诉父组件:“我要改xxx对应的值!” (this.$emit('update: value', this.xxx=yyy))
3 父组件在引用子组件时,在其标签内通过:xxx='local_value' @update:value='local_value = $event'来监听update:value事件,对更改请求作出响应
4 local_value的值更改为yyy

update:value其实是一个字符串,只要父子组件对应即可,不强制要求,但官方建议写为’update:value’,大概是为了语义性吧~

.sync是用来简化第3步操作的::xxx.sync = 'local_value'等价于:xxx='local_value' @update:value='local_value = $event'这么一长串,最后实现的效果一样,.sync就是这么一颗语法糖。

同时,可以用v-bind.sync = 'xxx’来一次传递多个值,这些值都封装在对象xxx内,xxx对象中的每一个属性都会作为一个独立的 prop 传给子组件,然后各自添加用于更新的 v-on 监听器。

props举例子

  <div id="app">
    <cpn :cMovies="movies" :cMessage="message"></cpn>
  </div>
  <template id="cpn">
    <div>
      <ul>
        <li v-for="(item, index) in cmovies" :key="index">{{item}}</li>
      </ul>
      <h2>{{cmessage}}</h2>
    </div>
  </template>
  <script src="https://cdn.jsdelivr.net/npm/vue@2.6.10/dist/vue.js"></script>

  <script>
    function Person(firstName,lastName) {
      this.firstName = firstName
      this.lastName = lastName
    }
    // 父传子:props
    const cpn = {
      template: "#cpn",
      // props: ['cmovies', 'cmessage'],//数组写法
      props: { //对象写法
        // 1.类型限制(多个类使用数组)
        // cmovies:Array,
        // cmessage:String,
        // cmessage:['String','Number'],
        // 2.提供一些默认值,以及必传值
        cmessage: {
          type: String,
          default: 'zzzzz',
          required: true //在使用组件必传值
        },
        //类型是Object/Array,默认值必须是一个函数
        cmovies: {
          type: Array,
          default () {
            return [1, 2, 3, 4]
          }
        },
        // 3.自定义验证函数
        // vaildator: function (value) {
        //   //这个传递的值必须匹配下列字符串中的一个
        //   return ['zzzzz', 'ttttt', 'yyy'].indexOf(value) !== -1
        // }
        // 4.自定义类型
        // cmessage:Person,
      },
      data() {
        return {
        }
      },
      methods: {

      },
    };
    const app = new Vue({
      el: "#app",
      data: {
        message: "你好",
        movies: ["复仇者联盟", "钢铁侠", "星际穿越", "哪吒传奇"]
      },
      components: {
        cpn
      }
    })
  </script>

四 子组件向父组件传值

1 在子组件中定义一个方法btnClick(item),使用$emit,'itemclick’是事件名,item是传过去的值。
2 在子组件中监听点击事件并回调此方法.
3 在父组件中<cpn @itemclick="cpnClcik"></cpn> 定义一个方法cpnClcik(item) ,参数就是上面传来的item

  <!-- 父组件 -->
  <div id="app">
    <!-- 不写参数默认传递btnClick的item -->
    <cpn @itemclick="cpnClcik"></cpn>

  </div>

  <!-- 子组件 -->
  <template id="cpn">

    <div>
      <button v-for="(item, index) in categoties" :key="index" @click="btnClick(item)">{{item.name}}</button>
    </div>
  </template>

  <script src="https://cdn.jsdelivr.net/npm/vue@2.6.10/dist/vue.js"></script>

  <script>
    // 父传子:props
    const cpn = {
      template: "#cpn",
      data() {
        return {
          categoties: [{
              id: 'aaa',
              name: '热门推荐'
            },
            {
              id: 'bbb',
              name: '手机数码'
            },
            {
              id: 'ccc',
              name: '家用家电'
            },
            {
              id: 'ddd',
              name: '电脑办公'
            },
          ]
        }
      },
      methods: {
        btnClick(item) {
          this.$emit('itemclick', item)
        }
      },
    };
    const app = new Vue({
      el: "#app",
      data() {
        return {

        }
      },
      methods: {
        cpnClcik(item) {
          console.log('cpnClick'+item.name);
        }
      },
      components: {
        cpn
      },
    })
  </script>

五 组件通信-父子通信案例(watch实现)

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

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>组件通信-父子通信案例(watch实现)</title>
</head>

<body>
  <!-- 父组件 -->
  <div id="app">

    <cpn :number1='num1' :number2='num2' @num1change="num1Change" @num2change="num2Change"></cpn>

    <h2>父组件{{num1}}</h2>
    <input type="text" v-model="num1" >
    <h2>父组件{{num2}}</h2>
    <input type="text" v-model="num2">

  </div>

  <!-- 子组件 -->
  <template id="cpn">

    <div>
      <h2>{{number1}}</h2>
      <input type="text" v-model="dnumber1">
      <h2>{{number2}}</h2>
      <input type="text" v-model="dnumber2">
    </div>
  </template>

  <script src="https://cdn.jsdelivr.net/npm/vue@2.6.10/dist/vue.js"></script>

  <script>
    // 父传子:props
    const cpn = {
      template: "#cpn",
      data() {
        return {
          dnumber1:this.number1,
          dnumber2:this.number2
        }
      },
      props:{
        number1:[Number,String],
        number2:[Number,String],
      },
      watch: {
        dnumber1(newValue){
          this.dnumber1 = newValue * 100
          this.$emit('num1change',newValue)
        },
        dnumber2(newValue){
          this.dnumber1 = newValue * 100
          this.$emit('num2change',newValue)
        }
      },
    };
    const app = new Vue({
      el: "#app",
      data() {
        return {
          num1:1,
          num2:2,
        }
      },
      methods: {
        num1Change(value){
          this.num1=value
        },
        num2Change(value){
          this.num1=value
        }
      },
      components: {
        cpn
      },
    })
  </script>
</body>

</html>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值