IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> JavaScript知识库 -> Vue 组件化学习(组件的基本使用,组件之间的数据传递,插槽slot) -> 正文阅读

[JavaScript知识库]Vue 组件化学习(组件的基本使用,组件之间的数据传递,插槽slot)

  1. 什么是组件?
    组件是一个单独功能模块的封装,有属于自己的HTML模板,也应该有属于自己的数据data ,还有methods;组件模板必须有一个根(常用div)

  2. 组件的基本使用:(含语法糖,含模板抽离,含对象抽离)这里是局部组件注册方式

    基本步骤就是: 先创建一个组件mycpn,在里面写一个模板 template ,template通过 id 分离到页面上,之后将组件
    mycpn 放到 vue实例对象里面的components 属性里面 进行注册,这样就可以在页面中直接使用mycpn这个组件了

     ```javascript
     <body>
       <!-- 在这里我们就不使用 Vue.extend()方法创建组件构造器了 -->
       <div id="app">
         <mycpn></mycpn>
       </div>
       <template id="cpn">
         <!-- 在子组件模板里需要一个根 这个根我们可以搞个div -->
         <div>
           <h3>这是我创建的第一个组件 组件名为 mycpn 以后就使用这个方式来创建使用组件</h3>
         </div>
       </template>
     
       <script>
         //  注册组件  使用语法糖
         const mycpn = {
           // 子组件将数据存放在data中 且 data属性为一个函数
           // 原因:如果data是一个对象,所有组件都会用一个data,就会产生连锁反应(组件的复用),使用函数每次都会返回新的对象,不会产生影响
           data() {
             return {
             }
           },
           template: '#cpn',
           methods: {},
           components: {}
         }
         const app = new Vue({
           el: '#app',
           data: {},
           methods: {},
           components: {
             // 对象字面量属性增强写法
             mycpn
           }
         });
       </script>
    
  3. 全局组件和局部组件
    全局组件 使用 Vue.component() 方法
    局部组件在vue实例里面创建 components 里面注册

      <body>
     	  <div id="app">
     	    <mycpn></mycpn>
     	    <hr>
     	    <mycpn1></mycpn1>
     	  </div>
     	  <template id="cpn">
     	    <div>
     	      <h4>这是全局组件的注册方式</h4>
     	    </div>
     	  </template>
     	  <template id="cpn1">
     	    <div>
     	      <h4>这是局部组件的注册方式</h4>
     	    </div>
     	  </template>
     	  <script>
     	    // 1.全局组件 使用 Vue.component() 方法
     	    Vue.component('mycpn', {
     	      template: '#cpn'
     	    })
     	    // 2.局部组件在vue实例里面创建 components 里面注册
     	    const app = new Vue({
     	      el: '#app',
     	      data: {},
     	      methods: {},
     	      components: {
     	        mycpn1: {
     	          template: '#cpn1'
     	        }
     	      }
     	      // 也可以将 mycpn1 组件抽出去 写成 const mycpn1 = { template: '#cpn1'}
     	    });
     	  </script>
     	</body>
    
  4. 父组件和子组件
    按我自己的理解就是:有俩个组件(组件1和组件2),组件 1 ,2 分别有自己的模板template,组件1放到组件2里面注册(components下面)在这里插入图片描述然后组件2 放到vue实例里面注册。二者都注册完之后,特别注意:组件1要在组件2模板里使用
    在这里插入图片描述之后将组件2放到页面上使用时,就可以看到组件1和组件2。这就是所谓的父子组件,其中组件1为组件2的孩子。

     <body>
       <div id="app">
         <mycpn></mycpn>
       </div>
       <template id="cpn">
         <div>
           <h3>我是父组件</h3>
           <hr>
           <!-- 注意: 子组件注册完之后 要在父模板里使用 这样当父组件加载到页面上时才能将子组件显示出来 -->
           <cpn1></cpn1>
         </div>
       </template>
       <template id="ccpn">
         <div>
           <h3>我是子组件</h3>
         </div>
       </template>
       <script>
         const cpn1 = {
           template: '#ccpn'
         }
         // 将cpn1 组件放到 mycpn 里面注册 mycpn组件放到 Vue实例里面注册 
         const mycpn = {
           template: '#cpn',
           components: {
             cpn1
           }
         }
         const app = new Vue({
           el: '#app',
           data: {},
           methods: {},
           components: {
             mycpn
           }
         });
       </script>
     </body>
    
  5. 组件中数据的存放问题(data 属性里面存)

    1. 组件是不能直接访问Vue实例对象里面的数据的 ;

    2. 组件有自己存放数据的地方 data属性 ;

    3. 只不过 data 是一个函数而且返回的是一个对象 对象里面存放数据

    4. 原因:Vue让每个组件对象都返回一个新的对象,因为如果是同一个对象的,组件在多次使用后会相互影响。

      <body>
        <div id="app">
          <cpn></cpn>
        </div>
        <template id="cpn">
          <div>
            <h3>这是组件,现在我需要获取组件的数据</h3>
            <span>这是子组件里面的数据:{{students}}</span>
            <ul>
              <h4>这是获取组件里面的数组对象数据</h4>
              <li v-for='items in books'>{{items.name}} {{items.price}}</li>
            </ul>
          </div>
        </template>
        <script>
          const cpn = {
            template: '#cpn',
            data() {
              return {
                // 存放一个对象
                students: {
                  name: '方敬',
                  age: 22,
                  height: 180
                },
                // 存放一个数组对象
                books: [{
                  id: 01,
                  name: '斗罗大陆',
                  price: '$180.00'
                },
                {
                  id: 02,
                  name: '斗破苍穹',
                  price: '$189.00'
                },
                {
                  id: 03,
                  name: '武动乾坤',
                  price: '$182.00'
                }
                ]
              }
            }
          }
          const app = new Vue({
            el: '#app',
            data: {},
            methods: {},
            components: {
              cpn
            }
          });
        </script>
      </body>
      
  6. 组件通信—父组件向子组件传递数据
    方法: 在子组件中通过 props 来声明接收父组件的数据
    props 的值有俩种方式:
    方式一:字符串数组,数组中的字符串就是传递时的名称。
    方式二:对象,对象可以设置传递时的类型,也可以设置默认值等。

    对象方法用的较多(在子组件<mycpn></mycpn>用v-bind绑定传值 : 子组件的数据=父组件的数据,:mymessage=‘message’ )
    在这里插入图片描述

    方式一:字符串数组

     <body>
       <div id="app">
         <mycpn :mymessage='message'></mycpn>
       </div>
       <template id="cpn">
         <div>
           <!-- join 将数组转换成字符串 -->
           <h4>这是从父组件接收过来的数组数据:{{mymessage.join()}}</h4>
         </div>
       </template>
       <script>
         // 父组件向子组件传递数据
         // 方法: 在子组件中通过 props 来声明接收父组件的数据
         // props 的值有俩种方式:方式一:字符串数组,数组中的字符串就是传递时的名称。
         //方式二:对象,对象可以设置传递时的类型,也可以设置默认值等。
         const mycpn = {
           template: '#cpn',
           // 声明需要从父亲接收到的数据
           props: ['mymessage']
         }
         const app = new Vue({
           el: '#app',
           data: {
             // 字符串数组
             message: ['方敬是', '傻逼'],
           },
           methods: {},
           components: {
             mycpn
           }
         });
       </script>
     </body>
    

    方式二:对象

     <body>
       <div id="app">
         <mycpn :cmessage='cmessage'></mycpn>
       </div>
       <template id="cpn">
         <div>
           <!-- join 将数组转换成字符串 -->
           <h4>这是从父组件接收过来的对象数据: {{cmessage.name}} {{cmessage.age}}</h4>
         </div>
       </template>
       <script>
         // 父组件向子组件传递数据
         const mycpn = {
           template: '#cpn',
           // 声明需要从父亲接收到的数据
           props: {
             cmessage: {
               type: Object,
               default() {
                 return {}
               }
             }
           }
         }
         const app = new Vue({
           el: '#app',
           data: {
             cmessage: {
               name: '刺客短裤',
               age: 18
             }
           },
           methods: {},
           components: {
             mycpn
           }
         });
       </script>
     </body>
    
  7. 组件通信—子组件向父组件传递 数据/事件(通过自定义事件
    在子组件中,通过$emit()来触发事件。

    在父组件中,通过v-on来监听子组件事件。

    在这里插入图片描述

    需求:我们之前做过一个两个按钮+1和-1,点击后修改counter。 我们整个操作的过程还是在子组件中完成,但是之后的展示交给父组件。
    这样,我们就需要将子组件中的counter,传给父组件的某个属性,比如total。

     <body>
       <div id="app">
         <!-- v-on 监听自定义事件 -->
         <childcpn @increment='totalChange' @decrement='totalChange'></childcpn>
         <h3>点击次数 : {{total}}</h3>
       </div>
       <template id="cpn">
         <div>
           <h3>计数:{{counter}}</h3>
           <button @click='increment'>+</button>
           <button @click='decrement'>-</button>
         </div>
       </template>
       <script>
         // 子组件向父组件传递 数据/事件 通过自定义事件
         // 在子组件中,通过$emit()来触发事件。
         // 在父组件中,通过v-on来监听子组件事件。
         const childcpn = {
           template: '#cpn',
           data() {
             return {
               counter: 0
             }
           },
           methods: {
             increment() {
               this.counter++
               // 在这里使用 $emit 来触发increment事件 并将数据传过去 在父组件中使用v-on来监听子组件事件
               this.$emit('increment', this.counter)
             },
             decrement() {
               this.counter--
               // 在这里使用 $emit 来触发increment事件 并将数据传过去  在父组件中使用v-on来监听子组件事件
               this.$emit('decrement', this.counter)
             }
           }
         }
         const app = new Vue({
           el: '#app',
           data: {
             total: 0
           },
           methods: {
             // 监听事件之后 在父组件里来接收数据
             totalChange(counter) {
               this.total = counter
             }
           },
           components: {
             childcpn
           }
         });
       </script>
     </body>
    
  8. 组件访问—父组件访问子组件($refs,少用 $children)
    $refs的使用

    1. $refs和ref指令通常是一起使用的。
    2. 首先,我们通过ref给某一个子组件绑定一个特定的ID。在父组件模板里,找到子组件的使用并绑上ID。
    3. 其次,通过this.$refs.ID就可以访问到该组件了。

    在这里插入图片描述

     <body>
       <div id="app">
         <childcpn1 ref='child1'></childcpn1>
         <childcpn2 ref='child2'></childcpn2>
         <button @click='showmessge()'>点击</button>
       </div>
       <template id="cpn1">
         <div>
           <h3>我是第一个孩子 哈哈哈哈哈</h3>
         </div>
       </template>
       <template id="cpn2">
         <div>
           <h3>我是第二个孩子 嘻嘻嘻嘻嘻</h3>
         </div>
       </template>
       <script>
         // 通过 $refs 来访问子组件 给子组件绑定 ref 相当于id
         const childcpn1 = {
           template: '#cpn1',
           data() {
             return {
               message: '方敬是傻逼'
             }
           },
           methods: {
             bnClick() {
               console.log('......点击了');
             }
           }
         }
         const childcpn2 = {
           template: '#cpn2',
           data() {
             return {
               message: '方敬不是傻逼'
             }
           }
         }
         const app = new Vue({
           el: '#app',
           data: {},
           methods: {
             showmessge() {
               console.log(this.$refs.child1.message);
               // 调用第一个孩子的方法
               console.log(this.$refs.child1.bnClick());
               console.log(this.$refs.child2.message);
             }
           },
           components: {
             childcpn1,
             childcpn2
           }
         });
       </script>
     </body>
    
  9. 组件访问—子组件访问父组件($root 直接访问祖宗,避免多重套娃的连锁反应 少用 $parent)子访问父 在子模板里写操作
    在这里插入图片描述

  10. slot 插槽的基本使用
    作用:以让使用者根据自己的需求,决定插槽中插入什么内容 是搜索框,还是文字,还是菜单。由调用者自己来决定
    使用: 就是在子组件的模板里添加一个 <slot></slot> 标签

    <body>
     <div id="app">
       <mycpn>
         <a href="">百度</a>
       </mycpn>
       <mycpn>
         <h3>这是我替换插槽的内容 哈哈哈哈哈</h3>
       </mycpn>
       <mycpn></mycpn>
     </div>
     <template id="cpn">
       <div>
         <h4>下面是插槽哦,里面的内容可以替换</h4>
         <slot>我是插槽哦,我可以被替换成其他哦</slot>
         <hr>
       </div>
     </template>
     <script>
       // 插槽的作用: 可以让使用者根据自己的需求,决定插槽中插入什么内容 是搜索框,还是文字,还是菜单。由调用者自己来决定
       const mycpn = {
         template: '#cpn'
       }
       const app = new Vue({
         el: '#app',
         data: {},
         methods: {},
         components: {
           mycpn
         }
       });
     </script>
    
  11. 具名插槽的使用(这里使用Vue 3 的 v-slot )
    注意: v-slot 是在组件里面添加一个 template 标签 然后在这个标签里写v-slot 并不是在 模板里面写v-slot v-slot: 的语法糖为 #
    在这里插入图片描述在这里插入图片描述注:区分俩个template的不同

  12. 作用域插槽 (父组件替换插槽的标签,但是内容由子组件来提供)
    使用场景:父组件向子组件拿数据
    我们选择将包含所有插槽prop的对象命名为 slotProps
    需求:

    子组件中包括一组数据,比如:pLanguages: [‘JavaScript’, ‘Python’, ‘Swift’, ‘Go’,‘C++’]
    需要在多个界面进行展示: 某些界面是以水平方向一一展示的, 某些界面是以列表形式展示的, 某些界面直接展示一个数组

    这里也使用 Vue3 的 v-slot:default = 'slotProps' 子组件模板template里的 slot 用 :data='子组件里的数据' 来绑定数据
    在这里插入图片描述

    <body>
      <div id="app">
        <mycpn>
          <!-- 水平显示 -->
          <template v-slot:default='slotProps'>
            <!-- join() 将数组转换成字符串 -->
            <span>{{slotProps.data}}</span>
            <span>{{slotProps.data.join()}}</span>
          </template>
        </mycpn>
        <mycpn>
          <!-- 列表形式显示 -->
          <template v-slot:default='slotProps'>
            <ul>
              <li v-for='item in slotProps.data'>{{item}}</li>
            </ul>
          </template>
        </mycpn>
      </div>
      <template id="cpn">
        <div>
          <slot :data='pLanguages'></slot>
          <hr>
        </div>
      </template>
      <script> 
        const mycpn = {
          template: '#cpn',
          data() {
            return {
              pLanguages: ['JavaScript', 'Python', 'Swift', 'Go', 'C++']
            }
          }
        }
        const app = new Vue({
          el: '#app',
          data: {},
          methods: {},
          components: {
            mycpn
          }
        });
      </script>
    </body>
    

    在这里插入图片描述

  13. 编译的作用域
    父组件模板的所有东西都会在父级作用域内编译;
    子组件模板的所有东西都会在子级作用域内编译;
    就近原则,往上查 。
    在谁家用谁的东西,在vue模板就去找vue实例 ,组件的模板找自己的作用域。

  14. 不懂就看官方文档:https://v3.cn.vuejs.org/

  JavaScript知识库 最新文章
ES6的相关知识点
react 函数式组件 & react其他一些总结
Vue基础超详细
前端JS也可以连点成线(Vue中运用 AntVG6)
Vue事件处理的基本使用
Vue后台项目的记录 (一)
前后端分离vue跨域,devServer配置proxy代理
TypeScript
初识vuex
vue项目安装包指令收集
上一篇文章      下一篇文章      查看所有文章
加:2021-07-27 16:07:20  更:2021-07-27 16:09:13 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/5 0:29:25-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码