博主:初映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中的属性名”

举个例子:

根组件App.vue




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

效果演示:

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


2.ref与$ref语法

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

注意点:

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

绑定是ref,调用是$refs

1.绑定dom写法:

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

我是父组件

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());},}}

子组件:MyGoods.vue

商品名称:小米

商品价格:{{ price }}

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

实现效果:


3.dynamic动态组件

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

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

语法格式:

 

举个例子:

父组件App.vue

我是父组件

import login from '@/components/login.vue'import user from '@/components/user.vue'export default {components: { login, user },data() {return {comName:"user"}}}

子组件 user.vue

我是个人信息组件

export default {name:"user"}

子组件 login.vue

我是登录组件

export default {name:"login"}

实现效果:

可以看到我们通过找到相应的标签运行


4.this.$nextTick()

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

上个例子:

我是父组件

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

实现的效果:

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

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

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


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

插槽概念:

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

1.匿名插槽

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

插槽书写结构:

父传:HTML结构

子收: 此处写默认值

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

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

我是父组件

点我跳转import goods from '@/components/goods.vue'export default {components:{goods}}

子组件:goods.vue

我是子组件

商品名称

我是默认的插槽export default {name: "goods",data() {return {}}}.son {border: 1px solid red;}

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

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


2.具名插槽

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

具名插槽书写结构:

父传:

 

HTML结构

子收:

插槽默认值 

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

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

我是父组件

I am Tittle

I am goodsInfoMy positionimport cell from '@/components/cell.vue'export default {components:{cell}}

子组件:cell.vue

我是默认标题 我是文本信息我是右侧信息export default {}.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;}

实现效果:

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

3.作用域插槽

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

作用域插槽书写结构:

子组件传递:

默认值

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

HTML属性

来个例子:

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

<!-- 1.匿名插槽:父组件传递 单个HTML结构 给子组件父传:HTML结构子收:默认HTML结构2.具名插槽:父组件传递 多个HTML结构 给子组件父传:HTML结构 子收:默认HTML结构3.作用域插槽:子组件传递数据给父组件子传:默认HTML结构父收:HTML结构-->

父组件

删除功能

头像功能

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",},],};},};

子组件:student.vue

修改
序号姓名年龄头像
{{ index+1 }}{{ item.name }}{{ item.age }}
export default {props: { arr: Array },data() {return {}}}table {margin-top: 20px;}td {height: 60px;}img {height: 90%;}

效果如下:

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

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

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

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

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


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

下篇文章将讲解【路由】的使用,本专栏将持续更新,欢迎关注~