十、Vue组件化开发

01-组件化实现和使用步骤

1.1 什么是组件化?

  • 人面对复杂问题的处理方式:
    • 任何一个人处理信息的逻辑能力都是有限的
    • 所以,当面对一个非常复杂的问题时,我们不太可能一次性搞定一大堆的内容
    • 但是,我们人有一种天生的能力,就是将问题进行拆解
    • 如果将一个复杂的问题,拆分成很多个可以处理的小问题,再将其放在整体当中,你会发现大的 问题也会迎刃而解
  • 组件化也是类似的思想:
    • 如果我们将一个页面中所有的处理逻辑全部放在一起,处理起来就会变得变得非常复杂,而且不利于后续的管理以及扩展
    • 但如果,我们将一个页面拆分成一个个小的功能块,每个功能块完成属于自己这部分独立的功能,那么之后整个页面的管理和维护就变得非常容易了
  • 在这里插入图片描述
    在这里插入图片描述
  1. 我们将一个完整的页面分成很多个组件
  2. 每个组件都用于实现页面的一个功能块
  3. 而每一个组件又可进行细分

1.2 组件化思想

  • 组件化是Vue.js中的重要思想

    • 它提供了一种抽象,让我们可以开发出一个个独立可复用的小组件来构造我们的应用
    • 任何的应用都会被抽象成一颗组件树

在这里插入图片描述

  • 组件化思想的应用:

    • 有了组件化的思想,我们在以后的开发中就要充分的利用它
    • 尽可能的将页面拆分成一个个小的,可复用的组件
    • 这样让我门的代码更加方便组织和管理,并且扩展性也更强

1.3 注册组件的基本步骤

  • 组件的使用分成三个步骤:
    • 创建组件构造器
    • 注册组件
    • 使用组件
    • 在这里插入图片描述

02-组件化的基本使用过程

2.1 代码实战

注:自定义组件一定要在Vue实例创建前创建和注册

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>02-组件化的基本使用过程</title>
</head>
<body>

<div id="app">
  <div>
    <h2>我是标题</h2>
    <p>我是内容,123</p>
    <p>我是内容,321</p>
  </div>
  <hr>
  <!--  3.使用组件-->
  <my_cpn></my_cpn>
</div>

<script type="text/javascript" src="../js/vue.js"></script>
<!--如果没有安装vue.js,就用下面的代码-->
<!--<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>-->
<script type="text/javascript">
  // 1.创建组件构造器
  //`` ES6新特性 ``定义字符串,可以不用换行
  // extend(传入对象)
  const cpnC = Vue.extend({
    template: `
    <div>
      <h2>我是标题</h2>
      <p>我是内容,hhh</p>
      <p>我是内容,aaa</p>
     </div>
    `
  })
  // 2.注册组件
  // component('使用标签的名字',组件构造器名)
  Vue.component('my_cpn',cpnC);

  // 下面代码要写在最下面
  const vm = new Vue({
    el: '#app',
    data: {
      message: 'hello world!'
    }
  })
</script>
</body>
</html>

2.2 运行结果

在这里插入图片描述

03-全局组件和局部组件

3.1 注册组件步骤解析

  • Vue.extend():
    • 调用Vue.extend()创建的是一个组件构造器
    • 通常在创建组件构造器时,传入template代表我们自定义组件模板
    • 该模板就是在使用到组件的地方,要显示的HTML代码
    • 事实上,这种写法在Vue2.x的文档中几乎看不到了,它会直接使用语法糖,但是在很多资料还是会提到这种方式,而且这种方式是学习后面方式的基础
  • Vue.component():
    • 调用Vue.component()是将刚才的组件构造器注册为一个组件,并且给它起一个组件的标签名称
    • 所以需要传递两个参数:
      • 注册组件的标签名
      • 组件构造器
  • 组件必须挂载在某个Vue实例下,否则它不会生效

3.2 代码实战

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>03-全局组件和局部组件</title>
</head>
<body>

<div id="app">
  <h1>app</h1>
  <my_cpn></my_cpn>
  <my_cpn></my_cpn>
  <hr>
</div>

<div id="app2">
  <h1>app2</h1>
  <my_cpn></my_cpn>
  <cpn></cpn>
</div>

<script type="text/javascript" src="../js/vue.js"></script>
<!--如果没有安装vue.js,就用下面的代码-->
<!--<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>-->
<script type="text/javascript">

  // 1.创建组件构造器
  const cpnC = Vue.extend({
    template:`
      <div>
        <h3>我是标题</h3>
        <p>我是内容,aaa</p>
        <p>我是内容,bbb</p>
      </div>
    `
  })
  // 2.注册组件(全局组件,意味着可以在多个Vue实例中使用---实际开发中一般不会有多个Vue实例)
  Vue.component('my_cpn',cpnC)

  const vm = new Vue({
    el: '#app',
    data: {
      message: 'hello world!'
    }
  })
  const vm2 = new Vue({
    el:'#app2',
    //局部注册 ,只有app实例用此组件
    components:{
      //cpn 定义标签
      cpn:cpnC
    }
  })
</script>
</body>
</html>

3.3 运行结果

在这里插入图片描述

04-父组件和子组件

4.1 父子组件

  • 在前面我们看到组件树:
    • 组件和组件之间存在层级关系
    • 而其中一种非常重要的关系就是父子组件的关系
  • 父子组件错误用法:以子标签的形式在Vue实例中使用
    • 因为当子组件注册到父组件的components时,Vue会编译好父组件的模块
    • 该模块的内容已经决定了父组件将要渲染的HTML(相当于父组件中已经有了子组件中内容了)
    • 是只能在父组件中被识别的
    • 类似这种用法,是会被浏览器忽略的

4.2 代码实战

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>04-父组件和子组件</title>
</head>
<body>

<div id="app">
  <p>cpn2是cpn1的父组件</p>
  <cpn2></cpn2>
</div>

<script type="text/javascript" src="../js/vue.js"></script>
<!--如果没有安装vue.js,就用下面的代码-->
<!--<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>-->
<script type="text/javascript">
  // 1.创建第一个组件
  const cpnC1 = Vue.extend({
    template:`
      <div>
        <h2>我是cpnC1</h2>
        <p>我是内容:bbb</p>
      </div>
    `
  })
  // 2.创建第二个组件
  const cpnC2 = Vue.extend({
    template:`
      <div>
        <h2>我是cpnC2</h2>
        <p>我是内容:aaa</p>
        <cpn1></cpn1>
      </div>
    `,
    // 引入cpnC1,所以cpnC1是cpnC2的子组件
    components:{
      cpn1 : cpnC1
    }
  })
  const vm = new Vue({
    el: '#app',
    data: {
    },
    // 引入cpnC2,所以cpnC2是Vue实例的子组件
    components:{
      cpn2 :cpnC2
    }
  })
</script>
</body>
</html>

4.3 运行结果

在这里插入图片描述

05-注册组件的语法糖写法

5.1 代码实战

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>05-注册组件的语法糖写法</title>
</head>
<body>

<div id="app">
  <h1>我是全局组件</h1>
  <my_cpn></my_cpn>
  <hr>
  <h1>我是局部组件</h1>
  <my_cpn1></my_cpn1>
</div>

<script type="text/javascript" src="../js/vue.js"></script>
<!--如果没有安装vue.js,就用下面的代码-->
<!--<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>-->
<script type="text/javascript">
  // 1.全局组件注册的语法糖
  // 1.创建组件构造器
  // 2.注册组件
  // 内部自动调用extend()
  Vue.component('my_cpn',{
    template:`<div>
      <h2>我是标题</h2>
      <p>我是内容,aaa</p>
      <p>我是内容,bbb</p>
     </div>`
  })

  //构建局部组件的语法糖
  const vm = new Vue({
    el:"#app",
    data:{

    },
    components:{
      my_cpn1:{
        template:`<div>
          <h2>我是标题</h2>
          <p>我是内容,ccc</p>
          <p>我是内容,ddd</p>
        </div>`
      }
    }
  })
</script>
</body>
</html>

5.2 运行结果

在这里插入图片描述

06-组件模板抽离的写法

6.1 代码实战

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>06-组件模板抽离的写法</title>
</head>
<body>

<div id="app">
  <cpn></cpn>
  <hr>
  <cpn1></cpn1>
</div>
<!--    1.script标签抽离,注意类型必须是text/x-template-->
<script type="text/x-template" id="cpn">
  <div>
    <h2>我是script标签抽离</h2>
    <p>我是内容,script type="text/x-template" id="cpn"</p>
    <p>我是内容,script type="text/x-template" id="cpn"</p>
  </div>
</script>
<!--2.template标签抽离-->
<template id="cpn1">
  <div>
    <h2>我是template标签抽离</h2>
    <p>我是内容,template id="cpn1"</p>
    <p>我是内容,template id="cpn1"</p>
  </div>
</template>
<script type="text/javascript" src="../js/vue.js"></script>
<!--如果没有安装vue.js,就用下面的代码-->
<!--<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>-->
<script type="text/javascript">
  // 1.注册一个全局组件
  Vue.component('cpn',{
    template:'#cpn'
  })

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

  const vm = new Vue({
    el: '#app',
    data: {
      message: 'hello world!'
    }
  })
</script>
</body>
</html>

6.2 运行结果

在这里插入图片描述

07-为什么组件data必须是函数

7.1 组件的数据

1、组件可以访问Vue实例数据吗?

  • 组件是一个单独功能模块的封装:
    • 这个模块有属于自己的HTML模板,也应该有属性自己的数据data
  • 组件中的数据是保存在哪里呢?顶层的Vue实例中吗?
    • 组件中不能直接访问Vue实例中的data
  • Vue组件应该有自己保存数据的地方

2、组件数据的存放

  • 组件自己的数据存放在哪里呢?
    • 组件对象也有一个data属性(也可以有methods等属性)
  • 只是这个data属性必须是一个函数
    • 而且这个函数的返回一个对象,对象内部保存着数据

3、为什么组件data必须是函数

  • 组件的设计,是为了使用模板,多处复用代码,方便快速搭建项目
  • 如果我们的data不是一个函数,函数不返回一个对象
  • 那么,我们复用的这一类型的所有组件的数据,都会随着一处的更改而全部都改,就没有独立性,这显示不是我们想要的
  • 然后我们data使用函数,返回一个对象,对象中装数据
  • 这样的话,我们每个组件的数据都会独立开辟一个空间存储自己的数据,组件间相同数据,互不影响

7.2 代码实战

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>07-为什么组件data必须是函数</title>
</head>
<body>

<div id="app">
  <my_count></my_count>
  <my_count></my_count>
  <my_count></my_count>
</div>
<template id="cpn">
  <div>
    <h2>当前计数:{{counter}}</h2>
    <button @click="increment">+</button>
    <button @click="decrement">-</button>
  </div>
</template>
<script type="text/javascript" src="../js/vue.js"></script>
<!--如果没有安装vue.js,就用下面的代码-->
<!--<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>-->
<script type="text/javascript">
  //1.注册全局组件
  Vue.component('my_count',{
    template:'#cpn',
    data(){
      return{
        counter:0
      }
    },
    methods:{
      increment(){
        this.counter++
      },
      decrement(){
        this.counter--
      }
    }

  })
  const vm = new Vue({
    el: '#app',
    data: {
    }
  })
</script>
</body>
</html>

7.3 运行结果

在这里插入图片描述

08-父子组件通信-父传子

8.1 父子组件的通信

  • 子组件是不能直接引用父组件或者Vue实例的数据的
  • 在开发中,往往一些数据确实需要从上层传递到下层
    • 比如在一个页面中,我们从服务器请求到了很多数据
    • 其中一些数据,并非是我们整个页面的大组件来展示的,而是需要下面的子组件进行展示
    • 这个时候,并不会让子组件再次发送一个一次网络请求,而是直接让大组件(父组件)将数据传递给小组件(子组件)
  • 如何进行父子组件间的通信呢?Vue官方提到
    • 通过props向子组件传递数据(父传子)
    • 通过自定义事件向父组件发送消息(子传父)
    • 在这里插入图片描述

8.2 props数据验证

  • props可以是一个数组,也可以是对象
  • 当需要对props进行类型验证时,就需要是对象写法了
  • 对象写法支持类型:
    • String
    • Number
    • Boolean
    • Array
    • Object
    • Date
    • Function
    • Symbol
  • 当我们有自定义构造函数时,验证也支持自定义类型

8.3 代码实战

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>08-父子组件通信-父传子</title>
</head>
<body>

<div id="app">
  <my_cpn :cmessage="message" :cmovies="movies"></my_cpn>
</div>
<template id="my_cpn">
  <div>
    <ul>
      <li v-for="movie in cmovies">{{movie}}</li>
    </ul>
    <p>{{cmovies}}</p>
    <p>{{cmessage}}</p>
  </div>
</template>
<script type="text/javascript" src="../js/vue.js"></script>
<!--如果没有安装vue.js,就用下面的代码-->
<!--<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>-->
<script type="text/javascript">
  // 定义局部组件
  const my_cpn ={
    template:'#my_cpn',
    // 传递数组
    // props:['cmovies','cmessage'],
    // 传递对象,控制传递类型的限制
    // 传递对象,提供一些默认值
    props:{
      // cmovies:Array,
      // cmessage:String,
      cmessage:{
        type: String,     // 限制类型
        default:"full",   // 设置默认值,默认值在没有传值的情况下,会自动显示默认值
        require:false     // 如果为True,那么就是必传值,不传就会报错
      },
      cmovies:{
        type:Array,
        default(){
          return []
        }
      }
    },
    data(){
      return{

      }
    }
  }

  const vm = new Vue({
    el: '#app',
    data: {
      message:'hello',
      movies:['海王','海贼王','海尔兄弟'],
    },
    components: {
      my_cpn
    }
  })
</script>
</body>
</html>

8.4 运行结果

在这里插入图片描述

8.5 props驼峰标识

  • 如果props使用的驼峰标识,在动态绑定的时候,不能直接绑定,在每个大写字母前面需要加一个-

8.6 代码实战

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>09-props驼峰标识</title>
</head>
<body>

<div id="app">
  
  <cpn :c-info="info"></cpn>
</div>
<template id="cpn">
  <h2>{{cInfo}}</h2>
</template>
<script type="text/javascript" src="../js/vue.js"></script>
<!--如果没有安装vue.js,就用下面的代码-->
<!--<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>-->
<script type="text/javascript">
  const cpn ={
    template:'#cpn',
    props:{
      //驼峰标识
      cInfo:{
        type:Object,
        default(){
          return{}
        }
      }
    }
  }

  const vm = new Vue({
    el: '#app',
    data: {
      info:{
        name:'key',
        age:20,
        height:1.83
      }
    },
    components:{
      cpn
    }
  })
</script>
</body>
</html>

8.7 运行结果

在这里插入图片描述

09-父子组件通信-子传父(自定义事件)

9.1 子级向父级传递

  • props用于父组件向子组件传递数据,还有一种比较常见的事子组件传递数据或事件到父组件中
  • 我们需要用自定义事件来完成
  • 什么时候需要自定义事件呢?
    • 当子组件需要向父组件传递数据时,就要用到自定义事件
    • v-on不仅仅可以用于监听DOM事件,也可以用于组件间的自定义事件
  • 自定义事件的流程:
    • 在子组件中,通过$emit()来监听事件
    • 在父组件中,通过v-on来监听子组件事件
  • 例子:
    • 我们之前做过两个按钮+1和-1,点击修改counter
    • 我们整个操作的过程还是在子组件中完成,但是之后的展示交给父组件
    • 这样,我们就需要将子组件中的counter,传给父组件的某个属性,比如total

9.2 代码实战

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>09-父子组件通信-子传父(自定义事件)</title>
</head>
<body>
<!--1.父组件模板-->
<div id="app">
  <cpn @itemclick="cpnclick"></cpn>
</div>
<!--2.子组件模板-->
<template id="cpn">
  <div>
    <!--    创建分类按钮,并监听点击-->
    <button v-for="item in categories" @click="itemclick(item)">
      {{item.name}}
    </button>
  </div>
</template>
<script type="text/javascript" src="../js/vue.js"></script>
<!--如果没有安装vue.js,就用下面的代码-->
<!--<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>-->
<script type="text/javascript">

  // 1.子组件
  const cpn = {
    template: '#cpn',
    data(){
      return{
        categories:[
          {id:'100',name:'热门推荐'},
          {id:'101',name:'手机数码'},
          {id:'102',name:'家用电器'},
          {id:'103',name:'电脑办公'},
        ]
      }
    },
    methods:{
      itemclick(item){
        console.log('子组件打印',item);
        //将item传给父组件,自定义
        //this.$emit('名称',传送参数)
        this.$emit('itemclick',item)
      }
    }
  }
  const vm = new Vue({
    el: '#app',
    data: {
      message: 'hello world!'
    },
    components:{
      cpn
    },
    methods:{
      cpnclick(item){
        console.log('父组件cpnclick打印',item);
      }
    }
  })
</script>
</body>
</html>

9.3 运行结果

在这里插入图片描述

10-父子组件通信-结合双向绑定

10.1 实现父组件与子组件之间的双向绑定

10.2 代码实战

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>10-父子组件通信-结合双向绑定</title>
</head>
<body>

<div id="app">
  <cpn :number1="num1"
       :number2="num2"
       @num1change="num1change"
       @num2change="num2change" >
  </cpn>
</div>
<template id="cpn">
  <div>
    <!--    使用data中的计算属性进程改动数据,双向绑定-->
    <h2>props:{{number1}}</h2>
    <h2>data:{{dnumber1}}</h2>
    <!--    单向绑定,只绑定子组件的数据-->
    <input type="text" v-model="dnumber1">   单向绑定,只绑定子组件的数据
    <hr>
    <!--<input type="text" :value="dnumber1" @input="dnumber1=$event.target.value"> 双向绑定-->
    <!--    @input后面太长了 可以写成函数-->
    <input type="text" :value="dnumber1" @input="num1Input"> 双向绑定
    <h2>props:{{number2}}</h2>
    <h2>data:{{dnumber2}}</h2>
    <input type="text" v-model="dnumber2">   单向绑定,只绑定子组件的数据
    <hr>
    <input type="text" :value="dnumber2" @input="num2Input">双向绑定
    <!--    单向绑定,只绑定子组件的数据-->
    <!--    <input type="text" v-model="dnumber2">-->
    <!--    直接绑定,Vue不支持-->
    <!--    <h2>{{number1}}</h2>-->
    <!--    <input type="text" v-model="number1">-->
    <!--    直接绑定,Vue不支持-->
    <!--    <h2>{{number2}}</h2>-->
    <!--    <input type="text" v-model="number2">-->
  </div>
</template>
<!--<script type="text/javascript" src="../js/vue.js"></script>-->
<!--如果没有安装vue.js,就用下面的代码-->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script type="text/javascript">
  // 局部组件
  const cpn = {
    template:'#cpn',
    props:{
      //如果只是想直接展示的话,就可以直接用
      //如果要改数据的话,最好是放在data中用计算属性更改
      number1:Number,
      number2:Number
    },
    data(){
      return{
        dnumber1:this.number1,
        dnumber2:this.number2
      }
    },
    methods:{
      num1Input(){
        this.dnumber1 = event.target.value;
        this.$emit('num1change',this.dnumber1)
      },
      num2Input(){
        this.dnumber2 = event.target.value;
        this.$emit('num2change',this.dnumber2)
      }
    }
  }
  const vm = new Vue({
    el: '#app',
    data: {
      num1:1,
      num2:0
    },
    methods: {
      num1change(value){
        this.num1 = parseFloat(value)
      },
      num2change(value){
        this.num2 = parseFloat(value)
      }
    },
    components:{
      cpn
    }
  })
</script>
</body>
</html>

10.3 运行结果

在这里插入图片描述

11-父组件访问子组件-children-refs

11.1 父子组件的访问方式:$children $refs

  • 有时候我们需要父组件直接访问子组件,子组件直接访问父组件,或者是子组件访问根组件
  • 父组件访问子组件:使用$ children或者$ refs

11.2 代码实战

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>11-父组件访问子组件-children-refs</title>
</head>
<body>

<div id="app">
  <cpn ref="aaa"></cpn>
  <cpn></cpn>
  <cpn ref="ccc"></cpn>
  <button @click="btnClick">按钮</button>
</div>
<template id="cpn">
  <div>我是子组件</div>
</template>
<script type="text/javascript" src="../js/vue.js"></script>
<!--如果没有安装vue.js,就用下面的代码-->
<!--<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>-->
<script type="text/javascript">
  const vm = new Vue({
    el: '#app',
    data: {
    },
    methods: {
      btnClick(){
        // 1. 真实开发中,一般不用$children==========》数组类型
        console.log(this.$children);
        this.$children[0].showMessage();
        console.log(this.$children[0].name);
        for (let c of this.$children){
          console.log(c);
          c.showMessage();
        }
        // 2.通过$refs拿取数据=====>对象类型,默认是一个空的对象
        // console.log(this.$refs);
        // console.log('aaa组件',this.$refs.aaa);
        // console.log('ccc组件',this.$refs.ccc);
      }
    },
    components: {
      cpn: {
        template: '#cpn',
        data() {
          return {
            name: "我是子组件的name"
          }
        },
        methods: {
          showMessage() {
            console.log("showMessage");
          }
        }
      }
    }
  })
</script>
</body>
</html>

11.3 运行结果

在这里插入图片描述

在这里插入图片描述

12-子组件访问父组件-parent-root

12.1 子访问父方式

  • 有时候我们需要父组件直接访问子组件,子组件直接访问父组件,或者是子组件访问根组件
  • 子组件访问父组件:使用$ parent
  • 子组件访问根组件:使用$ root

12.2 代码实战

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>12-子组件访问父组件-parent-root</title>
</head>
<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 type="text/javascript" src="../js/vue.js"></script>
<!--如果没有安装vue.js,就用下面的代码-->
<!--<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>-->
<script type="text/javascript">
  const vm = new Vue({
    el: '#app',
    data: {
      message: 'hello world!'
    },
    components: {
      cpn: {
        template: '#cpn',
        data() {
          return {
            name: "我是cpn组件的name"
          }
        },
        components: {
          //开发中一般不建议这样使用,会让组件不够独立,复用性降低,耦合度太高了
          ccpn: {
            template: "#ccpn",
            methods: {
              btnClick() {
                //1.访问父组件 $parent
                console.log(this.$parent);
                console.log(this.$parent.name);
                // 2.访问根组件  $root
                console.log(this.$root);
                console.log(this.$root.message);
              }
            },
          },
        }
      }
    }
  })
</script>
</body>
</html>

12.3 运行结果

在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值