Vue2Study(三)

11.表单输入绑定

v-model 会忽略所有表单元素的 valuecheckedselected attribute 的初始值而总是将 Vue 实例的数据作为数据来源。你应该通过 JavaScript 在组件的 data 选项中声明初始值。

v-model 在内部为不同的输入元素使用不同的 property 并抛出不同的事件:

  • text 和 textarea 元素使用 value property 和 input 事件;
  • checkbox 和 radio 使用 checked property 和 change 事件;
  • select 字段将 value 作为 prop 并将 change 作为事件。
修饰符
  • .lazy 在 change 事件_之后_进行同步
  • .number 将用户的输入值转为数值类型
  • .trim 自动过滤用户输入的首尾空白字符

12.组件基础

1.一个组件的 data 选项必须是一个函数

因此每个实例可以维护一份被返回对象的独立的拷贝:

1
2
3
4
5
data: function () {
return {
count: 0
}
}

2.组件的组织

  • 全局注册

    全局注册的行为必须在根 Vue 实例 (通过 new Vue) 创建之前发生

    1
    2
    3
    Vue.component('my-component-name', {
    // ... options ...
    }
  • 局部注册

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    import ComponentA from './ComponentA'
    import ComponentC from './ComponentC'

    export default {
    components: {
    ComponentA,
    ComponentC
    },
    // ...
    }
  • 基础组件的自动化全局注册

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    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
    )
    })

    //真实案例
    // Globally register all base components for convenience, because they
    // will be used very frequently. Components are registered using the
    // PascalCased version of their file name.

    import Vue from 'vue'

    // https://webpack.js.org/guides/dependency-management/#require-context
    const requireComponent = require.context(
    // Look for files in the current directory
    '.',
    // Do not look in subdirectories
    false,
    // Only include "_base-" prefixed .vue files
    /_base-[\w-]+\.vue$/
    )

    // For each matching file name...
    requireComponent.keys().forEach((fileName) => {
    // Get the component config
    const componentConfig = requireComponent(fileName)
    // Get the PascalCase version of the component name
    const componentName = fileName
    // Remove the "./_" from the beginning
    .replace(/^\.\/_/, '')
    // Remove the file extension from the end
    .replace(/\.\w+$/, '')
    // Split up kebabs
    .split('-')
    // Upper case
    .map((kebab) => kebab.charAt(0).toUpperCase() + kebab.slice(1))
    // Concatenated
    .join('')

    // Globally register the component
    Vue.component(componentName, componentConfig.default || componentConfig)
    })

    3.通过Prop向子组件传递数据

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    <blog-post
    v-for="post in posts"
    v-bind:key="post.id"
    v-bind:post="post"
    ></blog-post>

    Vue.component('blog-post', {
    props: ['post'],
    template: `
    <div class="blog-post">
    <h3>{{ post.title }}</h3>
    <div v-html="post.content"></div>
    </div>
    `
    })

4.监听子组件事件

  • 使用事件抛出一个值

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    <button v-on:click="$emit('enlarge-text', 0.1)">
    Enlarge text
    </button>

    <blog-post
    ...
    v-on:enlarge-text="onEnlargeText"
    ></blog-post>

    methods: {
    onEnlargeText: function (enlargeAmount) {
    this.postFontSize += enlargeAmount
    }
    }
  • 在组件上使用v-model

    为了让它正常工作,这个组件内的 <input> 必须:

    • 将其 value attribute 绑定到一个名叫 value 的 prop 上
    • 在其 input 事件被触发时,将新的值通过自定义的 input 事件抛出
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    Vue.component('custom-input', {
    props: ['value'],
    template: `
    <input
    v-bind:value="value"
    v-on:input="$emit('input', $event.target.value)"
    >
    `
    })
    <custom-input v-model="searchText"></custom-input>