前言 目前学完了深入组件的部分,进入动画学习,学了下然后有点静不下心,emmm 现在打算等学习项目的时候再深入学习吧,最后来总结下vue组件的一些内容。
组件 没学过其他框架,似乎是从react那边借鉴的精髓,重在数据交互上。
组件的通信方式 父组件向子组件通信
方法一:上一篇里也有提到,不过这里也说下,答案是使用prop
vue中: data :{ return : { name : 'xxx' } }, app.component('template-name', { prop : ['usename'] template:` <p > {{ usename }}</p>//子组件使用 ` } html中: <template :usename='name'> </template> 最后的效果就是将数据name传到了子组件<template-name>中
方法二:使用Provide / Inject 如果组件树太长了,使用prop来传递数据将会变得非常麻烦,而这种方法就能解决这个问题
//父组件 app.component('todo-list', { data() { return { todos: ['Feed a cat', 'Buy tickets'] } }, provide: { todoLength: this.todos.length //这种情况无法访问组件的实例 }, provide() { //将provide转换为对象,这样就能访问实例对象了 return { todoLength: this.todos.length } }, template: ` ... ` }) //子组件 app.component('todo-list-statistics', { inject: ['todoLength'], created() { console.log(`Injected property: ${this.todoLength}`) // > 注入的 property: John Doe } })
此外上述方法不是响应式的,应该如下使用计算属性
子组件为了响应式的更新数据,父组件数据有变动,使用computed app.component('todo-list', { // ... provide() { return { todoLength: Vue.computed(() => this.todos.length) } } }) app.component('todo-list-statistics', { inject: ['todoLength'], created() { console.log(`Injected property: ${this.todoLength.value}`) // > 注入的 property: 5 } })
’子组件向父组件通信‘:实际上不是,实际上是讲的 ’插槽‘ 方法:使用插槽<slot></slot>
将数据通信前先来讲讲具名插槽,如何将需要渲染的东西准确的插入子组件中, 说实话我感觉这样搞起来也是挺麻烦的。
具名插槽 子组件<base-layout>
组件中是如下内容:
<div class="container"> <header> <!-- 我们希望把页头放这里 --> </header> <main> <!-- 我们希望把主要内容放这里 --> </main> <footer> <!-- 我们希望把页脚放这里 --> </footer> </div>
那么怎么渲染呢? 像这样模板中
<div class="container"> <header> <slot name="header"></slot> </header> <main> <slot></slot> </main> <footer> <slot name="footer"></slot> </footer> </div>
然后在父组件中这样使用。注意:v-slot 只能添加在 <template>
上
<base-layout> <template v-slot:header> <h1>Here might be a page title</h1> </template> <template v-slot:default>//如果没有name那么默认default <p>A paragraph for the main content.</p> <p>And another one.</p> </template> <template v-slot:footer> <p>Here's some contact info</p> </template> </base-layout>
最后的渲染结果是这样:
<div class="container"> <header> <h1>Here might be a page title</h1> </header> <main> <p>A paragraph for the main content.</p> <p>And another one.</p> </main> <footer> <p>Here's some contact info</p> </footer> </div>
说实话现在我觉得挺麻烦的emmm,可能是还没有什么开发经验的原因吧。 简单来说就是: 1.模板中 用<slot name="header"></slot>
设置name,占据位置 2.父组件使用
<template v-slot:header> <h1>Here might be a page title</h1> </template>
来渲染需要的数据。
插槽内容访问子组件数据:作用域插槽 相当于父组件访问子组件的数据了吧emmm。总结的时候才发现不是父组件访问子组件的数据,有点尴尬😓
//子组件中: app.component('todo-list', { data() { return { items: ['Feed a cat', 'Buy milk'] } }, template: ` <ul> <li v-for="( item, index ) in items"> <slot :item="item" :index="index" :another-attribute="anotherAttribute"></slot>//也叫插槽 prop </li> </ul> ` }) //父组件中: <todo-list> <template v-slot:default="slotProps"> //将模板中<slot>元素绑定的数据给slotProps <i class="fas fa-check"></i> <span class="green">{{ slotProps.item }}</span> //可以通过slotProps访问模板中的数据了。 </template> </todo-list>
注意插槽prop不能和具名插槽一起使用,会导致作用域混乱 具名插槽缩写:v-slot: 缩写为 #** 如 v-slot:header 可以被缩写为 #header
后续 vue以及相关的要学的还有很多:路由,vuex,cli什么的,Components,webpack,不过这些还早,明天先看组合式 API