jiaozitang / Vuejs-note

0 stars 0 forks source link

深入了解组件 #8

Open jiaozitang opened 6 years ago

jiaozitang commented 6 years ago

组件名:

Vue.component("my-nav",{})//nav组件名就是第一个参数

推荐遵循 W3C 规范中的自定义组件名 (字母全小写且必须包含一个连字符)

组件名大小写 1.使用 kebab-case

 Vue.component("my-nav",{})
<my-nav></my-nav>

2.使用 PascalCase

 Vue.component("myNav",{})
<my-nav></my-nav>或者<myNav></myNav>都行。

注意:直接在 DOM (即非字符串的模板) 中使用时只有 kebab-case 是有效的。

jiaozitang commented 6 years ago

全局注册组件 它们在注册之后可以用在任何新创建的 Vue 根实例 (new Vue) 的模板中。 在所有子组件中也是如此,也就是说这三个组件在各自内部也都可以相互使用。 全局注册的行为必须在根 Vue 实例 (通过 new Vue) 创建之前发生。

Vue.component("my-nav1",{})
Vue.component("my-nav2",{})
Vue.component("my-nav3",{})
<my-nav1></my-nav1>
<my-nav2></my-nav2>
<my-nav3></my-nav3>

例子:https://github.com/tang119/Vuejs-note/blob/master/components/Quanju.vue

jiaozitang commented 6 years ago

局部注册组件 局部注册的组件在其子组件中不可用

var myNav1 = {};
new Vue({
    components:{myNav1}
})
jiaozitang commented 6 years ago

Prop

大小写 HTML 中的特性名是大小写不敏感的,所以浏览器会把所有大写字符解释为小写字符。

/*在js中的props是camelCase的*/
props: ['postTitle'],
<!-- 在 HTML 中是 kebab-case 的 -->
<blog-post post-title="hello!"></blog-post>

Prop 类型 可以以对象形式列出 prop,这些属性的名称和值分别是 prop 各自的名称和类型

props: ['title', 'likes', 'isPublished', 'commentIds', 'author'];//字符串数组形式
props: {
      title: String,
      likes: Number,
      isPublished: Boolean,
      commentIds: Array,
      author: Object
};//对象形式

传递静态或动态 Prop

<v-model :val="val"></v-model>//传入一个字符串变量
<v-model v-bind="obj"></v-model>/传入val对象的所有属性等同于下面这行
<v-model :id="obj.id" :name="obj.name" ></v-model>
data(){
  return{
    val:"123",
    obj:{
        id:1,
        name:"tangjiao"
    }

单向数据流 1.这个 prop 用来传递一个初始值;这个子组件接下来希望将其作为一个本地的 prop 数据来使用。在这种情况下,最好定义一个本地的 data 属性并将这个 prop 用作其初始值:

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

2.这个 prop 以一种原始的值传入且需要进行转换。在这种情况下,最好使用这个 prop 的值来定义一个计算属性:

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

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

Prop 验证 为了定制 prop 的验证方式,你可以为 props 中的值提供一个带有验证需求的对象,而不是一个字符串数组。 image

替换/合并已有的特性

模板中:<input type="date" class="form-control">
父组件中引入时<bootstrap-date-input
  data-date-picker="activated"
  class="date-picker-theme-dark"
></bootstrap-date-input>

对于绝大多数特性来说,从外部提供给组件的值会替换掉组件内部设置好的值。所以如果传入 type="text" 就会替换掉 type="date" 并把它破坏!庆幸的是,class 和 style 特性会稍微智能一些,即两边的值会被合并起来,从而得到最终的值:form-control date-picker-theme-dark。

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

Vue.component('my-component', {
  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>

` }) 这个模式允许你在使用基础组件的时候更像是使用原始的 HTML 元素,而不会担心哪个元素是真正的根元素:

<base-input
v-model="username"
class="username-input"
placeholder="Enter your username"
    ></base-input>
jiaozitang commented 6 years ago

自定义事件

事件名

不区分大小写,在子组件中定义了$emit("changeTxt")方法,父组件只能<my-nav @="changeTxt">,而不能<my-nav @="change-txt"> 跟组件和 prop 不同,事件名不会被用作一个 JavaScript 变量名或属性名,所以就没有理由使用 camelCase 或 PascalCase 了。并且 v-on 事件监听器在 DOM 模板中会被自动转换为全小写 (因为 HTML 是大小写不敏感的),所以 v-on:myEvent 将会变成 v-on:myevent——导致 myEvent 不可能被监听到。 因此,我们推荐你始终使用 kebab-case 的事件名。

自定义组件的 v-model

一个组件上的 v-model 默认会利用名为 value 的 prop 和名为 input 的事件,但是像单选框、复选框等类型的输入控件可能会将 value 特性用于不同的目的。model 选项可以用来避免这样的冲突:

<template>
  <input type="checkbox" :checked="checked" @change="$emit('change',$event.target.checked)"/>

  <script>
  export default {
      name: "MyCheckbox",
      model: {
        prop: 'checked',
        event: 'change'
      },
      props:["checked"]
  }
</script>

image

将原生事件绑定到组件

<base-input v-on:focus.native="onFocus"></base-input>
jiaozitang commented 6 years ago

插槽

承载分发内容的出口 它允许你像这样合成组件:

<navigation-link url="/profile">
  Your Profile
</navigation-link>

然后你在 的模板中可能会写为:

<a v-bind:href="url" class="nav-link" >
    <slot></slot>
    </a>

当组件渲染的时候,这个 元素将会被替换为“Your Profile”。插槽内可以包含任何模板代码,包括 HTML。甚至其它的组件。

如果 没有包含一个 元素,则任何传入它的内容都会被抛弃。 image image

具名插槽

需要多个插槽时 在子组件中<slot name="name"></slot> 在父组件中<h1 slot="name"></name>或者<template slot="name><h1></h1></template> 我们还是可以保留一个未命名插槽,这个插槽是默认插槽,也就是说它会作为所有未匹配到插槽的内容的统一出口。 image image

jiaozitang commented 6 years ago

动态组件 & 异步组件

当在这些组件之间切换的时候,在动态组件上使用 keep-alive,保持这些组件的状态,以避免反复重渲染导致的性能问题。

<keep-alive>
  <component :is="currentTab"></component>
</keep-alive> 
jiaozitang commented 6 years ago

处理边界情况

1.访问元素 & 组件

1.1访问根实例$root

所有的子组件都可以通过$root访问到根组件的数据 image image

1.2访问父级组件实例$parent

1.3访问子组件实例或子元素 --ref 特性

image

1.4依赖注入

当要给一个组件的每个子组件都传递同一个方法时,可以使用依赖注入,依赖注入包含两个新的实例选项