Vue(篇幅二)

关于如何学习Vue,Vue的缔造者尤雨溪前辈曾经在知乎发表过一篇新手向:Vue 2.0 的建议学习顺序
关于Vue其他知识介绍:篇幅一

5. 组件
  1. 创建(注册)组件
// 注册(全局注册)
Vue.component('my-component', {
  template: '<div>A custom component!</div>'
})

组件在注册之后,便可以在父实例的模块中以自定义元素 <my-component></my-component> 的形式使用。要确保在初始化根实例之前注册了组件:

<div id="example">
  <my-component></my-component>
</div>
//这里注册
// 创建根实例
new Vue({
  el: '#example'
})
  1. data
    通过Vue构造器创建的组件中,data属性必须是函数。
Vue.component('my-app',{
 template: '<span>{{message}}</span>',
data: function(){
  return {
    message: 'hello'
  }
}
})
  1. Props
    子组件通过显式地用props选项声明它期待获得的数据。
  2. 单向数据流
    prop 是单向绑定的:当父组件的属性变化时,将传导给子组件,但是不会反过来。每次父组件更新时,子组件的所有 prop 都会更新为最新值。这意味着你不应该在子组件内部改变 prop。
    为什么我们会有修改 prop 中数据的冲动呢?通常是这两种原因:
    (1)prop 作为初始值传入后,子组件想把它当作局部数据来用;
    (2)prop 作为初始值传入,由子组件处理成其它数据输出。
    对这两种原因,正确的应对方式是:
    定义一个局部变量,并用 prop 的值初始化它:
props: ['initialCounter'],
data: function () {
  return { counter: this.initialCounter }
}

定义一个计算属性,处理 prop 的值并返回。

props: ['size'],
computed: {
  normalizedSize: function () {
    return this.size.trim().toLowerCase()
  }
}
  1. Prop验证
    组件传入的props可以进行数据验证。要指定验证规格,需要用对象的形式,而不能用字符串数组。如:
Vue.component('my-app',{
  props: {
    propA: Number,//基本类型,null表示任何类型都行
    propB: [String,Number],//多种类型
    propC: {
      type: String,
      required: true //必须传,且时字符串
    },
    propD: {
      type: Number,
      default: 100  // 数字,有默认值
    },
    propE: {
      type: Object,
      default: function () {
        return { message: 'hello' }
      } // 数组/对象的默认值应当由一个工厂函数返回
    }, 
    propF: {
      validator: function (value) {
        return value > 10  // 自定义验证函数
      }
    }
  }
})

注意:props会在组件实例创建之前进行校验,所以在 defaultvalidator 函数里,诸如datacomputedmethods 等实例属性还无法使用。

  1. 自定义事件
    子组件通过自定义事件跟父组件通信。
    5.1 使用v-on绑定自定义事件
    每个Vue实例都实现了事件接口,即:
  • 使用 $on(eventName) 监听事件
  • 使用 $emit(eventName) 触发事件
    另外,父组件可以在使用子组件的地方直接用v-on来监听子组件触发的事件。
    注意:不能用 $on 侦听子组件释放的事件,而必须在模板里直接用 v-on 绑定。例如:
<template>
<div id = "app">
   {{ count }}
  <child v-on:add="addcount"></child>
</div>
</template>
Vue.component('child',{
  template: '<button @click="increment">父组件count +1={{number}}</button>',
  data: function(){
    return {
      number : 0
    },
    method : {
      increment: function(){
        this.number++
        $.emit(add)
      }
    }
  }
})

new Vue({
  el: '#app',
  data: {
    count  : 0
  },
  methods: {
    addcount: function(){
      this.count++
    }
  }
})

以上代码表示,点击子组件按钮时候,会触发父组件的addcount() 事件
5.2 .sync修饰符
.sync作为一个编译语法糖存在,他会被扩展为一个自动更新父组件属性的v-on侦听器,如:
<comp :foo.sync="bar"></comp>
扩展为:
<comp :foo="bar" @update:foo="val => var =val"></comp>
当组件需要需要更新foo的值时,它需要显示地触发一个更新事件:
this.$emit('update:foo',newValue)
5.3 非父子组件通信
有时候两个组件也需要通信(非父子关系),简单的场景下,可以使用一个空的Vue实例作为中央事件总线:
var bus = new Vue()
bus.$emit('id-selected',1) //触发组件A中的事件
bus.$on('id-selected',function(id){})//在组件B创建的钩子中监听事件
注意:复杂情况下,应该考虑专门的状态管理模式

  1. 使用插槽分发内容
    为了让组件可以结合,我们需要一种方式来混合组租间的内容与子组件自己的模板,这个过程被称为内容分发,Vue使用<slot>作为原始内容的插槽。如下:
//app-layout 组件模板如下
<div class="container">
  <header>
    <slot name="header"></slot> //具名插槽
  </header>
  <main>
    <slot></slot> //默认插槽
  </main>
  <footer>
    <slot name="footer"></slot>
  </footer>
</div>
//父组件模板:
<app-layout>
  <h1 slot="header">这里可能是一个页面标题</h1>
  <p>主要内容的一个段落。</p>
  <p>另一个主要段落。</p>
  <p slot="footer">这里有一些联系信息</p>
</app-layout>
渲染结果为:
<div class="container">
  <header>
    <h1>这里可能是一个页面标题</h1>
  </header>
  <main>
    <p>主要内容的一个段落。</p>
    <p>另一个主要段落。</p>
  </main>
  <footer>
    <p>这里有一些联系信息</p>
  </footer>
</div>

6.1 编译作用域
分发内容实在父作用域内编译。
6.2 作用域插槽
作用域插槽是一种特殊类型的插槽,用作一个替换已渲染元素的 (能被传递数据的) 可重用模板。
在子组件中,只需将数据传递到插槽,就像你将 props 传递给组件一样:

<div class="child">
  <slot text="hello from child"></slot>
</div>

在父级中,具有特殊属性 scope 的 <template> 元素必须存在,表示它是作用域插槽的模板。scope 的值对应一个临时变量名,此变量接收从子组件中传递的 props 对象:

<div class="parent">
  <child>
    <template scope="props">
      <span>hello from parent</span>
      <span>{{ props.text }}</span>
    </template>
  </child>
</div>

如果我们渲染以上结果,得到的输出会是:

<div class="parent">
  <div class="child">
    <span>hello from parent</span>
    <span>hello from child</span>
  </div>
</div>

作用域插槽更具代表性的用例是列表组件,允许组件自定义应该如何渲染列表每一项:

<my-awesome-list :items="items">
  <!-- 作用域插槽也可以是具名的 -->
  <template slot="item" scope="props">
    <li class="my-fancy-item">{{ props.text }}</li>
  </template>
</my-awesome-list>

列表组件的模板:

<ul>
  <slot name="item"
    v-for="item in items"
    :text="item.text">
    <!-- 这里写入备用内容 -->
  </slot>
</ul>
  1. 子组件索引
    有时候需要在js中直接访问子组件,为此可以使用ref为子组件制定一个索引 ID,如下:
<div id="parent">
  <user-profile ref="profile"></user-profile>
</div>
var parent = new Vue({ el: '#parent' })
// 访问子组件
var child = parent.$refs.profile

注意:$refs 只在组件渲染完成后才填充,并且它是非响应式的。它仅仅作为一个直接访问子组件的应急方案——应当避免在模板或计算属性中使用 $refs

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,948评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,371评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,490评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,521评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,627评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,842评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,997评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,741评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,203评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,534评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,673评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,339评论 4 330
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,955评论 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,770评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,000评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,394评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,562评论 2 349

推荐阅读更多精彩内容