美文网首页
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