【vue2】组件进阶与插槽详解

这篇具有很好参考价值的文章主要介绍了【vue2】组件进阶与插槽详解。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

vue2具名插槽,vue2,开发语言,前端,vue.js,vue,前端框架

🥳博       主:初映CY的前说(前端领域)

🌞个人信条:想要变成得到,中间还有做到!

🤘本文核心:v-modedl表单双向绑定、ref|$ref操作dom、dynamic动态组件、$nextTick同步、匿名插槽、具名插槽、作用域插槽


目录(文末有给大家准备好的Xmind思维导图)

一、组件进阶

1.v-model语法

2.ref与$ref语法

3.dynamic动态组件

4.this.$nextTick()

二、匿名|具名|作用域插槽

插槽概念:

1.匿名插槽

2.具名插槽

3.作用域插槽


一、组件进阶

1.v-model语法

v-model指令我们的一个初印象就是表单数据实现绑定双向,一修改同步修改,那么本质是什么?

博主认为v-mode语法本质上是简化了书写操作。触发v-model需要满足两个条件的(标红部分是语法规定部分不可自定义)

  1. data中数据变化,表单的值也会变化  :value="data中的属性名" 
  2. 表单的值发生变化,data中的数据也会变化  @input="data中的属性名=$event.target.value"

当满足了就可直接写上v-model="我们data中的属性名"

举个例子:

<template>
  <div>
    <h1>根组件App.vue</h1>
    <!-- 
      1.v-model = "msg"
        (1)data中的数据变化,表单的值也会变化     :value="msg"
        (2)表单的值发生变化,data中的数据也会变化  @input="msg=$event.target.value"
    -->
    <input type="text" v-model="msg" />
    <hr />
    <!-- 这种写法与上面写法功能一致 -->
    <input type="text" :value="msg" @input="msg = $event.target.value" />
    <hr />
    <!-- 这种写法也与上面写法一致 -->
    <input type="text" :value="msg" @input="doInput" />
    <hr />
  </div>
</template>

<script>
export default {
  data() {
    return {
      msg: ""
    };
  },
  methods: {
    doInput(e) {
      this.msg = e.target.value;
    }
  }
};
</script>

<style>
</style>

 效果演示:

vue2具名插槽,vue2,开发语言,前端,vue.js,vue,前端框架

 可见:当我们直接用v-model="属性名“这种方法写简化了书写的难度达到了同样的效果。


2.ref与$ref语法

这个语法可使用操作dom元素。每个 vue 的组件实例上,都包含一个$refs 对象,里面存储着对应的DOM 元素或组件的引用。

注意点:

当ref="自定义名"是写在组件身上就可以得到该对象实例vue

绑定是ref,调用是$refs

1.绑定dom写法:<标签 ref="自定义名"></标签>

    <div ref="aaa" class="box"></div>
    <input ref="bbb" type="text">
    <my-goods ref="ccc" ></my-goods>

2.调用dom写的:this.$refs.自定义属性名 

console.log(this.$refs.aaa);
console.log(this.$refs.bbb);
console.log(this.$refs.ccc);
// 调用子组件方法
console.log(this.$refs.ccc.doClick());//都包含一个$refs 对象因此可已获取标签里面的方法(组件)

参考下面这个例子:

父组件:App.vue

<template>
  <div>
    <h1>我是父组件</h1>
    <button @click="onAdd">点我查看ref打印的啥</button>
    <div ref="aaa" class="box"></div>
    <input ref="bbb" type="text">
    <my-goods ref="ccc" ></my-goods>
  </div>
</template>

<script>
import MyGoods from '@/components/MyGoods.vue'
export default {
  components: { MyGoods },
  data() {
    return {
    }
  },
  methods: {
    onAdd() {
      console.log(this);
      console.log(this.$refs.aaa);
      console.log(this.$refs.bbb);
      console.log(this.$refs.ccc);
      // 调用子组件方法
      console.log(this.$refs.ccc.doClick());
    },
  }
}
</script>

<style>

</style>

子组件:MyGoods.vue

<template>
  <div>
    <p>商品名称:小米</p>
    <p>商品价格:{{ price }}</p>
    <button @click="doClick">点我购买</button>
  </div>
</template>

<script>
export default {
props:{
    value:Number
},
data(){
  return{
    price:'999'
  }
},
    methods: {
        doClick() {
            console.log("点击了购买");
            return 0//当不写的时候调用了方法没有return会提示undefinded
    }
}
}
</script>

<style>

</style>

实现效果:

vue2具名插槽,vue2,开发语言,前端,vue.js,vue,前端框架


3.dynamic动态组件

什么是动态组件: 让多个组件使用同一个挂载点并动态切换,这就是动态组件。

通过设置组件名,让一个挂载点可以切换不同的组件。

语法格式:

 <component :is="组件名"></component>

举个例子:

父组件App.vue

<template>
  <div>
    <h1>我是父组件</h1>
    <button @click="comName='login'">登录</button>
    <button @click="comName='user'">信息</button>
    <component :is="comName"></component>
  </div>
</template>
<script>
import login from '@/components/login.vue'
import user from '@/components/user.vue'

export default {
  components: { login, user },
  data() {
    return {
    comName:"user"
  }
}
}
</script>

<style>

</style>

子组件 user.vue

<template>
  <div>
    <p>我是个人信息组件</p>
  </div>
</template>
<script>
export default {
name:"user"
}
</script>
<style>
</style>

子组件 login.vue

<template>
  <div>
    <p>我是登录组件</p>
  </div>
</template>
<script>
export default {
name:"login"
}
</script>
<style>
</style>

实现效果:

vue2具名插槽,vue2,开发语言,前端,vue.js,vue,前端框架

 可以看到我们通过<component :is="组件名">找到相应的标签运行


4.this.$nextTick()

是用来将我们vue的异步操作进行放在页面dom渲染前面。想要在修改数据后立刻得到更新后的DOM结构,可以使用Vue.nextTick()

上个例子:

<template>
  <div>
    <h1>我是父组件</h1>
    <input type="text" v-if="flag" ref="input">
    <button v-else @click="doClick">点我开始输入</button>
  </div>
</template>

<script>
export default {
  data() {
    return {
      flag: false
    }
  },
  methods: {
    doClick() {
      this.flag = true//异步操作,生命周期中修改阶段
      this.$nextTick(
        () => {//一定要箭头函数,因为箭头函数的this指向上一层作用域与原本的this是同一个
          this.$refs.input.focus()
        }
      )
    }
  }
}
</script>

<style>

</style>

 实现的效果:

vue2具名插槽,vue2,开发语言,前端,vue.js,vue,前端框架

当 this.flag = true执行完成之后页面应该是执行渲染在页面的操作,但是我们的 vue是异步的微任务(Vue将开启一个异步更新队列,视图需要等队列中所有数据变化完成之后,再统一进行更新),渲染的时候找不到ref="input"这个dom就会报错,因此需要就用  this.$nextTick来将需要的操作放在渲染之前。

vue2具名插槽,vue2,开发语言,前端,vue.js,vue,前端框架

 可看上图:当我写在外面的时候就会报错。

原理:vue操作dom是异步的操作,如果需要同步显示出来需要利用this.$nextTick()将异步操作提前放在dom树更新后,页面渲染前


二、匿名|具名|作用域插槽

插槽概念:

  • slot相当于是组件里面的一个内置的开关,打开了这个开关就可以在复用组件的同时修改单个组件中的HTML的结构。
  • 用来解决组件复用的同时可以对单个组件进行修改操作,让组件变得更加灵活

1.匿名插槽

我们在父中调用子组件,在复用组件的同时修改单个组件不受影响

插槽书写结构:   

父传:<子组件名>HTML结构</子组件名>

子收: <slot>此处写默认值</slot>

我们一起来看看这个例子:

父组件:App01(匿名插槽).vue

<template>
  <div>
    <h1>我是父组件</h1>
    <goods><button>已下单</button></goods>
    <goods></goods>
    <goods ><button disabled>已卖完</button></goods>
    <goods><a href="#">点我跳转</a></goods>

  </div>
</template>

<script>
import goods from '@/components/goods.vue'
export default {
components:{goods}
}
</script>

<style>

</style>

 子组件:goods.vue

<template>
  <div class="son">
    <h3>我是子组件</h3>
    <h4>商品名称</h4>
    <!-- slot相当于是一个开关,打开了这个开关就可以插入想要的值
    从父传 HTML的结构 -->
    <slot>我是默认的插槽</slot>
  </div>
</template>

<script>
export default {
  name: "goods",
  data() {
    return {}
  }
}
</script>

<style scoped>
.son {
  border: 1px solid red;
}
</style>

我们先看下我们的实现效果:

vue2具名插槽,vue2,开发语言,前端,vue.js,vue,前端框架

 可以看出来,我们的<goods></goods>调用了四次,我们在父中的值传到子中的都不一样,页面也根据我们所想的展示出来了不同的组件。


2.具名插槽

使用多个slot实现精准的传递多个位置的插槽给子组件 ,写的时候必须在<template></template>中

具名插槽书写结构: 

父传:


 <组件名>
      <template v-slot:自定义名>
        <h2>HTML结构</h2>
      </template>
 </组件名>

子收:

      <div >
          <slot name="自定义插槽名">插槽默认值</slot>
      </div>

我们一起来看看这个例子:

父组件:App02(具名插槽).vue

<template>
  <div>
    <h1>我是父组件</h1>
    <cell>
      <template v-slot:title>
        <h2>I am Tittle</h2>
      </template>
      <template v-slot:content>
        <i>I am goodsInfo</i>
      </template>
      <template v-slot:right>
        <i>My position</i>
      </template>
    </cell>
  </div>
</template>

<script>
import cell from '@/components/cell.vue'

export default {
components:{cell}
}

</script>

<style>

</style>

 子组件:cell.vue

<template>
  <div class="cell">
<!-- 
    具名插槽使用:
      1.在子组件钟使用 slot+name确定组件的作用域
      2.在父组件钟用template 接收 使用v-slot:name传递
 -->

      <div class="title" >
          <slot name="title">我是默认标题</slot>
      </div>
      <div class="content" >
        <slot name="content"> 我是文本信息</slot>
          
      </div>
      <div class="right" >
        <slot name="right">我是右侧信息</slot>
          
      </div>
  </div>
</template>

<script>
export default {

}
</script>

<style>
    .cell{
        border: 1px solid #f00;
        height: 60px;
        padding: 10px;
        position: relative;
    }

    .title{
        float: left;
        line-height: 1px;
    }

    .content{
        position: absolute;
        bottom: 10px;
        left: 10px;
    }

    .right{
        float: right;
    }
</style>

 实现效果:

vue2具名插槽,vue2,开发语言,前端,vue.js,vue,前端框架

 通过这个例子,我们可以看到,我们具名比匿名插槽多了一个精准定位的功能。

3.作用域插槽

父组件可根据子组件传过来的插槽数据来进行不同的方式展现和填充插槽内容

作用域插槽书写结构: 

子组件传递:

    <slot 属性名="属性值">默认值</slot>

父组件接收:(注意接收的是一个对象)

    <组件名 父传值属性>
      <template v-slot="{一个对象}">
        HTML属性
      </template>
    </组件名>

来个例子:

父组件:App03(作用域插槽).vue

<template>
  <div>
    <!-- 
        1.匿名插槽:父组件传递 单个HTML结构 给子组件
            父传:<子组件>HTML结构</子组件>
            子收:<slot>默认HTML结构</slot>
        2.具名插槽:父组件传递 多个HTML结构 给子组件
            父传:
                <子组件>
                    <template #插槽名>
                        HTML结构
                    </template>
                </子组件> 
            子收:<slot name="插槽名">默认HTML结构</slot>
        3.作用域插槽:子组件传递数据给父组件
            子传:<slot 属性名="属性值">默认HTML结构</slot>
            父收:
                <子组件>
                    <template v-slot="对象名">
                        HTML结构
                    </template>
                </子组件> 
     -->
    <!-- (具名插槽 + 作用域插槽)组合写法:#插槽名 = "对象名" -->
    <h1>父组件</h1>
    <student></student>

    <h3>删除功能</h3>
    <student :arr="list1">
      <template v-slot="{ $index }">
        <button @click="list1.splice($index, 1)">删除</button>
      </template>
    </student>
    <h3>头像功能</h3>
    <student :arr="list2">
      <template v-slot="{ row }">
        <img :src="row.headImgUrl" alt="" />
      </template>
    </student>
  </div>
</template>

<script>
import student from "./components/student.vue";
export default {
  components: { student },
  data() {
    return {
      list1: [
        {
          id: "13575",
          name: "小传同学",
          age: 18,
          headImgUrl:
            "http://yun.itheima.com/Upload/./Images/20210303/603f2d2153241.jpg",
        },
        {
          id: "62408",
          name: "小黑同学",
          age: 25,
          headImgUrl:
            "http://yun.itheima.com/Upload/./Images/20210304/6040b101a18ef.jpg",
        },
        {
          id: "73969",
          name: "智慧同学",
          age: 21,
          headImgUrl:
            "http://yun.itheima.com/Upload/./Images/20210302/603e0142e535f.jpg",
        },
      ],
      list2: [
        {
          id: "13575",
          name: "传同学",
          age: 8,
          headImgUrl:
            "http://yun.itheima.com/Upload/./Images/20210303/603f2d2153241.jpg",
        },
        {
          id: "62408",
          name: "黑同学",
          age: 5,
          headImgUrl:
            "http://yun.itheima.com/Upload/./Images/20210304/6040b101a18ef.jpg",
        },
        {
          id: "73969",
          name: "慧同学",
          age: 1,
          headImgUrl:
            "http://yun.itheima.com/Upload/./Images/20210302/603e0142e535f.jpg",
        },
      ],
    };
  },
};
</script>

<style>
</style>

子组件: student.vue

<template>
  <div>
    <slot name="title" >修改</slot>
    <table border="1">
      <thead>

          <tr>
            <th>序号</th>
            <th>姓名</th>
            <th>年龄</th>
            <th>头像</th>
          </tr>
      </thead>
      <tbody>
        <tr v-for="(item,index) in arr" :key="item.id">
          <td>{{ index+1 }}</td>
          <td>{{ item.name }}</td>
          <td>{{ item.age }}</td>
          <td>
            <slot :row="item" :$index="index"></slot>
          </td>
        </tr>
      </tbody>
    </table>
  </div>
</template>

<script>
export default {
  props: { arr: Array },
  data() {
    return {}
  }
}
</script>

<style scoped>
table {
  margin-top: 20px;
}

td {
  height: 60px;
}

img {
  height: 90%;
}
</style>

效果如下:vue2具名插槽,vue2,开发语言,前端,vue.js,vue,前端框架

 可以看见,我们复用的三个student的组件都分别实现了不同的效果,第一个因为我没有将父组件中的arr传进去,因此arr提示undefin,后面两个组件分别实现了不同的功能。对比具名插槽,作用域插槽实现了

总结匿名|具名|作用域函数:

匿名插槽:插槽可以实现组件复用的同时显示不同的内容

具名插槽:slot开关可以写多个,并且可以精准定位到我们想要的位置

作用域插槽:子组件可以传递数据给父组件


vue2具名插槽,vue2,开发语言,前端,vue.js,vue,前端框架

好了,兄弟姐妹们,本文结束喽!如果有未知的疑问,大家留言我会尽我所能帮助大家

下篇文章将讲解【路由】的使用,本专栏将持续更新,欢迎关注~ 文章来源地址https://www.toymoban.com/news/detail-779134.html

到了这里,关于【vue2】组件进阶与插槽详解的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • vue2 自定义指令,插槽

    1.自定义指令 基本语法(全局、局部注册) 指令的值 v-loading的指令封装 2.插槽 默认插槽 具名插槽 作用域插槽 1.指令介绍 内置指令: v-html、v-if、v-bind、v-on … 这都是Vue给咱们内置的一些指令,可以直接使用 自定义指令:同时Vue也支持让开发者,自己注册一些指令。这些指

    2024年02月11日
    浏览(44)
  • Vue2(组件开发)

    前言 上一章博客我们讲解了Vue生命周期,列表过滤,计算属性和监听器 这一章我们来讲Vue组件开发 一,组件的使用 创建组件两种方式 组件的分类 通用组件(例如表单、弹窗、布局类等) (多个项目都可以复用) 业务组件(抽奖、机器分类)(本项目中复用) 页面组件(单页面

    2024年02月12日
    浏览(29)
  • Vue2向Vue3过度核心技术插槽

    1.作用 让组件内部的一些 结构 支持 自定义 2.需求 将需要多次显示的对话框,封装成一个组件 3.问题 组件的内容部分, 不希望写死 ,希望能使用的时候 自定义 。怎么办 4.插槽的基本语法 组件内需要定制的结构部分,改用****占位 使用组件时, ****标签内部, 传入结构替换slo

    2024年02月11日
    浏览(42)
  • 【干货】Vue2.x 组件通信方式详解,这篇讲全了

    vue是数据驱动视图更新的框架, 我们平时开发,都会把页面不同模块拆分成一个一个vue组件, 所以对于vue来说组件间的数据通信非常重要,那么组件之间如何进行数据通信的呢? 首先我们需要知道在vue中组件之间存在什么样的关系, 才更容易理解他们的通信方式。 一般我们分

    2023年04月27日
    浏览(46)
  • 【vue2第九章】组件化开发和根组件以及style上的scoped作用

    组件化开发和根组件 什么是组件化开发? 一个页面可以拆分为多个组件,每个组件有自己的 样式,结构,行为 ,组件化开发的好处就是,便于维护,利于重复利用,提升开发的效率。 便于维护 :页面中块出了问题,可以直接去找到这个组件,修改组件的样式逻辑结构。

    2024年02月10日
    浏览(53)
  • Vue——动态组件、插槽

    1.ref属性(也可以实现组件间通信:子和父都可以实现通信) ref放在 标签 上,拿到的是 原生的DOM节点 ref放在 组件 上,拿到的是 组件对象  ,对象中的数据、函数 都可以直接使用 通过这种方式实现子传父(this.$refs.mychild.text) 通过这种方式实现父传子(调用子组件方法传

    2024年02月01日
    浏览(34)
  • vue组件间传值之插槽

    什么是插槽? 插槽就是子组件中的提供给父组件使用的一个占位符,用 表示,父组件可以在这个占位符中填充任何模板代码,如 HTML、组件等,填充的内容会替换子组件的标签。插槽显不显示、怎样显示是由父组件来控制的,而插槽在哪里显示就由子组件来进行控制。 vue中

    2024年02月04日
    浏览(36)
  • 使用Vue2开发一个图片预览组件,支持多图切换、缩放旋转、鼠标滚轮、键盘按键、拖动等等操作

    话不多说,咱们赶紧来开启本章的内容,这次小编给各位带来的依旧是实用类文章,分享如何开发一个完整的 图片预览组件 ,它支持多图切换、放大缩小、旋转、鼠标滚轮操作、键盘按键控制、拖动等等的功能,并且使用方便、易扩展,零依赖。 项目演示技术小编采用的是

    2024年02月09日
    浏览(78)
  • 【Vue框架】Vue2中Vue.js路由—路由介绍、路由控制组件切换、路由重定向、路由传参、嵌套路由、路由布局(附源码详解)

    Vue Router官方文档 :https://router.vuejs.org/zh/installation.html 使用路由文件: 1.引用vue-router路由js文件 2.创建router对象 3.在vm对象中注册router对象 4.在视图中使用 router-view 标签 第一种传参形式——路由路径进行传参,如:/login?id=20 第二种传参形式——路由占位符进行传参,如:/

    2023年04月08日
    浏览(88)
  • Vue的插槽与作用域插槽详解

    在Vue中,插槽(Slot)是一个非常强大且灵活的特性,用于在父组件中定义子组件的内容。Vue提供了两种主要类型的插槽:默认插槽(Slot)和作用域插槽(Scoped Slot)。本篇博文将深入介绍这两种插槽类型,从基础到进阶。 公众号:Code程序人生,个人网站:https://creatorblog.c

    2024年02月09日
    浏览(34)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包