数据绑定 / 组件通讯

  • 当前函数运行形成传递的数据改变的执行顺序:一、执行完当前函数(这个时候调用子组件中的方法拿到的值依然是旧的,由于还未传递到子组件中)。 二、传递数据到子组件中。三、执行页面更新
// 父组件
<my-components :commonData='commonData' @changeCommonData='changeCommonData'></my-components>
changeCommonData(data){
    this.commonData = data
}

// my-components子组件中
doSome(){
    this.$emit('changeCommonData',data) // data === 2,这时父组件中的commonData已经更改成2,可是子组件的响应,要等待当前函数执行完后响应
    console.log(this.commonData) // 原始值是1,
}

—————————————————————————————————————————————————————————

组件内

props

  • 使用some-propssomeProps的命名方式,外部均可以经过some-propssomeProps赋值,在内部只能经过this.someProps得到
    • 内部使用驼峰式命名
    • 外部视使用状况是否使用驼峰式
  • 不能使用this
  • .sync对一个 prop 进行“双向绑定”。
<text-document v-bind:title.sync="doc.title"></text-document>
// 实际为
<text-document
  v-bind:title="doc.title"
  v-on:update:title="doc.title = $event" 
></text-document>

...
watch:{
    title(newTitle){
        this.$emit('update:title', newTitle) 
    }
}
...
  • 能够传入一个未定义的prop,会自动添加到的根元素上(不必定会添加到根元素上,组件能够经过设置inheritAttrs来禁止绑定,同时还能够经过$attrs来获取绑定到组件上的属性)。对于绝大多数特性来讲,从外部提供给组件的值会替换掉组件内部设置好的值。因此若是传入 type="text" 就会替换掉 type="date" 并把它破坏!庆幸的是,class 和 style 特性会稍微智能一些,即两边的值会被合并起来,从而获得最终的值
  • 验证,props 会在一个组件实例建立以前进行验证,因此实例的属性 (如 data、computed 等) 在 default(默认值,当是数组或对象时须要函数返回) 或 validator 函数(传入值校验)中是不可用的。
props: {
    propA:{
        type: Number,
        default: 100, // 对象或数组默认值必须从一个工厂函数获取
        required: true, // 必传
        validator: function (value) { // 自定义验证函数
            // 这个值必须匹配下列字符串中的一个
            return ['success', 'warning', 'danger'].indexOf(value) !== -1
        }
    }
}
  • type能够是下列原生构造函数中的一个String、Number、Boolean、Array、Object、Date、Function、Symbol,还能够是一个自定义的构造函数,而且经过 instanceof 来进行检查确认。prop 的值是不是经过 new Person 建立的。
function Person (firstName, lastName) {
  this.firstName = firstName
  this.lastName = lastName
}

Vue.component('blog-post', {
  props: {
    author: Person
  }
})
// 类同于
propA: Number

inheritAttrs

  • 能够传入一个未定义的prop,会自动添加到的根元素上(不必定会添加到根元素上,组件能够经过设置inheritAttrs来禁止绑定,同时还能够经过$attrs来获取绑定到组件上的属性)。对于绝大多数特性来讲,从外部提供给组件的值会替换掉组件内部设置好的值。因此若是传入 type="text" 就会替换掉 type="date" 并把它破坏!庆幸的是,class 和 style 特性会稍微智能一些,即两边的值会被合并起来,从而获得最终的值
  • 若是你不但愿组件的根元素继承特性,你能够设置在组件的选项中设置
Vue.component('my-component', {
  inheritAttrs: false,
  // ...
})

—————————————————————————————————————————————————————————

组件外

v-bind

  • 当在一个自定义组件上使用 class 属性时,这些类将被添加到该组件的根元素上面。这个元素上已经存在的类不会被覆盖。
  • 当绑定为布尔值flase时,该特性不会绑定给元素
  • 当 v-bind:style 使用须要添加浏览器引擎前缀的 CSS 属性时,如 transform,Vue.js 会自动侦测并添加相应的前缀。因此尽可能使用(须要browserslist目标浏览器支持吗?)
  • 从 2.3.0 起你能够为 style 绑定中的属性提供一个包含多个值的数组,这样写只会渲染数组中最后一个被浏览器支持的值。(须要browserslist目标浏览器支持吗?)
<div :style="{ display: ['-webkit-box', '-ms-flexbox', 'flex'] }"></div>
  • 若是你想要将一个对象的全部属性都做为 prop 传入,你可使用不带参数的 v-bind (取代 v-bind:prop-name)。可是不容许绑定字面量对象,例如v-bind=”{ title: doc.title }”没法正常工做
<blog-post v-bind="post"></blog-post>
// 等价于
<blog-post
  v-bind:id="post.id"
  v-bind:title="post.title"
></blog-post>

v-model

  • 在inpu中,可使用修饰符.lazy(使用 change 事件进行输入数据同步).number(自动将用户的输入值转为数值类型,原生中即便在 type="number" 时,HTML 输入元素的值也总会返回字符串).trim(自动过滤用户输入的首尾空白字符)
  • 对于须要使用输入法 (如中文、日文、韩文等) 的语言,你会发现 v-model 不会在输入法组合文字过程当中获得更新。若是你也想处理这个过程,请使用 input 事件。当用输入法时可以捕获输入的每一个拼音字母vue

  • 下拉菜单选项的value能够绑定为任意内存对象,不必定要是字符串。只要传入相同键值的对象就可以选中下拉项(测试来源于饿了吗组件)
  • select下拉菜单,单选为文本,多选为文本数组(option有value时优先绑定)。若是 v-model 表达式的初始值未能匹配任何选项,<select> 元素将被渲染为“未选中”状态。在 iOS 中,这会使用户没法选择第一个选项。由于这样的状况下,iOS 不会触发 change 事件。所以,更推荐提供一个值为空的禁用选项。
<div id="example-5">
  <select v-model="selected"> // selected 默认为''
    <option disabled value="">请选择</option>
    <option>A</option>
    <option>B</option>
    <option>C</option>
  </select>
  <span>Selected: {{ selected }}</span>
</div>
  • 单选按钮绑定value值
<input type="radio" id="huey" name="drone" value="huey" checked>    // checked初始被选中
  • 复选框能够单独设置选中和未选中时的值
<input
  type="checkbox"
  v-model="toggle"
  true-value="yes"
  false-value="no"
>
  • 单个复选框,绑定到布尔值:<input type="checkbox" id="checkbox" v-model="checked">选中时checked为true,不然为false。不须要value
  • 多个复选框,绑定到同一个数组:
<div id='example-3'>
  <input type="checkbox" id="jack" value="Jack" v-model="checkedNames">
  <label for="jack">Jack</label>
  <input type="checkbox" id="john" value="John" v-model="checkedNames">
  <label for="john">John</label>
</div>

new Vue({
  el: '#example-3',
  data: {
    checkedNames: []    //=>['Jack','John']
  }
})
  • 在组件中使用v-model
// input中
<input v-model="searchText">
// 等价于
<input
  v-bind:value="searchText"
  v-on:input="searchText = $event.target.value"    // 这里的$event是事件对象
>


// 组件中
// 组件外部使用
<custom-input v-model="searchText"></custom-input>
// 等价于
<custom-input
  v-bind:value="searchText"
  v-on:input="searchText = $event"
></custom-input>

// 组件内部定义
Vue.component('custom-input', {
  props: ['value'],
  template: `
    <input
      v-bind:value="value"
      v-on:input="$emit('input', $event.target.value)" // $event.target指向时间对象,input对象有value属性
    >
  `
})
  • 一个组件上的 v-model 默认会利用名为 value 的 prop 和名为 input 的事件
Vue.component('base-checkbox', {
  model: {
    prop: 'checked',
    event: 'change'
  },

<base-checkbox v-model="lovingVue"></base-checkbox>
// 使用 v-model 的时候,这里的 lovingVue 的值将会传入这个名为 checked 的 prop。同时当 <base-checkbox> 触发一个 change 事件并附带一个新的值的时候,这个 lovingVue 的属性将会被更新。

—————————————————————————————————————————————————————————

插槽通信

slot和slot-scope

  • 做用域插槽(从子组件传数据给父组件处理)
// 组件
<ul>
  <li
    v-for="todo in todos"
    v-bind:key="todo.id"
  >
    <!-- 咱们为每一个 todo 准备了一个插槽,-->
    <!-- 将 `todo` 对象做为一个插槽的 prop 传入。-->
    <slot v-bind:todo="todo">
      <!-- 回退的内容 -->
      {{ todo.text }}
    </slot>
  </li>
</ul>

// 使用(获取组件中传出的数据)
<todo-list v-bind:todos="todos">
  <!-- 将 `slotProps` 定义为插槽做用域的名字 -->
  <template slot-scope="slotProps"> // 这里可使用解构语法{ todo }
    <!-- 为待办项自定义一个模板,-->
    <!-- 经过 `slotProps` 定制每一个待办项。-->
    <span v-if="slotProps.todo.isComplete">✓</span>
    {{ slotProps.todo.text }}
  </template>
</todo-list>
  • 普通slot(非做用域插槽)能够传入多个子元素

<template>

  • v-show 不支持 <template> 元素。若是须要很是频繁地切换,则使用 v-show 较好;

—————————————————————————————————————————————————————————

后代组件通信

provide / inject

  • provide 选项容许咱们指定咱们想要提供给后代组件的数据/方法。当多个子/孙组件须要调用同一个父组件的方法时使用。而后在任何后代组件里,咱们均可以使用 inject 选项来接收指定的咱们想要添加在这个实例上的属性(provide 和 inject 绑定并非可响应的。这是刻意为之的。然而,若是你传入了一个可监听的对象,那么其对象的属性仍是可响应的。在 Vue 2.2.1以前inject中的值在prop和data以后初始化)
// 父级组件提供 'foo'
var Provider = {
  provide: { // provide 选项应该是一个对象或返回一个对象的函数。
    foo: 'bar'
  },
  // ...
}

// 子组件注入 'foo'
var Child = {
  inject: ['foo'], 
  created () {
    console.log(this.foo) // => "bar"
  }
  // ...
}
// inject 选项应该是数组或对象(该对象的 key 是本地的绑定名,value 是搜索用的 key 或一个包含from和default属性的对象。(对象的from 属性是在可用的注入内容中搜索用的 key 、default 属性是降级状况下使用的 value))
inject:{
    myFoo1:'foo',
    myFoo:{
        from:'foo',
        default:'boy' // 与 prop 的默认值相似,你须要对非原始值(数组、对象)使用一个工厂方法
    }
}

bus只是一种解决方案并非vue提供的官方示例

  • 局部bus
// 组件1
import Bus from './Bus'

export default {
    data() {
        return {
            .........
            }
      },
  methods: {
        ....
        Bus.$emit('log', 120)
    },

  } 

// 组件2
import Bus from './Bus'

export default {
    data() {
        return {
            .........
            }
      },
    mounted () {
       Bus.$on('log', content => { 
          console.log(content)
        });    
    }    
}
  • 全局bus
import Vue from 'vue'
const Bus = new Vue()

var app= new Vue({
    el:'#app',
   data:{
    Bus
    }  

})
相关文章
相关标签/搜索