vue 文档笔记

176 阅读3分钟

前言

本文是通读vue文档的笔记,记录了自己忽略或者不熟悉的知识点,以便后续查阅。有些语言描述是根据自己的理解而来的,表达可能不够准确,如有疑惑,还请查阅官方文档,当然也希望与您一起谈论,共同进步。(未完)

基础

  • v-once: 使用它可以计算一次后不再计算,大大提高性能,但是只要在确定不会再有更新的时候使用
  • 强制更新$forceUpdate
  • key 管理可复用的元素:Vue 会尽可能高效地渲染元素,通常会复用已有元素而不是从头开始渲染。但是有时这些元素需要相互独立,不能复用他们,此时需要添加一个唯一的key值即可;
  • v-if 与 v-show
  • 可以在<template>元素上使用v-if条件渲染分组,v-for列表渲染
  • v-for 可以使用对象

vue 实例

  • vue实例在生成的过程中会有一系列的动作,需要设置数据监听 编译模板 将实例挂载到dom并在数据变化是更新dom等
  • 生命周期

模板语法

  • v-html: 你的站点上动态渲染的任意 HTML 可能会非常危险,因为它很容易导致 XSS 攻击。

计算属性和侦听器

  • computed具有缓存功能,不能传参;methods没有缓存功能,可以传参; watch 当需要根据变化执行异步操作或者开销比较大的时候使用。

事件处理

  • 事件修饰符:.stop .prevent .capture .self .once .passive
  • 按键修饰符: .enter .tab .delete .esc .space .up .down
  • 系统修饰符:ctrl .alt .shift .meta
  • .exact修饰符 : 精确触发
  • 鼠标按钮修饰符: .left .right .middle

深入了解组件

组件注册

  • 全局注册基础组件:对于一些可能频繁用到的基础组件,可以在webpack(或者vue-cli3)中使用require.context 全局注册

    import Vue from 'vue'
    import upperFirst from 'lodash/upperFirst'
    import camelCase from 'lodash/camelCase'
    
    const requireComponent = require.context(
      // 其组件目录的相对路径
      './components',
      // 是否查询其子目录
      false,
      // 匹配基础组件文件名的正则表达式
      /Base[A-Z]\w+\.(vue|js)$/
    )
    
    requireComponent.keys().forEach(fileName => {
      // 获取组件配置
      const componentConfig = requireComponent(fileName)
    
      // 获取组件的 PascalCase 命名
      const componentName = upperFirst(
        camelCase(
          // 获取和目录深度无关的文件名
          fileName
            .split('/')
            .pop()
            .replace(/\.\w+$/, '')
        )
      )
    
      // 全局注册组件
      Vue.component(
        componentName,
        // 如果这个组件选项是通过 `export default` 导出的,
        // 那么就会优先使用 `.default`,
        // 否则回退到使用模块的根。
        componentConfig.default || componentConfig
      )
    })
    

Prop

  • 动态prop: prop作为父级向子组件传递数据时使用,可使用:传递动态prop(包括boolean,数组,对象,变量,表达式,数字);
  • prop验证:子组件接受数据是可以使用对象的方式验证(type,default,require)
  • 单项数据流:子组件可以通过data,compute接受传递的数据。对于作为引用类型的对象和数组,需要格外小心,不能在子组件中修改prop。确实需要修改可以复制一分副本
  • 合并/替换:对于大多数prop,使用替换的方式作用的组件的根元素中,而style class则可以智能的合并;如果不希望根元素被替换可以使用
  Vue.component('my-component', {
    inheritAttrs: false,
    // ...
  })

自定义事件

  • 组件和prop名称都会自动将大写字母转换为小写,事件名称不会

  • 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)"
           >
         `
        }) 
    
  • .sync 修饰符

    <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>
    
  • 将原生事件绑定到组件 : .native 具有局限性 可以使用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>
        `
      })
    

插槽

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

  • 后备内容

  • 具名插槽

    组件实例:

     <div class="container">
        <header>
          <slot name="header"></slot>
        </header>
        <main>
          <slot></slot>
        </main>
        <footer>
          <slot name="footer"></slot>
        </footer>
      </div>
    

    使用实例:

    <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 v-slot:footer>
          <p>Here is some contact info</p>
        </template>
      </base-layout>
    
  • 作用域插槽示例:

    组件中绑定
     <span>
      <slot v-bind:user="user">
        {{ user.lastName }}
      </slot>
    </span>
    使用:
    <current-user>
      <template v-slot:default="slotProps">
        {{ slotProps.user.firstName }}
      </template>
    </current-user>
    
  • 动态插槽名

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

    <base-layout>
      <template #header>
        <h1>Here might be a page title</h1>
      </template>
    </base-layout>
    
  • 解构

  • 旧语法

<slot-example>
   <template slot="default" slot-scope="slotProps">
     {{ slotProps.msg }}
   </template>
 </slot-example>

动态组件&异步组件

  • 在动态组件上使用keep-alive
  • 在大型应用中,我们可能需要将应用分割成小一些的代码块,并按需加载:如下代码示例:
       Vue.component('async-webpack-example', function (resolve) {
        // 这个特殊的 `require` 语法将会告诉 webpack
        // 自动将你的构建代码切割成多个包,这些包
        // 会通过 Ajax 请求加载
        require(['./my-async-component'], resolve)
      })
    
     Vue.component(
        'async-webpack-example',
        // 这个 `import` 函数会返回一个 `Promise` 对象。
        () => import('./my-async-component')
      )
    

组件间传值

  • 关键词:根组件$route 父级$parent 父级到子组件prop 子组件触发父级 $emit 祖级传递给子级provide 子级接收祖级inject 混入mixinx
  • 父级访问子组件实例或子元素ref,子级不能访问不要父级ref
  • 事件监听器 $on $once $off

模板定义的替代品

  • inline-template : 这里组件会使用组件里面的内容作为模板

    <my-component inline-template>
     <div>
      <p>These are compiled as the component's own template.</p>
      <p>Not parent's transclusion content.</p>
      </div>
    </my-component>
    
  • X-Template

    <script type="text/x-template" id="hello-world-template">
      <p>Hello hello hello</p>
    </script>
    
    Vue.component('hello-world', {
      template: '#hello-world-template'
    })
    

过渡 & 动画

可复用性 & 组合

混入

  • mixins 可以混合到组件中,选项合并,也可以定义合并策略

自定义指令

  • directive

渲染函数 & JSX

插件

  • 插件使用示例:
    // 调用 `MyPlugin.install(Vue)`
    Vue.use(MyPlugin)
    
    new Vue({
      // ...组件选项
    })
    
    或者
    Vue.use(MyPlugin, { someOption: true })
    
  • 插件开发实例:
        MyPlugin.install = function (Vue, options) {
      // 1. 添加全局方法或属性
      Vue.myGlobalMethod = function () {
        // 逻辑...
      }
    
      // 2. 添加全局资源
      Vue.directive('my-directive', {
        bind (el, binding, vnode, oldVnode) {
          // 逻辑...
        }
        ...
      })
    
      // 3. 注入组件选项
      Vue.mixin({
        created: function () {
          // 逻辑...
        }
        ...
      })
    
      // 4. 添加实例方法
      Vue.prototype.$myMethod = function (methodOptions) {
        // 逻辑...
      }
    }