• 从零开始的vue学习笔记(四)


    组件注册

    • 组件名
       Vue.component('my-component-name', { /* ... */ })
      
      这里的my-component-name就是组件名,组件名的取法可以参考指南
      • kebab-case写法(-连接单词) 推荐的写法
        定义:

          Vue.component('my-component-name', { /* ... */ })
        

        用法:

          <my-component-name></my-component-name>
        
      • PascalCase写法(单词首字母大写)

          Vue.component('MyComponentName', { /* ... */ })
        
    • 全局注册
        Vue.component('my-component-name', { /* ... */ })
      
    • 局部注册
      先用一个普通的 JavaScript 对象来定义组件:
        var ComponentA = { /* ... */ }
        var ComponentB = { /* ... */ }
      
      然后在 components 选项中定义你想要使用的组件:
        new Vue({
        el: '#app',
        components: {
            'component-a': ComponentA,
            'component-b': ComponentB
        }
        })
      
      对于 components 对象中的每个属性来说,其属性名就是自定义元素的名字,其属性值就是这个组件的选项对象。
      注意局部注册的组件在其子组件中不可用。例如,如果你希望 ComponentA 在 ComponentB 中可用,则你需要这样写:
        var ComponentA = { /* ... */ }
      
        var ComponentB = {
        components: {
            'component-a': ComponentA
        },
        // ...
        }
      
      或者如果你通过 Babel 和 webpack 使用 ES2015 模块,那么代码看起来更像:
        import ComponentA from './ComponentA.vue'
      
        export default {
        components: {
            ComponentA
        },
        // ...
        }
      
    • 模块系统
      通过 import/require 使用一个模块系统
      • 模块系统中局部注册
        import ComponentA from './ComponentA'
        import ComponentC from './ComponentC'
      
        export default {
        components: {
            ComponentA,
            ComponentC
        },
        // ...
        }
      

    prop

    • prop大小写(camelCase vs kebab-case)
      HTML 中的特性(属性)名是大小写不敏感的,所以浏览器会把所有大写字符解释为小写字符,camelCase (驼峰命名法) 的 prop 名需要使用其等价的 kebab-case (短横线分隔命名) 命名:

        Vue.component('blog-post', {
        // 在 JavaScript 中是 camelCase 的
        props: ['postTitle'],
        template: '<h3>{{ postTitle }}</h3>'
        })
      
        <!-- 在 HTML 中是 kebab-case 的 -->
        <blog-post post-title="hello!"></blog-post>
      

      因此,强烈建议kebab-case写法。

    • prop 类型
      通常,以字符串数组形式列出 prop:

        props: ['title', 'likes', 'isPublished', 'commentIds', 'author']
      

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

        props: {
            title: String,
            likes: Number,
            isPublished: Boolean,
            commentIds: Array,
            author: Object,
            callback: Function,
            contactsPromise: Promise // or any other constructor
        }
      
    • 传递静态或动态prop
      传递静态值:

        <blog-post title="My journey with Vue"></blog-post>
      

      传递动态值

        <!-- 动态赋予一个变量的值 -->
        <blog-post v-bind:title="post.title"></blog-post>
      
        <!-- 动态赋予一个复杂表达式的值 -->
        <blog-post
        v-bind:title="post.title + ' by ' + post.author.name"
        ></blog-post>
      

      实际上,能传递的值包括:字符串、数字、布尔值、数组、对象、对象所有属性。

    • 单向数据流

      所有的 prop 都使得其父子 prop 之间形成了一个单向下行绑定:父级 prop 的更新会向下流动到子组件中,但是反过来则不行。

    • prop验证

        Vue.component('my-component', {
            props: {
                // 基础的类型检查 (`null` 和 `undefined` 会通过任何类型验证)
                propA: Number,
                // 多个可能的类型
                propB: [String, Number],
                // 必填的字符串
                propC: {
                    type: String,
                    required: true
                },
                // 带有默认值的数字
                propD: {
                    type: Number,
                    default: 100
                },
                // 带有默认值的对象
                propE: {
                type: Object,
                // 对象或数组默认值必须从一个工厂函数获取
                    default: function () {
                        return { message: 'hello' }
                    }
                },
                // 自定义验证函数
                propF: {
                validator: function (value) {
                    // 这个值必须匹配下列字符串中的一个
                    return ['success', 'warning', 'danger'].indexOf(value) !== -1
                }
            }
            }
        })
      

      上面的type可以是原生构造函数的一个:StringNumberBooleanArrayObjectDateFunctionSymbol

    • 非 Prop 的特性
      一个非 prop 特性是指传向一个组件,但是该组件并没有相应 prop 定义的特性。

      • 替换/合并已有的特性
        对于绝大多数特性来说,从外部提供给组件的值会替换掉组件内部设置好的值,classstyle 特性会稍微智能一些,即两边的值会被合并起来。
      • 禁用特性继承
        组件的选项中设置 inheritAttrs: false ,适合配合实例的 $attrs 属性使用:
          Vue.component('base-input', {
            inheritAttrs: false,
            props: ['label', 'value'],
            template: `
                <label>
                {{ label }}
                <input
                    v-bind="$attrs"
                    v-bind:value="value"
                    v-on:input="$emit('input', $event.target.value)"
                >
                </label>
            `
            })
        

    自定义事件

    • 事件名
      不同于组件和 prop,事件名不存在任何自动化的大小写转换。而是触发的事件名需要完全匹配监听这个事件所用的名称:

        this.$emit('myEvent')
      

      则监听这个名字的 kebab-case 版本是不会有任何效果的:

        <!-- 没有效果 -->
        <my-component v-on:my-event="doSomething"></my-component>
      

      推荐始终使用 kebab-case 的事件名

    • 自定义组件的 v-model

        Vue.component('base-checkbox', {
        model: {
            prop: 'checked',
            event: 'change'
        },
        props: {
            checked: Boolean
        },
        template: `
            <input
            type="checkbox"
            v-bind:checked="checked"
            v-on:change="$emit('change', $event.target.checked)"
            >
        `
        })
      
        <base-checkbox v-model="lovingVue"></base-checkbox>
      
    • 将原生事件绑定到组件
      使用 v-on 的 .native 修饰符:

        <base-input v-on:focus.native="onFocus"></base-input>
      

      Vue 提供了一个 $listeners 属性,它是一个对象,里面包含了作用在这个组件上的所有监听器。可以配合 v-on="$listeners" 将所有的事件监听器指向这个组件的某个特定的子元素。

        Vue.component('base-input', {
        inheritAttrs: false,
        props: ['label', 'value'],
        computed: {
            inputListeners: function () {
            var vm = this
            // `Object.assign` 将所有的对象合并为一个新对象
            return Object.assign({},
                // 我们从父级添加所有的监听器
                this.$listeners,
                // 然后我们添加自定义监听器,
                // 或覆写一些监听器的行为
                {
                // 这里确保组件配合 `v-model` 的工作
                input: function (event) {
                    vm.$emit('input', event.target.value)
                }
                }
            )
            }
        },
        template: `
            <label>
            {{ label }}
            <input
                v-bind="$attrs"
                v-bind:value="value"
                v-on="inputListeners"
            >
            </label>
        `
        })
      
    • .sync 修饰符
      update:myPropName 的模式触发事件

        this.$emit('update:title', newTitle)
      
        <text-document
        v-bind:title="doc.title"
        v-on:update:title="doc.title = $event"
        ></text-document>
      

      缩写:

        <text-document v-bind:title.sync="doc.title"></text-document>
      

      同时设置多个 prop :

        <text-document v-bind.sync="doc"></text-document>
      

    插槽

    • 插槽内容

       <navigation-link url="/profile">
        Your Profile
        </navigation-link>
      

      <navigation-link> 的模板中:

        <a v-bind:href="url" class="nav-link">
        <slot></slot>
        </a>
      

      Your Profile会替换<slot></slot>部分。Your Profile可以是HTML代码或者其他插件。

    • 编译作用域
      父级模板里的所有内容都是在父级作用域中编译的;子模板里的所有内容都是在子作用域中编译的。

        <navigation-link url="/profile">
        Clicking here will send you to: {{ url }}
        <!--
        这里的 `url` 会是 undefined,因为 "/profile" 是
        _传递给_ <navigation-link> 的而不是
        在 <navigation-link> 组件内部定义的。
        -->
        </navigation-link>
      
    • 后备内容(默认值)

        <button type="submit">
          <slot>Submit</slot>
        </button>
      

      这里的Submit就是默认值。

    • 具名插槽
      <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>
      
    • 作用域插槽
      绑定在 <slot> 元素上的特性被称为插槽 prop。现在在父级作用域中,我们可以给 v-slot 带一个值来定义我们提供的插槽 prop 的名字:

        <current-user>
        <template v-slot:default="slotProps">
            {{ slotProps.user.firstName }}
        </template>
        </current-user>
      
      • 独占默认插槽的缩写语法

          <current-user v-slot:default="slotProps">
            {{ slotProps.user.firstName }}
          </current-user>
        
      • 解构插槽 Prop

          <current-user v-slot="{ user }">
            {{ user.firstName }}
          </current-user>
        
    • 动态插槽名

        <base-layout>
        <template v-slot:[dynamicSlotName]>
            ...
        </template>
        </base-layout>
      
    • 具名插槽的缩写

      (v-slot:) 替换为字符 #

    • 其它示例(略)

    动态组件&&异步组件

    • 在动态组件上使用 keep-alive
      曾经在一个多标签的界面中使用 is 特性来切换不同的组件:

        <component v-bind:is="currentTabComponent"></component>
      

      可以用一个 <keep-alive> 元素将其动态组件包裹起来,避免切换的时候重新渲染:

        <!-- 失活的组件将会被缓存!-->
        <keep-alive>
        <component v-bind:is="currentTabComponent"></component>
        </keep-alive>
      
    • 异步组件(略)

    处理边界情况

    这些特殊场景和危险情况需要留心~

    • 访问元素 & 组件

      • 访问根实例
        $root属性
      • 访问父级组件实例
        $parent属性
      • 访问子组件实例或子元素
        ref特性
      • 依赖注入
        新的实例选项:provideinject
    • 程序化的事件侦听器

      • 通过 $on(eventName, eventHandler) 侦听一个事件
      • 通过 $once(eventName, eventHandler) 一次性侦听一个事件
      • 通过 $off(eventName, eventHandler) 停止侦听一个事件
    • 循环引用

      • 递归组件
      • 组件之间的循环引用
    • 模板定义的替代品

      • 内联模板
      • X-Template
    • 控制更新

      • 强制更新
        $forceUpdate
      • 通过 v-once 创建低开销的静态组件
  • 相关阅读:
    理解 Delphi 的类(十) 深入方法[15] 调用其他单元的函数
    理解 Delphi 的类(十) 深入方法[13] 在 interface 区声明的方法
    理解 Delphi 的类(十) 深入方法[12] implementation 区中的方法
    理解 Delphi 的类(十) 深入方法[6] Result
    什么是B*树倒排索引技术 已解决 搜搜问问
    caoruntao的博客 数据结构及算法分类文章列表 ITeye技术网站
    PForDelta索引压缩算法的实现
    计算机词汇(融合了搜狗所有的计算机词库)_搜狗输入法词库
    一种由B+树实现的倒排索引《电脑知识与技术》2011年08期
    海量数据处理专题(九)——外排序
  • 原文地址:https://www.cnblogs.com/huangmengke/p/11656632.html
Copyright © 2020-2023  润新知