美文网首页
Vue教程进阶篇

Vue教程进阶篇

作者: A郑家庆 | 来源:发表于2019-03-31 16:46 被阅读0次

    深入了解组件

    组件注册

    全局注册
    Vue.component('my-component-name', {})
    
    局部注册

    如果所有的组件都用全局注册意味着即使你已经不再使用一个组件,它仍然会被包含在全局环境中,这就造成javascript无谓的增加。

    基础组件的自动化全局注册

    可能你的许多组件只是包裹了一个输入框或按钮之类的元素,是相对通用的。我们有时候会把它们称为基础组件,它们会在各个组件中被频繁的用到,如果我们在很多组件中都用到,那么就都需要引入,会比较麻烦,这时候我们可以使用require.context只全局注册这些非常通用的基础组件,不需要在每个需要引入的组件中引入,可以直接写。在main.js中写:

    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

    HTML中的特性名是大小写不敏感,所以浏览器会把所有大写字符解释为小写字符。这意味着当你使用DOM中的模版时,驼峰命名法都需要使用其等价的kebab-case(短横线分隔命名)命名。

    传入一个布尔值
    <!-- 包含该prop没有值的情况在内,都意味着true -->
    <blog-post is-published></blog-post>
    

    #######传入一个对象的所有属性
    如果你想要将一个对象的所有属性都作为prop传入,你可以使用不带参数的v-bind(取代v-bind:prop-name)。例如,对于一个给定的对象post:

    post: {
       id: 1,
       title: 'My Journey with Vue'
    }
    

    下面的模版:

    <blog-post v-bind="post"></blog-post>
    

    等价于:

    <blog-post
      v-bind:id="post.id"
      v-bind:title="post.title"
    ></blog-post>
    

    单向数据流

    prop只能父传子不能子传父,这里有两种常见的试图改变一个prop的情形:
    1.这个prop用来传递一个初始值,这个子组件接下来希望将其作为一个本地的prop数据来使用。

    props: ['initialCounter'],
    data: function () {
      return {
        counter: this.initialCounter
      }
    }
    

    2.这个prop以一个原始的值传入且需要进行转换。

    props: ['size'],
    computed: {
      normalizedSize: function () {
        return this.size.trim().toLowerCase()
      }
    }
    

    注意在JavaScript中对象和数组是通过引用传入的,所以对于一个数组或对象类型的prop来说,在子组件中改变这个对象或数组本身将会影响到父组件的状态。

    非prop的特性

    如果在自定义组件上添加一个属性,没有使用prop,那么这个属性就会被添加到组件的根元素上。

    <bootstrap-date-input data-date-picker="activated"></bootstrap-date-input>
    

    然后这个 data-date-picker="activated" 特性就会自动添加到 <bootstrap-date-input> 的根元素上。

    替换/合并已有的特性

    如果给自定义组件添加属性,但是组件内部的模版上也有同样的属性,那么会有不一样的处理结果。

    // 组件
    <bootstrap-date-input
      type="text"
      style="color:black"
      data-date-picker="activated"
      class="date-picker-theme-dark"
    ></bootstrap-date-input>
    // 组件内
    <input type="date" class="form-control"  style="color:white">
    

    我们会发现组件外的type会将组件内的type替换掉,但是class和style特性会智能一些,会将组件内和组件外的合并。

    禁用特性继承

    如果你不希望组件的根元素继承特性,你可以在组件的选项中设置inheritAttrs: false。例如:

    Vue.component('my-component', {
      inheritAttrs: false,
      // ...
    })
    

    这尤其适合配合实例的$attrs属性使用,该属性包含了传递给一个组件的特性名和特性值,例如:

    {
      required: true,
      placeholder: 'Enter your username'
    }
    

    有了 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>
      `
    })
    

    注意 inheritAttrs: false 选项不会影响 style 和 class 的绑定。

    相关文章

      网友评论

          本文标题:Vue教程进阶篇

          本文链接:https://www.haomeiwen.com/subject/oyqubqtx.html