VUE学习总结(一)

构造器

每一个Vue.js的应用都是通过够构造函数Vue创建的一个Vue的根实例。例如:

var vm = new Vue({
  // 选项  
})

上述代码中在实例化vue的时候需要传入一个对象,它可以包涵数据、模板、挂载元素、方法、生命周期钩子等。

当然为了创建可复用的组件构造器,我们可以通过扩展vue构造器的方法实现来实现预定义选项,通过扩展的预定义选项来创建更多可复用的组件。例如:

var MyComponent = Vue.extend({
  // 所扩展的预定义选项
})

var myComponentTnstance = new MyComponent()

vue中的data

在vue中每个实例都会去代理其data对象里面的所有属性,这些被代理的属性是响应的,如果属性改变就会触发视图的更新,但是如果属性是在实例创建之后添加的新属性那么久不会触发视图的更新。

vue生命周期

lifecycle.png

vue的计算属性computed

往往在模板中绑定表达式是非常方便的,但是这一方法值适合简单的操作,在模板中放入太多的逻辑会让模板过重并且难以维护,所以任何复杂的逻辑计算我们都需要用计算属性。

简单的例子:

<div id="test">
  <p>{{message}}</p>
  <p>{{myMessage}}</p>      
</div>

var vm = new Vue({
  el: '#test', // 将实例挂载到id位test的元素上去
  data: function () {
    return {
      message: 'hello'
    }
  },
  computed: {
    myMessage: function () {
      return this.message.split('').revers().join('')
    }
  }
})

在上述实例中myMessage的值是依赖于message的,所以message的值发生改变时候,myMessage的值相应的也会发生改变。

计算属性默认的只有getter,不过我们也可以通过需要提供一个setter:

computed: {
  fullName: {
    get: function () {
    }
    set: function () {
    }
  }
}

当fullName被赋值时,setter会被调用。

计算属性 vs methods

我们还可以通过vue实例中的methods来实现模拟计算属性的功能,在methods来定义一个函数来替代myMessage,该函数返回计算过后的值。不同的是计算属性是依赖缓存的。只有依赖的值发生改变的时候才会执行函数。而通过methods的方法则每次重新渲染的时候都会调用methods中的方法。用法根据实际使用。

代码示例:

<p>{{ myMessage() }}</p>

methods: {
  // 每次重新渲染的时候都会执行
  myMessage: function () {
    return this.message.split('').revers().join('')
  }
}

计算属性 vs watch

在vue中给我提供了一个$watch,用于观察vue实例上数据的变动,每当数据变动时会调用。通常如果是为了计算属性的话那么更好的办法还是使用computed。

v-if VS v-show

v-if
是真实的条件渲染,因为它会确保条件块在切换当中适当地销毁与重建条件块内的事件监听器和子组件。
v-if
也是惰性的:如果在初始渲染时条件为假,则什么也不做——在条件第一次变为真时才开始局部编译(编译会被缓存起来)。
相比之下, v-show
简单得多——元素始终被编译并保留,只是简单地基于 CSS 切换。
一般来说, v-if
有更高的切换消耗而 v-show
有更高的初始渲染消耗。因此,如果需要频繁切换使用 v-show
较好,如果在运行时条件不大可能改变则使用 v-if
较好。

vue组件

组件是vue一个强大的功能,组件是可以扩展html元素,封装可以重用的代码。

全局注册组件:

<div id="id">
  <my-component></my-component>
</div>

Vue.component('my-component', {
  template: '<p>我是一个组件</p>'
})

new Vue({
  el: '#id'
})

局部注册组件:

var child = {
  template: '<p>我是一个组件</p>'
}

new Vue({
  ...
  component: {
    'my-component': child
  }
})

在使用组件的时候代理数据data必须是一个函数,函数返回的是代理的数据。

组件之间的通信

父组件可以通过Prop来给子组件传递数据

prop是父组件用来传递数据的一个自定义属性。子组件需要显示的用props选项声明prop:

Vue.component('child', {
  // 子组件显示的声明props
  props: ['message'],
  // prop就像data一样可以再模板中使用也可以通过this来调用
  template: '<span> {{ message }} </spam>'
})

我么可以通过v-bind动态的绑定props的值到父组件的数据中,每次当绑定的数据在父组件中发生改变的时候,该组件也会相应的传递给子组件。

<child v-bind:child-message='message'></child>

如果要给prop传递一个字面的时候必须要使用v-bind这样传递下去的才是正真的字面量,否则都会当做字符串。

<child v-bind:number="1"></child>

prop是单向绑定的:当父组件的属性变化时,将传递给子组件,但是在子组件中改变数据的时候并不会传递给父组件,为了防止子组件无意间修改父组件的状态,所以不应该在子组件 中改变prop的数据。

如果想在子组件中想改变prop的值通常有二种情况:

  • prop 作为初始值传入,子组件之后只是将它的初始值作为本地数据的初始值使用。
props: ['initialCounter'],
data: function () {
  return {
    couter: this.initialCounter
  }
}
  • prop 作为需要被转变的原始值传入。
  props: ['size'],
  computed: {
    childSize: function () {
      return this.size.trim().toLowerCase()
    }
  }

组件可以给props指定一个验证要求,验证数据是否是某一个类型的数据,例如:

Vue.component('example', {
  props: {
    // 基础类型检测 (`null` 意思是任何类型都可以)
    propA: Number,
    // 多种类型
    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可以传递数据给子组件,但是如果子组件要把数据传递给父组件那么我们就要通过自定义事件的方法将数据传递给父组件。

使用v-on绑定自定义事件

每个vue实例都实现了事件接口(Events interface),即:

  • 使用$on(eventName) 监听事件
  • 使用$emit(eventName) 触发事件

父组件可以再使用子组件的地方直接使用v-on来监听子组件的触发:

<div id="counter-event-example">
  <p>{{ total }}</p>
  <!-- 使用v-on来监听子组件,如果$emit触发那么则该事件也会触发 -->
  <button-counter v-on:increment="incrementTotal"></button-counter>
  <button-counter v-on:increment="incrementTotal"></button-counter>
</div>

Vue.component('button-counter', {
  template: '<button v-on:click="increment">{{ counter }}</button>',
  data: function () {
    return {
      counter: 0
    }
  },
  methods: {
    increment: function () {
      this.counter += 1
      // 子组件中通过$emit触发事件往父组件传递数据
      this.$emit('increment')
    }
  },
})

new Vue({
  el: '#counter-event-example',
  data: {
    total: 0
  },
  methods: {
    // 父组件监听到子组件的$emit触发后才调用的方法
    incrementTotal: function () {
      this.total += 1
    }
  }
})

非父子组件的通信

非父子组件的通信我们一般往往用vuex

vue中的slot分发内容

当我们在使用vue组件的时候,我们常常要像如下代码一样组合它们:

<app>
  <app-header></app-header>
  <app-footer></app-footer>
</app>

为了让组件可以组合,我们需要一种方式来来混合父组件的内容和子组件的模板,这个过程被叫做内容分发,我们通过<slot>元素作为原始内容的插槽的方式来实现。

注意:父组件模板的内容应该就要在父组件 作用域内编译,子组件模板的内容应该在子组件作用域内编译。

<!-- 无效,应为someChildProperty是子组件的属性 -->
<child-component v-show="someChildProperty"></child-component>

Vue.component('child-component', {
   // 有效,因为是在正确的作用域内
  template: '<div v-          show="someChildProperty">Child</div>',
  data: function () {
    return {
      someChildProperty: true
    }
  }
})

在进行内容分发的时候子组件至少要有一个slot插槽,否则父组件中的内容将被丢弃。当子组件只有一个slot插槽的时候父组件的所有内容片断都将要插入子组件的slot插槽s所在DOM位子上,并替换掉slot插槽标签本身。

假设子组件模板my-component如下:

<div>
  <h2>我是子组件的标题</h2>
  <slot>
    只有在父组件没有要分发的内容时才会显示。
  </slot>
</div>

父组件模板如下:

<div>
  <h1>我是父组件的标题</h1>
  <my-component>
    <!-- 以下内容会进行分发到子组件模板上,如果子组件的模板没有slot插槽,那么内容会被抛弃,如果有一个slot插槽那么以下内容会替换掉slot插槽所在的DOM位子 -->
    <p>这是一些初始内容</p>
    <p>这是更多的初始内容</p>
  </my-component>

</div>

最终渲染的结果为:

<div>
  <h1>我是父组件的标题</h1>
  <div>
    <h2>我是子组件的标题</h2>
    <p>这是一些初始内容</p>
    <p>这是更多的初始内容</p>
  </div>
</div>

如果子组件有多个slot插槽的情况下我们可以通过具名slot将父组件的内容分别分发到子组件的对应名称的slot插槽上面。

在子组件的slot插槽标签上可以通过一个name属性来进行配置如何分发内容,同时父组件可以通过标签的slot属性来明确要分发到子组件中的某一个插槽中。

子组件:

<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>

在子组件插槽中可以通过slot插槽标签的text属性将数据传递到父组件要分发的内容当中,父组件要通过<template scopr=""></template>等模板来接受子组件插槽传递上来的数据。

子组件:

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

父组件:

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

推荐阅读更多精彩内容

  • 这篇笔记主要包含 Vue 2 不同于 Vue 1 或者特有的内容,还有我对于 Vue 1.0 印象不深的内容。关于...
    云之外阅读 5,044评论 0 29
  • 此文基于官方文档,里面部分例子有改动,加上了一些自己的理解 什么是组件? 组件(Component)是 Vue.j...
    陆志均阅读 3,799评论 5 14
  • 下载安装搭建环境 可以选npm安装,或者简单下载一个开发版的vue.js文件 浏览器打开加载有vue的文档时,控制...
    冥冥2017阅读 6,027评论 0 42
  • Vue 实例 属性和方法 每个 Vue 实例都会代理其 data 对象里所有的属性:var data = { a:...
    云之外阅读 2,198评论 0 6
  • 什么是组件 组件(Component)是 Vue.js 最强大的功能之一。组件可以扩展 HTML 元素,封装可重用...
    angelwgh阅读 776评论 0 0