动态组件,插槽分发内容,缓存组件

动态组件

<!DOCTYPE Html>
<html>
<head>
    <script src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js"></script>
    <meta charset="UTF-8">
</head>
<div id="app">
    <ul>
        <li @click="toggleView('Home')">Home</li>
        <li @click="toggleView('About')">About</li>
    </ul>
    <div>
        <component :is="view"></component>
    </div>
</div>
<script type="text/javascript">
    let Home = {
        template: '<p>Hello World</p>'
    };
    let About = {
        template: '<p>Hello About!</p>'
    };
    let vm = new Vue({
        el: '#app',
        components: {Home, About},
        data: () => {
            return {
                view: 'Home'
            }
        },
        methods: {
            toggleView: function (view) {
                this.view = view;
            }
        }
    })
</script>
</html>

定义两个组件,使用components选项注册实例到Vue中。
在上方中使用了组件,将会接收一个父组件的注册过的名称,在父组件注册的名称为Home和About两个名称,在data对象中定义view的值的Home,即默认的值为Home的值。父组件为id=app的组件,该组件注册了两个名称,为Home和About

2019-05-31-20-07-34----

单击Home切换到Home组件,单击About切换到About组件

插槽分发

组件接收多态DOM结构
使用slot插槽分发内容

<!DOCTYPE Html>
<html>
<head>
    <script src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js"></script>
    <meta charset="UTF-8">
</head>
<div id="app">
    <slot-test>
        <p>使用插槽分发内容</p>
        <h1 slot="header">插槽555测试!</h1>
        <p>组件中,没有指定插槽名称的元素会默认置入插槽中!</p>
        <p slot="none">指定到不存在的插槽不会显示</p>
    </slot-test>
</div>
<script type="text/javascript">
    let SlotTest = {
        template: '<div>' +
            '33333' +
            '<slot name="header">添加了slot名称为hader插槽</slot>' +
                '<slot>这是默认插槽</slot>' +
                '</div>'
    }
    let vm = new Vue({
        el: '#app',
        components: { SlotTest }
    })
</script>
</html>

查看渲染过后的dom结构树

2019-05-31-21-32-17----

可以看到父组件把指定插槽名称为header 分发到子组件SlotTest的名称为header的插槽,进行替换。。

默认的插槽,父组件,依旧进行替换

使用slot-scope获取子组件回传数据,在父组件中执行多态渲染和响应

使用slot-scope根据数据不同,进行多态渲染。。。根据数据不同,进行多态化渲染。。组件化

这是多态

这本书太老了。。。
直接找文档去了。。
https://cn.vuejs.org/v2/guide/components-slots.html

新的内容

有时我们需要多个插槽。例如对于一个带有如下模板的 <base-layout> 组件:

<div class="container">
  <header>
    <!-- 我们希望把页头放这里 -->
  </header>
  <main>
    <!-- 我们希望把主要内容放这里 -->
  </main>
  <footer>
    <!-- 我们希望把页脚放这里 -->
  </footer>
</div>
对于这样的情况,<slot> 元素有一个特殊的特性:name。这个特性可以用来定义额外的插槽:

<div class="container">
  <header>
    <slot name="header"></slot>
  </header>
  <main>
    <slot></slot>
  </main>
  <footer>
    <slot name="footer"></slot>
  </footer>
</div>
一个不带 name 的 <slot> 出口会带有隐含的名字“default”。

在向具名插槽提供内容的时候,我们可以在一个 <template> 元素上使用 v-slot 指令,并以 v-slot 的参数的形式提供其名称:

<base-layout>
  <template v-slot:header>
    <h1>Here might be a page title</h1>
  </template>

  <p>A paragraph for the main content.</p>
  <p>And another one.</p>

  <template v-slot:footer>
    <p>Here's some contact info</p>
  </template>
</base-layout>
现在 <template> 元素中的所有内容都将会被传入相应的插槽。任何没有被包裹在带有 v-slot 的 <template> 中的内容都会被视为默认插槽的内容。

然而,如果你希望更明确一些,仍然可以在一个 <template> 中包裹默认插槽的内容:

<base-layout>
  <template v-slot:header>
    <h1>Here might be a page title</h1>
  </template>

  <template v-slot: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>
注意 v-slot 只能添加在一个 <template> 上 (只有一种例外情况),这一点和已经废弃的 slot 特性不同。

这个依旧能看懂

作用域插槽

插槽的数据访问子组件的数据。。

<span>
  <slot>{{ user.lastName }}</slot>
</span>

插槽如下

<current-user>
  {{ user.firstName }}
</current-user>

不看了。。。看不懂

单插槽

<!DOCTYPE Html>
<html>
<head>
    <script src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js"></script>
    <meta charset="UTF-8">
</head>
<div id="app">
    <div>
        <!-- 单slot -->
        <v-one>
            <p>初始化段落一</p>
            <p>初始化段落二</p>
        </v-one>

    </div>
</div>


<template id="one">
    <div>
        <h1>组件标题</h1>
        <slot></slot>
        <p>组件段落内容</p>
        <p>{{one}}</p>
    </div>
</template>
<script type="text/javascript">
    new Vue({
        el: '#app',
        components: {
            'v-one': {
                template: '#one',
                data() {
                    return {
                        'one': 'I am one'
                    }
                }
            }
        }
    });
</script>
</html>

通过slot可以访问v-one内的内容。。

传递给组件的内容将会在slot中展示出来。。

传递给slot中的数据默认无法在父组件中展示。需要使用slot进行展示

<!DOCTYPE Html>
<html>
<head>
    <script src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js"></script>
    <meta charset="UTF-8">
</head>
<div id="app">
    <div>
        <!-- 作用域插槽 -->
        <v-three>
            <!-- 父组件默认无法使用子组件数据 -->
            <template scope="props">
                <p>{{props.text}}</p>
            </template>
        </v-three>
    </div>
</div>



<!-- 作用域插槽 -->
<template id="three">
    <div>
        33333
        <!-- 把数据传递给slot,这样父组件也可以访问three这个组件的数据 -->
        <slot :text="three"></slot>
        {{ three }}
    </div>
</template>
<script type="text/javascript">
    new Vue({
        el: '#app',
        components: {
            'v-three': {
                template: '#three',
                data() {
                    return {
                        'three': 'I am three'
                    }
                }
            }
        }
    });
</script>
</html>

组件缓存

过渡效果