组件

  • 组件
  • 组件的复用
  • 组件的注册
  • 组件名
  • 放置限制
  • 通过 Prop 向子组件传递数据
  • 单向数据流
  • poro的验证
  • 属性继承
  • 自定义事件
  • 插槽slot
    • 普通插槽
    • 具名插槽
    • 默认插槽
    • 作用域插槽
    • 解构插槽
    • 动态插槽
  • 动态组件
  • keep-alive
    • 组件名称
  • Provide / Inject
  • 异步组件

组件

在项目中,很多时候我们需要在不同的模块使用相同的一个块,而这个块的代码时相同的,这时候会造成代码冗余,我们可以通过封装组件的方式,实现代码的复用

在components文件夹中创建子组件
引入父组件中

创建子组件 MyCount

<template><h1>{{title}}</h1><div>{{num}}</div><button @click="add">增加</button>
</template>
<script>
export default {props:['title'],data(){return{num:0}},methods:{add(){this.num++}}
}
</script>

组件的复用

<template><my-count :title="t1"></my-count>  <!-- 有插槽需要写双标签 --><MyCount></MyCount> <div is="vue:my-count"></div><my-count :title="t2"/><!-- 无插槽可以使用单标记 -->
</template>

注意当点击按钮时,每个组件都会各自独立维护它的 count。因为你每用一次组件,就会有一个它的新实例被创建。

组件的注册

<script>
import MyCount from '../components/MyCount.vue'
export default {data(){return{t1:'home的计时器',t2:'第二个计数器',}},components:{MyCount,}
}
</script>

组件名

组件在导入时,import语句后面的名称我们可以自定义,它会作为标签名进行使用。
当我们需要把它放入模板时:

//都可以确定使用组件
<MyCount />
<MyCount></MyCount> 主要针对于插槽
<my-count />
<my-count></my-count>

放置限制

有些 HTML 元素,诸如 < ul>、< ol>、< table> 和 < select>,对于哪些元素可以出现在其内部是有严格限制的。而有些元素,诸如 < li>、< tr> 和 < option>,只能出现在其它某些特定的元素内部。
这会导致我们使用这些有约束条件的元素时遇到一些问题。

<table>
<blog-post-row></blog-post-row>
</table>

这个自定义组件 会被作为无效的内容提升到外部,并导致最终渲染结果出错。我们可以使用特殊的 is attribute 作为一个变通的办法:

<table>
<tr is="vue:blog-post-row"></tr>
</table>

通过 Prop 向子组件传递数据

使用组件时,如果模板中的内容都固定不变,那么每个模块引入该组件的内容都将一致;
可以将组件的某些内容变为动态的,内容由父元素的传值决定,vue给我们提供了props属性,让我们的组件可以对子组件传值

子组件MyCount

<template><h1>{{title}}</h1></template>
<script>
export default {props:['title'],}
</script>

父组件 动态传值

<template><my-count :title="t1"></my-count>  <!-- 有插槽需要写双标签 --><my-count :title="t2"/><!-- 无插槽可以使用单标记 --></template><script>import MyCount from '../components/MyCount.vue'export default {data(){return{t1:'home的计时器',t2:'第二个计数器',}},components:{MyCount,}}
</script>

父组件 静态传值

<my-count title="title"/>
<my-count :title="'title'"/>

可以提供一个数组,遍历多个相同组件传递不同数据:

<my-count :title="t" v-for="t in title" :key="t"/>
export default {data:function(){return {title:['计数器1','计数器2','计数器3']}},
}

希望每个 prop 都有指定的值类型时,可以以对象形式列出 prop,这些 property 的名称和值分别是 prop 各自的名称和类型。

<template><div><h2 :class="title">组件的标题{{num}}</h2>{{bool}} <!-- <h2>组件的标题{{ num }}</h2> -->{{ bool }}<hr />{{ arr }}<hr />{{ obj }}<hr /></div></template>
<script>export default {inheritAttrs:false, //不会继承根组件的样式props: {num: Number,bool: Boolean,arr: Array,obj: Object,},}
</script>

开启了对prop的验证,那么就需要注意传值的方式

<template><my-title   :title="color" :num="1" :bool="true"  :arr="[1,2,3]" :obj="{name:'zhangsan'}"></my-title>//一次传入多个prop<my-title   v-bind="post"  :arr="[1,2,3]" :obj="{name:'zhangsan'}"></my-title>
</template><script>import MyTitle from '../components/MyTitle.vue'export default {data(){return{color:'red',//一次传入多个post:{title:'red',num:1,bool:true}}},components:{MyTitle}}
</script>

单向数据流

所有的 prop 都使得其父子 prop 之间形成了一个单向下行绑定:父级 prop 的更新会向下流动到子组件中,但是反过来则不行。
这样会防止从子组件意外变更父级组件的状态,从而导致你的应用的数据流向难以理解。
每次父级组件发生变更时,子组件中所有的 prop 都将会刷新为最新的值。
这意味着你不应该在一个子组件内部改变 prop。如果你这样做了,Vue 会在浏览器的控制台中发出警告。

//子组件
prop:['name']
this.name = "李四"//报错

注:
在 JavaScript 中对象和数组是通过引用传入的,所以对于一个数组或对象类型的 prop 来说,在子组件中改变变更这个对象或数组本身将会影响到父组件的状态

//子组件
prop:['obj']//对象比较特殊,引用数据类型
this.obj.name="zhaoliu"//不会报错

poro的验证

<template><div><h2 :class="title">组件的标题{{num}}</h2></div>
</template>
<script>export default {props: {//多个可能的类型// title:[String,Number],//必填的字符串  带有默认值的字符串title: {type: String,// required:true, //必填字符串  必须传递值default: "red", //默认值},//带有默认值的对象// title:{//     type:Object,//     default(){//         return{name:'xiaoming'}//     } // },//自定义验证函数// title:{//     type:String,//     validator(value){//         return ['red','green'].includes(value)//     } //自定义验证函数  值必须匹配数组中字符串中的一个//prop验证时发生在实例创建之前的,所有验证中不能使用实例中data中的数据// },//有默认值的函数// title: {//   type: Function,//   default() {//     return "hello";//   },// }, <script>

当 prop 验证失败的时候,(开发环境构建版本的) Vue 将会产生一个控制台的警告。
注意
注意那些 prop 会在一个组件实例创建之前进行验证,所以实例的 property (如 data、computed 等) 在 default 或 validator 函数中是不可用的。

属性继承

一个非 prop 的 attribute 是指传向一个组件,但是该组件并没有相应 props 或 emits 定义的 attribute。常见的示例包括 class、style 和 id 属性。

如果我们需要通过 data status property 定义 组件的状态,它将应用于根节点 (即 div.date-picker)。

//父组件
<my-count class="a1"  data-status="activated"></my-count>
<style>.a1{}</style>
//子组件
<template><div ></div><template>

如果你不希望组件的根元素继承 attribute,你可以在组件的选项中设置 inheritAttrs: false。

//子组件
inheritAttrs:false,
<p v-bind="$attrs">1111111</p>
//父组件
<my-count class="a1"  data-status="activated">

自定义事件

子组件中会有一些事件和数据需要传递到父组件,例如我们点击了子组件中的按钮,那么这个按钮可能会触发某个方法,甚至传递了一些参数。这时我们的父组件就需要对事件进行处理或验证。

点击子组件按钮放大文字案例

//子组件
//这里我们给子组件绑定了一个事件,并通过调用内建的 $emit 方法并传入事件名称让父组件可以触发postfont
<button @click="$emit('postfont')">放大</button>//父组件
//我们可以通过@+$emit 方法并传入事件名称去触发子组件的方法进行文字的放大
<template>
<div :style="{fontSize:font+'em'}"><p>父组件的文字</p><my-title @postfont="postfont"></my-title>
</div>
</template>
<script>import MyTitle from '../components/MyTitle.vue'export default {data(){return{font:1,}},components:{MyTitle},}}
</script>

在$emit 方法中我们可以提供第二个参数来告诉父组件我们需要放大多少

//子组件
<button @click="$emit('postfont',0.2)">放大</button>//父组件  传值的值会保存在$event中
<template><div :style="{fontSize:fontSize+ 'em'}"><my-count :title="title" @postfont="fontSize += $event"/></div>
</template>

验证抛出事件:
要添加验证,将为事件分配一个函数,该函数接收传递给 $emit 调用的参数,并返回一个布尔值以指示事件是否有效。

emits:{postfont:(res)=>{if(typeof res==='number')return true;elsereturn false;} //验证},

emit语法糖

//如果我们只是想要把值传输到父组件,那么可以通过update的方式进行传值
$emit('update:v',newv);
//父组件
<post-size  v-model:v="size"  />
//传递过来的v会覆盖size

组件的双向数据绑定

子组件

<template><input type="text" :value="h_name" @input="$emit('update:h_name',$event.target.value)"/>{{h_name}}
</template>
<script>export default {emits:['update:h_name'],props:['h_name']}
</script>

父组件

<template><my-input  v-model:h_name="h_name"></my-input>{{h_name}}
</template>
<script>
import MyInput from '../components/MyInput.vue'
export default {data(){return{h_name:'zhangsan'}},components:{MyInput},methods:{},
}
</script>

允许为组件绑定多个v-model

插槽slot

使用插槽为了实现组件结构的复用。
将不确定的,希望由用户指定的部分定义为插槽。

将 元素作为承载分发内容的出口。

在出现组件的多重嵌套时,可以考虑使用插槽进行简化

普通插槽

父组件中子组件标签之间写插槽的内容,
如果子组件 template 中没有包含一个 元素,则该组件起始标签和结束标签之间的任何内容都会被抛弃

父组件 Home.vue

<template><my-slot>这是插槽内容</my-slot></template>

子组件 MySlot.vue

<template><slot></slot>
</template>

插槽还可以包含任何模板代码,包括 HTML
插槽中可以使用实例的数据

<template>
<my-slot><b>这里是插槽内容 {{msg}} </b> </my-slot>
</template>
<script>import MySlot from '../components/MySlot.vue'export default {data(){return{msg:"百度一下"     }},components:{MySlot} }</script>

vue官方规定:每一个slot插槽,都需要有一个name名称。

如果省略了slot的name属性,则有一个默认名称为default。

默认情况下,使用组件时,组件标签中的内容默认会被填充在default插槽中。

具名插槽

一个子组件标签中需要多个插槽

一个不带 name 的 出口会带有隐含的名字“default”。

  1. 父组件中使用子组件,要将内容填充到指定名称的插槽中,需要使用v-slot指令指定插槽的名称。
 v-slot:name
  1. v-slot:指令不能直接使用在元素身上,必须写在template标签上。
  2. template标签是一个虚拟的标签,只起到包裹性质的作用,但是不会被渲染为任何实质性的html元素

跟 v-on 和 v-bind 一样,v-slot 也有缩写,即把参数之前的所有内容 (v-slot:) 替换为字符 #。例如 v-slot:header 可以被重写为 #header

子组件 MySlot.vue

<template><div id="header"><slot name="header"></slot></div><div id="content"><slot name="default"></slot> </div><div id="footer"><slot name="footer"></slot></div>
</template>

父组件 Home.vue

<template><my-slot><template v-slot:header>这是头部内容</template><template #default>这里是体部内容</template> <template #footer>这是底部内容</template></my-slot>
</template>

默认插槽

可以在插槽中提供默认内容(后背内容),在组件使用时未给插槽提供内容时会默认展示插槽的后背内容。
但是如果组件在使用时提供了插槽内容,则插槽的后背内容不会被显示。

ref.vue<div><slot name="default">插槽后背内容</slot> </div>
App.vue<Ref ref="ref" :value1="value"><template #default>覆盖插槽默认内容</template></Ref>

当被提供的内容只有默认插槽时,组件的标签才可以被当作插槽的模板来使用。这样我们就可以把 v-slot 直接用在组件上

<template><my-slot v-slot:a="abc">{{abc.user.name}}</my-slot>
</template>

注意默认插槽的缩写语法不能和具名插槽混用,因为它会导致作用域不明确

作用域插槽

让插槽内容能够访问子组件中才有的数据

在封装使用时,为预留的slot提供属性对应的值,这种用法叫做作用域插槽。

子组件 MySlot.vue

<template>
<div> <slot name="a" :user="user" :info="information">{{user.name}}</slot></div>
<!-- 将子组件中的user值传递给父组件中的插槽 -->
</template>
<script>export default {data(){return{user:{name:'zhangsan',age:10},information:"msg"}},}
</script>

父组件 Home.vue

<template><my-slot><template v-slot:a="abc">{{abc.user.name}} {{abc.info}} </template><!-- 父组件中插槽通过abc(一般通过scope)(#a="scope") 来接收子组件插槽传递过来的值,并可以通过插槽表达式渲染到页面上 --><!-- abc默认为对象,值为 { ”user“:{ ”name“:”zhangsan“,”age“:10}, ”information“:"msg" } --></my-slot>
</template>

v-slot:插槽名称=“变量名”

使用变量接收从子组件插槽定义的数据。

表格案例

子组件 MyTable

<table><!-- 标题区域 --><thead><tr><slot name="header"></slot></tr></thead><!-- 内容主体区域 --><tbody><tr v-for="(item, index) in data" :key="item.id"><slot name="body" :row="item" :index="index"></slot>  <!-- 作用域插槽 将子组件中的数据传递给父组件插槽中 --></tr></tbody></table>

父组件

<my-table :data="goodslist"><template v-slot:header><th>序号</th><th>商品名称</th><th>价格</th><th>标签</th><th>操作</th></template><template v-slot:body="{ row, index }"><!-- 父组件作用域插槽中解构子组件传递过来的数据 --> <td>{{ index + 1 }}</td><td>{{ row.goods_name }}</td>  <td>¥{{ row.goods_price }}</td><td><button type="button" @click="onRemove(row.id)">删除</button></td><!-- 将子组件传递过来的数据通过插槽表达式的方式渲染在页面上--></template></my-table>

解构插槽

<template><my-slot><!-- 父组件可以通过对象解构的方式来接受子组件作用域插槽传递过来的数据 --><template v-slot:a="{ user,info }">{{user.name}} {{info}} </template><my-slot>
<template>

动态插槽

子组件 MySlot.vue

<template><div id="header"><slot name="header"></slot></div><div id="content"><slot name="default"></slot> </div><div id="footer"><slot name="footer"></slot></div>
</template>

父组件 Home.vue

<template><my-slot><template v-slot:[s_name]>这里是内容</template><my-slot>
<template>
export default {data(){return{s_name:'header'}},
}

动态组件

不同组件之间进行动态切换。

动态切换组件的显示与隐藏。

使用< component>内置组件实现组件的动态渲染。

< component>作为组件的占位符。

is属性的值表示要渲染的组件的名称。

< component :is=“currentTabComponent”></ component>

<template><button @click="comp='MyA' ">A</button><button @click="comp='MyB'">B</button><button @click="comp='MyC'">C</button><div><component :is="comp"/></div>
</template>
<script>
import MyA from '../components/MyA.vue'
import MyB from '../components/MyB.vue'
import MyC from '../components/MyC.vue'
export default {data(){return{comp:'MyA'}},components:{MyA,MyB,MyC}
}
</script>

组件切换时,会进行组件的创建和销毁。

keep-alive

组件切换时,之前的组件会被销毁,创建新的组件。进入组件时会重新渲染。

若不希望组件切换被隐藏时组件被销毁,则需要进行缓存。

keep-alive可以将内部组件进行缓存,而不是进行销毁。

    <keep-alive><component :is="name"></component></keep-alive>

keep-alive对应的生命周期函数:

actived:组件被激活

deactived:组件被缓存

组件被切换时会执行deactived缓存生命周期函数;再次切换进入组件时,组件不会再进行重新创建,不会进入created生命周期函数,而会进入actived被激活。

当组件第一次被创建的时候,既会执行created也会执行actived生命周期;当组件不是第一次被创建,由缓存状态进入被激活状态时,不会执行created,只会执行actived。

include属性

keep-alive默认会缓存包裹的所有组件。

include表示需要被keep-alive缓存的组件(组件名称)。

    <keep-alive :include="includeName"><component :is="name"></component></keep-alive>

exclude属性

exclude表示bu需要被keep-alive缓存的组件。

    <keep-alive :exclude="excludeName"><component :is="name"></component></keep-alive>

include和exclude属性不要同时使用。

组件名称

若在声明组件时,没有为组件指定name属性,则组件的默认名称为组件的注册名称;若组件声明时有那么属性,则name则为组件的组件名称。

若组件有name属性时,include和exclude必须使用组件的name名称,使用注册名称不起作用。

// 组件声明名称
export default {name:'Ref',
}
<Ref ref="ref" :value1="value"></Ref>import Ref from './components/ref.vue'export default {components: {// 组件注册名称Ref},

组件注册名称使用场景:以标签的形式将注册好的组件渲染和使用到页面结构中。

组件声明时的name名称主要使用场景:结合keep-alive标签实现组件缓存功能,以及在调试工具中看到组件的name名称。

Provide / Inject

需要从父组件向子组件传递数据时,需要使用 props。
若有一些深度嵌套的组件,而深层的子组件只需要父组件的部分内容。在这种情况下,如果仍然将 prop 沿着组件链逐级传递下去,可能会很麻烦。
这种情况下可以使用一对 provide 和 inject,无论组件层次结构有多深,父组件都可以作为其所有子组件的依赖提供者。

这个特性有两个部分:父组件有一个 provide 选项提供数据,子组件有一个 inject 选项来开始使用这些数据

Home父组件

< template>< my-a/>
< /template>
< script>import MyA from '../components/MyA.vue'export default {provide:{msg:'hello'}, //provide 在父组件中提供数据components:{MyA,}}
< /script>

子组件 MyA.vue

< template>is A< my-b></my-b>
< /template>
< script>import MyB from './MyB.vue'  //引入子组件MyBexport default {inject:['msg'], // inject 在子组件中使用数据components:{MyB}
}
< /script>

子组件 MyB.vue

< template>is B {{msg}}
< /template>
< script>export default {inject:['msg']// inject 在子组件中使用数据}
< /script>

异步组件

在大型应用中,我们可能需要将应用分割成小一些的代码块,并且只在需要的时候才从服务器加载一个模块。为了简化,可以使用defineAsyncComponent方法

<template><my-c/>
</template>
<script>
import {defineAsyncComponent} from 'vue'
export default {components:{MyC:defineAsyncComponent(()=>import('../components/MyC.vue'))}
}
</script>

为什么要使用异步组件

  1. 异步组件在创建时什么也不做,在组件第一次渲染时加载并缓存。
  2. 异步组件的性能更高,加载的速度更快。
  3. 异步组件在打包时,体积更小。

vue基础二(组件)相关推荐

  1. Vue基础知识+组件化开发+模块化开发总结

    三.内容: 一.MVVM View层 视图层,我们前端开发时候的DOM层 主要就是给用户展示各种信息 Model层 数据层:可能是我们固定的思数据,更多的是来自我们的服务器,在网路上请求下来的数据 V ...

  2. WEB前端 vue学习二 组件之间的数据传递

    Vue 的组件作用域都是孤立的,不允许在子组件的模板内直接引用父组件的数据.必须使用特定的方法才能实现组件之间的数据传递. 首先用 vue-cli 创建一个项目,其中 App.vue 是父组件,com ...

  3. vue基础整理-组件

    1--组件 可以理解为页面的一部分,其具有独立的逻辑及功能或界面,同时又能与其他部分进行相应地融合,变成完整的应用.页面可以由这样一个个的组件构成,如导航栏.列表项.弹窗.侧边栏.下拉框.多选框等.页 ...

  4. 【VUE基础】组件化高级

    1. slot-插槽的基本使用 ​ 我们在使用组件的时候有时候希望,在组件内部定制化内容,例如京东这样. 这两个都是导航栏,组件的思想是可以复用的,把这个导航栏看做一个组件. 这个组件都可以分成三个部 ...

  5. 从壹开始前后端分离 [ Vue2.0+.NET Core2.1] 二十║Vue基础终篇:组件详解+项目说明...

    缘起 新的一天又开始啦,大家也应该看到我的标题了,是滴,Vue基础基本就到这里了,咱们回头看看这一路,如果你都看了,并且都会写了,那么现在你就可以自己写一个Demo了,如果再了解一点路由,ajax请求 ...

  6. (vue基础试炼_05)简单组件之间的传值

    接上一篇:(vue基础试炼_04)使用组件改造TodoListhttps://gblfy.blog.csdn.net/article/details/103844256 文章目录 一.上篇回顾 ① 代 ...

  7. (vue基础试炼_04)使用组件改造TodoList

    接上一篇:(vue基础试炼_03)使用vue.js实现TodoListhttps://gblfy.blog.csdn.net/article/details/103842233 指令 说明 v-bin ...

  8. Vue2基础、组件化编程、脚手架、Vuex、Vue路由、UI组件库

    尚硅谷张天禹老师讲课 学习视频 1.Vue简介 Vue2中文官网 1.1 Vue 介绍 一套用于构建用户界面的渐进式JavaScript框架 构建用户界面:把数据通过某种办法变成用户界面 渐进式:可以 ...

  9. Vue 基础快速入门(二)

    Vue 组件化编程 模块, 组件, 模块化与组件化 模块 理解:向外提供特定功能的 js 程序, 一般就是一个 js 文件 为什么:js 文件很多很复杂 作用:复用 js,简化 js 的编写, 提高 ...

最新文章

  1. 将会改变未来IT世界的十种编程语言
  2. 用Python爬取WordPress官网所有插件
  3. xen 虚拟机挂了,宿主机假死的问题追终,全思路
  4. 皮一皮:这是。。。养了个白眼狼???
  5. Monkey Server自动化脚本
  6. linux 备份mbr,MBR的备份与恢复
  7. 求离散数据的突变点_Nat Gen | 染色质三维构象决定突变分布
  8. vscode更换主题的插件_VScode 插件开发(三)主题
  9. php封ip,php实现封IP功能[原创]
  10. java怎么写网络爬虫_教你如何编写简单的网络爬虫
  11. 数据库(.udl)简单测试连接
  12. tensorflow之安装opencv
  13. OD调试2----破解序列号验证程序
  14. 2 分钟玩转 Apizza,轻量级 API 工具
  15. 【PowerDesigner】PowerDesigner的下载及安装
  16. CentOS7安装FTP服务器及默认21端口修改
  17. 武昌职业学院与湖北美和易思教育科技有限公司校企签约揭牌仪式隆重举行
  18. Spark3 AQE (Adaptive Query Execution) 一文搞懂 新特性
  19. C# .NET实现扫描识别图片中的文字
  20. 厌倦只是一瞬间的事 2012-03-29 09:54:01 明明该有许多话要交代下去有许多事要汇报上去,明明有很多事情要去做,可是偏偏都不想去。可是突然还是打算留在电脑前漫无目的地把时间都耗费在了

热门文章

  1. 【原创】通过Web远程浏览并控制Mini6410上的摄像头(二)
  2. php落寞了,php语言最近走势如何?php没落了吗?
  3. 计算机毕设Python+Vue医院药品进销存系统(程序+LW+部署)
  4. 2.SQC概念和方法
  5. SpringBoot-记录一只noob在学习中遇到的-问题2:Field providerDao in com.shen.EurekaProvider.service.impl.Provider……
  6. 苹果手机自带软件删除了怎么恢复_手机备忘录删除了怎么恢复
  7. 无人值守-污水处理远程智慧运维系统
  8. [笔试补完计划]澜起科技2022数字验证笔试
  9. 笔记--Java IDEA常用快捷键
  10. 怎样用c语言编程解多元方程组,C语言解多元一次方程组(矩阵法)