前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Vue基础:组件--slot、异步组件、递归组件及其他

Vue基础:组件--slot、异步组件、递归组件及其他

作者头像
奋飛
发布2021-08-30 11:00:01
2.9K0
发布2021-08-30 11:00:01
举报
文章被收录于专栏:Super 前端Super 前端

slot分发内容

为了让组件可以组合,我们需要一种方式来混合父组件的内容与子组件自己的模板。这个过程被称为内容分发。Vue中使用特殊的 元素作为原始内容的插槽。

问题(编译作用域)

message 应该绑定到父组件的数据,还是绑定到子组件的数据?

代码语言:javascript
复制
<child-component>
  {{ message }}
child-component>

答案是父组件。父组件模板的内容在父组件作用域内编译;子组件模板的内容在子组件作用域内编译。

单个slot

除非子组件模板包含至少一个 插口,否则父组件的内容将会被丢弃。当子组件模板只有一个没有属性的 slot 时,父组件整个内容片段将插入到 slot 所在的 DOM 位置,并替换掉 slot 标签本身。在 标签中的任何内容都被视为备用内容。备用内容在子组件的作用域内编译,并且只有在宿主元素为空,且没有要插入的内容时才显示备用内容。

具名slot

元素可以用一个特殊的属性 name 来配置如何分发内容。多个 slot 可以有不同的名字。具名 slot 将匹配内容片段中有对应 slot 特性的元素。仍然可以有一个匿名 slot,它是默认 slot,作为找不到匹配的内容片段的备用插槽。如果没有默认的 slot,这些找不到匹配的内容片段将被抛弃。

代码语言:javascript
复制
<div id="app">
  <my-component>
    <template>
      <p>父组件分发内容p>
    template>
  my-component>
  <my-component2>
    <b>内容ab>
    <template slot="title">
      父组件分发的title
    template>
    <b>内容bb>
  my-component2>
div>

<script>
const app = new Vue({
  el: '#app',
  components: {
    'my-component': {
      template: `

渲染结果:

代码语言:javascript
复制
<div>
  <p>父组件分发内容p>
div> 
<div>
  父组件分发的title
  <b>内容ab>  
  <b>内容bb>
div>

完整示例参考地址:https://jsfiddle.net/381510688/tugxd14s/

作用域插槽

在子组件插槽中可以通过slot插槽标签的属性将数据传递到父组件要分发的内容当中,父组件要通过模板来接收子组件插槽传递上来的数据。

代码语言:javascript
复制
<my-component>
  <template scope="props">
    <p>父组件分发内容p>
    <p>{{props.message}}p>
  template>
my-component>

<script>
const app = new Vue({
    el: '#app',
    components: {
    'my-component': {
        template: `

渲染结果:

代码语言:javascript
复制
<div>
  <p>父组件分发内容p> 
  <p>哈哈p>
div>

具代表性的列表组:

代码语言:javascript
复制
<my-list :list="['a.com', 'b.com']">
  <template slot="item" scope="props">
    <li class="link"><a>{{props.link}}a>li>
  template>
my-list>

<script>
// ...
'my-list': {
  props: ['list'],
  template: `

渲染结果:

代码语言:javascript
复制
<ul>
  <li class="link"><a>a.coma>li>
  <li class="link"><a>b.coma>li>
ul>

完整示例参考地址:https://jsfiddle.net/381510688/j8qkbwbo/

动态组件

动态地绑定到它的 is 特性,让多个组件可以使用同一个挂载点,并动态切换:

代码语言:javascript
复制
<component v-bind:is="currentView">
  
component>
代码语言:javascript
复制
var vm = new Vue({
  el: '#example',
  data: {
    currentView: 'home'
  },
  components: {
    home: { /* ... */ },
    posts: { /* ... */ },
    archive: { /* ... */ }
  }
})

keep-alive可以把切换出去的组件保留在内存中,保留它的状态,避免重新渲染。

代码语言:javascript
复制
<keep-alive>
  <component :is="currentView">
    
  component>
keep-alive>

杂项

编写可复用组件

可复用组件应当定义一个清晰的公开接口,同时也不要对其使用的外层数据作出任何假设。

  • Prop 允许外部环境传递数据给组件;
  • 事件允许从组件内触发外部环境的副作用;
  • 插槽允许外部环境将额外的内容组合在组件中。
代码语言:javascript
复制
<my-component
  :foo="baz"
  :bar="qux"
  @event-a="doThis"
  @event-b="doThat"
>
  <img slot="icon" src="...">
  <p slot="main-text">Hello!p>
my-component>
子组件引用

尽管有 prop 和事件,但是有时仍然需要在 JavaScript 中直接访问子组件。为此可以使用 ref 为子组件指定一个引用 ID。

代码语言:javascript
复制
<div id="parent">
  <user-profile ref="profile">user-profile>
div>
代码语言:javascript
复制
var parent = new Vue({ el: '#parent' })
// 访问子组件实例
var child = parent.$refs.profile

注意:refs 只在组件渲染完成后才填充,并且它是非响应式的。它仅仅是一个直接操作子组件的应急方案——应当避免在模板或计算属性中使用 refs。 ref 被用来给元素或子组件注册引用信息。引用信息将会注册在父组件的 refs 对象上。如果在普通的 DOM 元素上使用,引用指向的就是 DOM 元素;如果用在子组件上,引用就指向组件实例,可以通过el,获取DOM元素。

异步组件

Vue.js 允许将组件定义为一个工厂函数,异步地解析组件的定义。

代码语言:javascript
复制
Vue.component('async-example', function (resolve, reject) {
  setTimeout(function () {
    // 将组件定义传入 resolve 回调函数
    resolve({
      template: '<div>I am async!div>'
    })
  }, 1000)
})
代码语言:javascript
复制
Vue.component('async-webpack-example', function (resolve) {
  // 这个特殊的 require 语法告诉 webpack
  // 自动将编译后的代码分割成不同的块,
  // 这些块将通过 Ajax 请求自动下载。
  require(['./my-async-component'], resolve)
})

webpack 2 + ES2015 的语法时可以这样:

代码语言:javascript
复制
Vue.component(
  'async-webpack-example',
  () => import('./my-async-component')
)
组件命名约定

当注册组件 (或者 prop) 时,可以使用 kebab-case (短横线分隔命名)、camelCase (驼峰式命名) 或 PascalCase (单词首字母大写命名);在 HTML 模板中,请使用 kebab-case。

代码语言:javascript
复制
components: {
  myComponent: { /* ... */ }
}
代码语言:javascript
复制
<my-component/>
递归组件

一定要确保递归调用有终止条件,可以通过v-if进行控制。

递归组件示例:https://jsfiddle.net/381510688/nhhfL1bd/

组件间的循环引用

参考官网地址:https://cn.vuejs.org/v2/guide/components.html#组件间的循环引用

内联模板

如果子组件有 inline-template 特性,组件将把它的内容当作它的模板,而不是把它当作分发内容。这让模板编写起来更灵活。

代码语言:javascript
复制
<my-component inline-template>
  <div>
    <p>这些将作为组件自身的模板。p>
    <p>而非父组件透传进来的内容。p>
  div>
my-component>

但是 inline-template 让模板的作用域难以理解。使用 template 选项在组件内定义模板或者在 .vue 文件中使用 template 元素才是最佳实践。

X-Template

另一种定义模板的方式是在 JavaScript 标签里使用 text/x-template 类型,并且指定一个 id。例如:

代码语言:javascript
复制
<script type="text/x-template" id="hello-world-template">
代码语言:javascript
复制
Vue.component('hello-world', {
  template: '#hello-world-template'
})

注意:在有很多大模板的演示应用或者特别小的应用中可能有用,其它场合应该避免使用,因为这将模板和组件的其它定义分离了。

对低开销的静态组件使用v-once

尽管在 Vue 中渲染 HTML 很快,不过当组件中包含大量静态内容时,可以考虑使用 v-once将渲染结果缓存起来,就像这样:

代码语言:javascript
复制
Vue.component('terms-of-service', {
  template: '\
    \
      Terms of Service\
      ...很多静态内容...\
    \
  '
})
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2017-10-26 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • slot分发内容
    • 问题(编译作用域)
      • 单个slot
        • 具名slot
          • 作用域插槽
            • 动态组件
              • 杂项
                • 编写可复用组件
                • 子组件引用
                • 异步组件
                • 组件命名约定
                • 递归组件
                • 组件间的循环引用
                • 内联模板
                • X-Template
                • 对低开销的静态组件使用v-once
            领券
            问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档