学习笔记-vue

VUE

What

Vue.js是一个构建数据驱动的web界面的库。技术上,它重点集中在MVVM模式的ViewModel层,因此它非常容易学习,非常容易与其它库或已有项目整合。

Vue.js的目标是通过尽可能简单的API实现响应的数据绑定和组合的视图。
  Vue.js 的核心是一个响应的数据绑定系统,它让数据与DOM保持同步非常简单。在使用jQuery手工操作DOM时,我们的代码常常是命令式的、重复的与易错的。Vue.js拥抱数据驱动的视图概念。通俗地讲,它意味着我们在普通HTML模板中使用特殊的语法将DOM “绑定”到底层数据。

安装

独立版本
  直接下载并用 < script > 标签引入,Vue会被注册为一个全局变量。如下代码,这样就可以在脚本中使用Vue.js了。
CDN
  也可以在 jsdelivr或 cdnjs获取 (版本更新可能会略滞后)。
NPM
  在用 Vue.js 构建大型应用时推荐使用 NPM 安装,NPM 能很好地和诸如 Webpack 或 Browserify 的 CommonJS 模块打包器配合使用。Vue.js 也提供配套工具来开发单文件组件。

$ npm install vue
# 获取CSP兼容版本:
$ npm install vue@csp
# 获取最新开发版本(来自于GitHub):
$ npm install yyx990803/vue#dev

构造器
每个Vue.js应用的起步都是通过构造函数Vue创建一个Vue的根实例:

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

一个Vue实例其实正是一个MVVM模式中所描述的 ViewModel - 因此在文档中经常会使用vm这个变量名
属性与方法
每个Vue实例都会代理其data对象里所有的属性,如下代码:

var data = { a: 1 }
var vm = new Vue({
  data: data
})
//vm.a === data.a  -> true
// 设置属性也会影响到原始数据
vm.a = 2
// data.a  -> 2
// ... 反之亦然
data.a = 3
//vm.a -> 3
注意只有这些被代理的属性是响应的。如果在实例创建之后添加新的属性到实例上,它不会触发视图更新。

除了前面这些数据属性,Vue实例还有一些有用的实例属性与方法。这些属性与方法都有前缀 $,以便与代理的数据属性区分。例如:

var data = { a: 1 }
var vm = new Vue({
  el: '#example',
  data: data
})
vm.$data === data // -> true
vm.$el === document.getElementById('example') // -> true
// $watch 是一个实例方法
vm.$watch('a', function (newVal, oldVal) {
  // 这个回调将在 `vm.a`  改变后调用
})

数据绑定语法

文本
数据绑定最基础的形式是文本插值,使用 {{}} 语法(双大括号):
<span>Message: {{ msg }}</span>
  {{ msg }} 标签会被相应数据对象的 msg 属性的值替换。每当这个属性变化时它也会更新。
  也可以只处理单次插值,今后的数据变化就不会再引起插值更新了:
<span>This will never change: {{* msg }}</span>
如下JavaScript代码:

var data={msg:'Hello Vue.js!'};
new Vue({
  el: '#demo',
  data: data
 })
data.msg="Hello World!";

原始HTML
双大括号标签将数据解析为纯文本而不是HTML。为了输出真的HTML字符串,需要用三大括号标签:
<div>{{{ msg }}}</div>
  如下javascript代码:

var data={msg:'<p>Hello Vue.js!</p>'};
new Vue({
    el: '#demo',
    data: data
   })

在网站上动态渲染任意 HTML 是非常危险的,因为容易导致 XSS 攻击。只在可信内容上使用 v-html,永远不要用在用户提交的内容上!
HTML特性
双大括号标签也可以用在 HTML 特性 (Attributes) 内:
<div id="{{ id }}"></div>
javascript代码如下:

var data={id:'demo'};
new Vue({
  el: 'div',
  data: data
 })

我们去查看HTML源码,是不是id已经变成我们设置的id了。
JavaScript表达式
Vue.js 在数据绑定内支持全功能的JavaScript表达式:

{{ number + 1 }}
{{ ok ? 'YES' : 'NO' }}
{{ message.split('').reverse().join('') }}

过滤器
Vue.js 允许在表达式后添加可选的“过滤器 (Filter) ”,以“管道符(|)”指示。过滤器本质上是一个函数,这个函数会接收一个值,将其处理并返回。
{{ message | uppercase }}
  这里我们将表达式 message 的值“管输(pipe)”到内置的 uppercase 过滤器,这个过滤器其实只是一个 JavaScript 函数,返回大写化的值。Vue.js 提供数个内置过滤器,在后面我们会谈到如何开发自己的过滤器。
  可以串联多个过滤器:
{{ message | filterA | filterB }}
html代码:

<div id='demo'>
<span>{{msg | lowercase | capitalize}}</span>
</div>

javaScript代码:

 var data={msg:'heLLO!'};
 new Vue({
  el: '#demo',
  data: data
 })

运行结果为:Hello
指令
Vue.js指令 (Directives) 是特殊的带有前缀v-的特性。本质是模板中出现的特殊标记,让处理模板的库知道需要对这里的DOM元素进行一些对应的处理。指令的职责就是当其表达式的值改变时把某些特殊的行为应用到 DOM 上。
<p v-if="msg">Hello!</p>
  这里 v-if 指令将根据表达式 msg 值的真假删除/插入 < p > 元素。
  在Vue.js中为我们提供了一些指令:v-text,v-html,v-model,v-on,v-else等等,同学们可以去查看Vue.js的指令api(cn.vuejs.org/api/#指令)。
javascript代码:

 var data={msg:0};
 new Vue({
  el: '#demo',
  data: data
 })

计算属性
在模板中表达式非常便利,但是它们实际上只用于简单的操作。模板是为了描述视图的结构。在模板中放入太多的逻辑会让模板过重且难以维护。这就是为什么 Vue.js 将绑定表达式限制为一个表达式。如果需要多于一个表达式的逻辑,应当使用计算属性。
  在 Vue.js 中,你可以通过 computed 选项定义计算属性:

<div id="example">
  a={{ a }}, b={{ b }}
</div>
var vm = new Vue({
  el: '#example',
  data: {
    a: 1
  },
  computed: {
    // 一个计算属性的 getter
    b: function () {
      // `this` 指向 vm 实例
      return this.a + 1
    }
  }
})

运行结果为:a=1,b=2

Class与Style绑定

Class对象语法
  可以传给 v-bind:class 一个对象,以动态地切换class。注意 v-bind:class 指令可以与普通的 class 特性共存。
html代码:

<div class="static" v-bind:class="{ 'class-a': isA, 'class-b': isB }"></div>

javascript代码:

var vm = new Vue({
  el: 'div',
  data: {
  isA: true,
  isB: false
}
})

渲染为:

<div class="static class-a">
</div>

当 isA 和 isB 变化时,class 列表将相应地更新。例如,如果 isB 变为 true,class 列表将变为 “static class-a class-b”。
Class数组语法
可以把一个数组传给 v-bind:class,以应用一个 class 列表:
html代码:

<div v-bind:class="[classA, classB]">

js代码:

var vm = new Vue({
  el: 'div',
  data: {
  classA: 'class-a',
  classB: 'class-b'
}
})

渲染为:

<div class="class-a class-b"></div>

Style对象语法
v-bind:style的对象语法十分直观——看着非常像 CSS,其实它是一个JavaScript对象。CSS属性名可以用驼峰式(camelCase)或短横分隔命名(kebab-case):
html代码:
<div v-bind:style="{ color: activeColor, fontSize: fontSize + 'px' }">Style 对象语法</div>
javascript代码:

var vm = new Vue({
  el: 'div',
  data: {
  activeColor: 'red',
  fontSize: 30
}
})

渲染为:

<div style="color: red; font-size: 30px;">Style 对象语法</div>

Style数组语法
v-bind:style的数组语法可以将多个样式对象应用到一个元素上。
<div v-bind:style="[styleObjectA, styleObjectB]">Style 数组语法</div>
javascript代码:

var vm = new Vue({
  el: 'div',
  data: {
  styleObjectA: {
    color: 'red'
  },
    styleObjectB: {
     fontSize: '30px'
  }
}
})

渲染为:

<div style="color: red; font-size: 30px;">Style 数组语法</div>

渲染指令

v-if
  在字符串模板中,如Handlebars,我们得像这样写一个条件块:

<!-- Handlebars 模板 -->
{{#if ok}}
  <h1>Yes</h1>
{{/if}}

在 Vue.js,我们使用 v-if 指令实现同样的功能:
<h1 v-if="ok">Yes</h1>
  也可以用 v-else 添加一个 “else” 块:

<h1 v-if="ok">Yes</h1>
<h1 v-else>No</h1>

template v-if
  因为 v-if 是一个指令,需要将它添加到一个元素上。但是如果我们想切换多个元素呢?此时我们可以把一个 元素当做包装元素,并在上面使用 v-if,最终的渲染结果不会包含它。

<template v-if="ok">
  <h1>Title</h1>
  <p>Paragraph 1</p>
  <p>Paragraph 2</p>
</template>

当ok为真值时,渲染为:

<h1>Title</h1>
<p>Paragraph 1</p>
<p>Paragraph 2</p>

v-show
  另一个根据条件展示元素的选项是 v-show 指令。用法大体上一样:
<h1 v-show="ok">Hello!</h1>
  不同的是有 v-show 的元素会始终渲染并保持在 DOM 中。v-show 是简单的切换元素的 CSS 属性 display。
v-else
  可以用 v-else 指令给 v-if 或 v-show 添加一个 “else 块”:

<div v-if="Math.random() > 0.5">
  Sorry
</div>
<div v-else>
  Not sorry
</div>

v-else 元素必须立即跟在 v-if 或v-show元素的后面,否则它不能被识别。
限制: 前一兄弟元素必须有 v-if 或 v-else-if。
v-for
当和 v-if 一起使用时,v-for 的优先级比 v-if 更高(先遍历,后判断)
  可以使用 v-for指令基于一个数组渲染一个列表。这个指令使用特殊的语法,形式为 item in items,items是数据数组,item是当前数组元素的别名:

<ul id="example">
  <li v-for="item in items">
    {{ item.message }}
  </li>
</ul>

js代码:

var example1 = new Vue({
  el: '#example',
  data: {
    items: [
      { message: 'one' },
      { message: 'two' }
    ]
  }
})

在 v-for 块内我们能完全访问父组件作用域内的属性,另有一个特殊变量 $index,正如你猜到的,它是当前数组元素的索引:

<ul id="example">
  <li v-for="item in items">
    {{ parentMessage }} - {{ $index }} - {{ item.message }}
  </li>
</ul>

js代码:

var example2 = new Vue({
  el: '#example',
  data: {
    parentMessage: 'Parent',
    items: [
      { message: 'one' },
      { message: 'two' }
    ]
  }
})

template v-for
  类似于 template v-if,也可以将 v-for 用在 template 标签上,以渲染一个包含多个元素的块。例如:

<ul>
  <template v-for="item in items">
    <li>{{ item.msg }}</li>
    <li class="divider"></li>
  </template>
</ul>

表单控件绑定

文本输入框Text
可以在表单的input 元素上使用v-model 指令来创建双向数据绑定。它会根据input元素的类型自动选取正确的绑定模式。

<span>Message is:{{msg}}</span>
<input type="text" v-model="msg" placeholder="edit me">

js代码:

var vm = new Vue({
  el: 'div',
  data: {
      msg:"hello world"
  }
})

其中placeholder为默认显示提示。
多选框Checkbox
多个勾选逻辑值,如下代码:

<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>
<input type="checkbox" id="mike" value="Mike" v-model="checkedNames">
<label for="mike">Mike</label>
<br>
<span>Checked names: {{ checkedNames }}</span>

当我们要绑定值时可以用v-bind来绑定,如下代码:

<div>
<input
  type="checkbox"
  v-model="toggle"
  v-bind:true-value="a"
  v-bind:false-value="b">
</div>

当checkbox为true时,值为a;当为fals时,值为b。
单选按钮Radio

<input type="radio" id="one" value="One" v-model="picked">
<label for="one">One</label>
<br>
<input type="radio" id="two" value="Two" v-model="picked">
<label for="two">Two</label>
<br>
<span>Picked: {{ picked }}</span>

我们可以用v-bind指令来绑定数据。如下代码:

<input type="radio" v-model="pick" v-bind:value="a">

下拉列表select
单选,如下代码:

<select v-model="selected">
  <option selected>A</option>
  <option>B</option>
  <option>C</option>
</select>
<span>Selected: {{ selected }}</span>

多选,如下代码:

<select v-model="selected" multiple>
  <option selected>A</option>
  <option>B</option>
  <option>C</option>
</select>
<br>
<span>Selected: {{ selected | json }}</span>

动态选项,用 v-for 渲染,如下代码:

<select v-model="selected">
  <option v-for="option in options" v-bind:value="option.value">
    {{ option.text }}
  </option>
</select>
<span>Selected: {{ selected }}</span>

js代码如下:

new Vue({
  el: 'div',
  data: {
    selected: 'A',
    options: [
      { text: 'One', value: 'A' },
      { text: 'Two', value: 'B' },
      { text: 'Three', value: 'C' }
    ]
  }
})

对象的格式应为 {text:’’, value:’’}。这允许你把展示的文字和其背后对应的值区分开来。
也可以用v-bind来绑定数据,如我们要绑定一个数值型的数据,如下代码:

<select v-model="selected">
  <!-- 对象字面量 -->
  <option v-bind:value="{ number: 123 }">123</option>
</select>

参数特性
lazy
  在默认情况下,v-model 在input 事件中同步输入框值与数据,可以添加一个特性 lazy,从而改到在 change 事件中同步:

<!-- 在 "change" 而不是 "input" 事件中更新 -->
<input v-model="msg" lazy>

如下实例,当在文本框中输入完成以后,才更新内容:

<span>Message is:{{msg}}</span>
<input type="text" v-model="msg" lazy>

number
  如果想自动将用户的输入保持为数字,可以添加一个特性 number:
<input v-model="age" number>
debounce
  debounce 设置一个最小的延时,在每次敲击之后延时同步输入框的值与数据。如果每次更新都要进行高耗操作(例如在输入提示中 Ajax 请求),它较为有用。
<input v-model="msg" debounce="500">
  注意 debounce 参数不会延迟 input 事件:它延迟“写入”底层数据。

自定义指令

基础
Vue.js允许自定义指令,实质上是让你教 Vue一些新技巧:怎样将数据的变化映射到 DOM 的行为。可以使用 Vue.directive(id, definition) 的方法传入指令 id 和定义对象来注册一个全局自定义指令。定义对象需要提供一些钩子函数(全部可选):
bind: 仅调用一次,当指令第一次绑定元素的时候。
update: 第一次是紧跟在 bind 之后调用,获得的参数是绑定的初始值;以后每当绑定的值发生变化就会被调用,获得新值与旧值两个参数。
unbind:仅调用一次,当指令解绑元素的时候。

Vue.directive('my-directive', {
  bind: function () {
    // 准备工作
    // 例如,添加事件处理器或只需要运行一次的高耗任务
  },
  update: function (newValue, oldValue) {
    // 值更新时的工作
    // 也会以初始值为参数调用一次
  },
  unbind: function () {
    // 清理工作
    // 例如,删除 bind() 添加的事件监听器
  }
})

在注册之后,便可以在 Vue.js 模板中这样用(记着添加前缀 v-):

<div v-my-directive="someValue"></div>

当只需要 update 函数时,可以传入一个函数替代定义对象:

Vue.directive('my-directive', function (value) {
  // 这个函数用作 update()
})

js代码如下:

<p v-font-color="'#ff6700'">hello Vue!</p>
<p v-font-color>hello Vue!</p>
// 参数1: 指令的名称
// 参数2: 指令函数
Vue.directive('font-color', function(color){
    // this.el是指令所在的标签
    console.log(color);
    this.el.style.color = color ? color : '#333';
});
Vue.directive('my-directive', {
  bind: function () {
    console.log('my-directive')
  },
  update: function (value) {
    this.el.innerHTML ='value - '+ value
  }
})
var demo = new Vue({
  el: '#demo',
  data: {
    my-directive: 'hello!'
  }
})

指令实例属性
所有的钩子函数将被复制到实际的指令对象中,钩子内 this 指向这个指令对象。这个对象暴露了一些有用的属性:
  el: 指令绑定的元素。
  vm: 拥有该指令的上下文 ViewModel。
  expression: 指令的表达式,不包括参数和过滤器。
  arg: 指令的参数。
  name: 指令的名字,不包含前缀。
  modifiers: 一个对象,包含指令的修饰符。
  descriptor: 一个对象,包含指令的解析结果。
<div id="demo" v-demo:hello.a.b="msg"></div>
js代码:

Vue.directive('demo', {
  bind: function () {
    console.log('demo bound!')
  },
  update: function (value) {
    this.el.innerHTML =
      'name - '       + this.name + '<br>' +
      'expression - ' + this.expression + '<br>' +
      'argument - '   + this.arg + '<br>' +
      'modifiers - '  + JSON.stringify(this.modifiers) + '<br>' +
      'value - '      + value
  }
})
var demo = new Vue({
  el: '#demo',
  data: {
    msg: 'hello!'
  }
})

对象字面量
如果指令需要多个值,可以传入一个 JavaScript 对象字面量。记住,指令可以使用任意合法的 JavaScript 表达式:
<div v-demo="{ color: 'white', text: 'hello!' }"></div>
js代码如下:

Vue.directive('demo', function (value) {
  document.write(value.color+" "+value.text);
})

字面修饰符
当指令使用了字面修饰符literal,它的值将按普通字符串处理并传递给 update 方法。update 方法将只调用一次,因为普通字符串不能响应数据变化。
<div id="demo" v-demo.literal="foo bar baz">
js代码如下:

Vue.directive('demo', function (value) {
  document.write(value) // "foo bar baz"
})

元素指令
有时候,我们可能想要我们的指令可以以自定义元素的形式被使用,而不是作为一个特性。这与Angular 的 E 类指令的概念非常相似。元素指令可以看做是一个轻量的自定义组件(后面会讲到)。你可以像下面这样注册一个自定义的元素指令:

<bg-color>hello Vue!</bg-color>
<script>
Vue.elementDirective('my-directive', {
  // API 同普通指令
  bind: function () {
    // 操作 this.el...
  }
})
Vue.elementDirective('bg-color', {
    bind(color) {   // es6语法,es5用 bind: function(){}
        this.el.style.backgroundColor = color ? color : '#ccc';
    }
});
</script>

页面应用为:

<my-directive></my-directive>

自定义过滤器

基础
可以用全局方法 Vue.filter() 注册一个自定义过滤器,它接收两个参数:过滤器ID和过滤器函数。过滤器函数以值为参数,返回转换后的值:

Vue.filter('split0', function (value) {
  return value.split('.')[0];
})

html代码:

<div id="demo">{{msg|split0}}</div>

js代码:

Vue.filter('split0', function (value) {
  return value.split('.')[0];
})
var vm=new Vue({
  el: '#example',
  data:{
  msg:'2.0'}
})

过滤器函数可以接收任意数量的参数:

Vue.filter('wrap', function (value, begin, end) {
  return begin + value + end;
})
<!-- 'hello' => 'before hello after' -->
<span>{{msg | wrap 'before' 'after'}}</span>

双向过滤器
我们使用过滤器都是在把来自模型的值显视在视图之前转换它。不过也可以定义一个过滤器,在把来自视图(< input > 元素)的值写回模型之前转化它,如下代码:

Vue.filter('currencyDisplay', {
  // model -> view
  // 在更新 `<input>` 元素之前格式化值
  read: function(val) {
    return '¥'+val.toFixed(2)
  },
  // view -> model
  // 在写回数据之前格式化值
  write: function(val, oldVal) {
    var number = +val.replace(/[^\d.]/g, '')
    return isNaN(number) ? 0 : parseFloat(number.toFixed(2))
  }
})

html代码如下:

<div id="example">
  <input type="text" v-model="msg|currencyDisplay"><br>
  <span>{{msg}}</span>
</div>

动态参数
如果一个过滤器参数没有被引号包裹,它会在当前 vm 的数据作用域里当做表达式进行动态求值。此外,过滤器函数的 this 上下文永远是调用它的当前 vm。

<input v-model="userInput">
<span>{{msg | concat userInput}}</span>

js代码:

Vue.filter('concat', function (value, input) {
  // 这里 `input` === `this.userInput`
  return value + input
})
Vue.filter('len', function (value) {
  if(!value){
  	return 0;
  }else{
  	return value.length 
  }
})

方法与事件处理器

方法处理器
可以用 v-on 指令监听 DOM 事件:

<div id="example">
  <button v-on:click="greet">Greet</button>
</div>

我们绑定了一个单击事件处理器到一个方法 greet。下面在 Vue 实例中定义这个方法:

var vm = new Vue({
  el: '#example',
  data: {
    name: 'Vue.js'
  },
  // 在 'methods' 对象中定义方法
  methods: {
    greet: function (event) {
      // 方法内 'this'指向 vm
      alert('Hello ' + this.name + '!')
      // 'event' 是原生 DOM 事件
      alert(event.target.tagName)
    }
  }
})

内联语句处理器
除了直接绑定到一个方法,也可以用内联 JavaScript 语句:

<div id="example-2">
  <button v-on:click="say('hi')">Say Hi</button>
  <button v-on:click="say('what')">Say What</button>
</div>

js代码:

new Vue({
  el: '#example',
  methods: {
    say: function (msg) {
      alert(msg)
    }
  }
})

有时也需要在内联语句处理器中访问原生 DOM 事件。可以用特殊变量 $event 把它传入方法:

<button v-on:click="say('hello!', $event)">Submit</button>

js代码:

new Vue({
  el: '#example',
  methods: {
    say: function (msg, event) {
    // 现在我们可以访问原生事件对象
    event.preventDefault()
  }
  }
})

事件修饰符
在事件处理器中经常需要调用 event.preventDefault() 或 event.stopPropagation()。尽管我们在方法内可以轻松做到,不过让方法是纯粹的数据逻辑而不处理 DOM 事件细节会更好。为了解决这个问题,Vue.js 为 v-on 提供两个事件修饰符:.prevent 与 .stop。

<!-- 阻止单击事件冒泡 -->
<a v-on:click.stop="doThis"></a>
<!-- 提交事件不再重载页面 -->
<form v-on:submit.prevent="onSubmit"></form>
<!-- 修饰符可以串联 -->
<a v-on:click.stop.prevent="doThat"></a>
<!-- 只有修饰符 -->
<form v-on:submit.prevent></form>

按键修饰符
在监听键盘事件时,我们经常需要检测 keyCode。Vue.js允许为v-on添加按键修饰符:

<!-- 只有在 keyCode 是 13 时调用 vm.submit() -->
<input v-on:keyup.13="submit">

记住所有的 keyCode 比较困难,Vue.js 为最常用的按键提供别名:

<!-- 同上 -->
<input v-on:keyup.enter="submit">

常用按键别名:enter、tab、delete、esc、space、up、down、left、right。

过度效果

简介
通过 Vue.js 的过渡系统,你可以轻松的为 DOM 节点被插入/移除的过程添加过渡动画效果。Vue 将会在适当的时机添加/移除 CSS 类名来触发 CSS3 过渡/动画效果,你也可以提供相应的 JavaScript 钩子函数在过渡过程中执行自定义的 DOM 操作。
  以 v-transition="my-transition 这个指令为例,当带有这个指令的 DOM 节点被插入或移除时,Vue 将会:
  1.用 my-transition这个 ID 去查找是否有注册过的 JavaScript 钩子对象。这个对象可以是由 Vue.transition(id, hooks) 全局注册,或是通过 transitions 选项定义在当前的组件内部。如果找到此对象,则会在过渡动画不同的阶段调用相应的钩子。
  2.自动探测目标元素是否应用了 CSS 过渡效果或者动画效果,并在适当的时机添加/移除 CSS 类名。
  3.如果没有提供 JavaScript 钩子函数,也没有检测到相应的 CSS 过渡/动画效果,DOM 的插入/移除会在下一帧立即执行。

<div v-if="show" transition="my-transition"></div>

所有的 Vue.js 过渡效果只有在该 DOM 操作是通过 Vue.js 触发时才会生效。触发的方式可以是通过内置指令,比如 v-if,或是通过 Vue 实例的方法,比如 vm.$appendTo()。
CSS 过渡
一个典型的 CSS 过渡效果定义如下:

<div v-if="show" v-transition="expand">hello</div>

然后为.expand-transition,.expand-enter 和.expand-leave 添加 CSS 规则:

/* 必需 */
.expand-transition {
  transition: all .3s ease;
  height: 30px;
  padding: 10px;
  background-color: #eee;
  overflow: hidden;
}
/* .expand-enter 定义进入的开始状态 */
/* .expand-leave 定义离开的结束状态 */
.expand-enter, .expand-leave {
  height: 0;
  padding: 0 10px;
  opacity: 0;
}

另外,可以提供 JavaScript 钩子:

Vue.transition('expand', {
  beforeEnter: function (el) {
    el.textContent = 'beforeEnter'
  },
  enter: function (el) {
    el.textContent = 'enter'
  },
  afterEnter: function (el) {
    el.textContent = 'afterEnter'
  },
  enterCancelled: function (el) {
    // handle cancellation
  },
  beforeLeave: function (el) {
    el.textContent = 'beforeLeave'
  },
  leave: function (el) {
    el.textContent = 'leave'
  },
  afterLeave: function (el) {
    el.textContent = 'afterLeave'
  },
  leaveCancelled: function (el) {
    // handle cancellation
  }
})

说简单点就是我们在操作某个元素时,当v-if的值为发生变化时,就会引起transition的变化,从而使的CSS样式改变。如果还是不明白,请看第四节《过渡流程详解》。
过渡的CSS类名
类名的添加和切换取决于 transition特性的值。比如 transition=“fade”,会有三个 CSS 类名:
  1).fade-transition 始终保留在元素上。
  2).fade-enter 定义进入过渡的开始状态。只应用一帧然后立即删除。
  3).fade-leave 定义离开过渡的结束状态。在离开过渡开始时生效,在它结束后删除。
  如果 transition 特性没有值,类名默认是 .v-transition, .v-enter 和 .v-leave。
过渡流程详解
根据我们第一节中的代码来讲解过渡流程:
  当 show 属性改变时,Vue.js 将相应地插入或删除div元素,按照如下规则改变过渡的 CSS 类名:
  如果 show 变为 false,Vue.js 将:
1.用 beforeLeave 钩子;
2.添加 v-leave 类名到元素上以触发过渡;
3.调用 leave 钩子;
4.等待过渡结束(监听 transitionend 事件);
5.从 DOM 中删除元素并删除 v-leave 类名;
6.调用 afterLeave 钩子。
  如果 show 变为 true,Vue.js 将:
1.调用 beforeEnter 钩子;
2.添加 v-enter 类名到元素上;
3.把它插入 DOM;
4.调用 enter 钩子;
5.强制一次CSS 布局,让 v-enter 确实生效。然后删除 v-enter 类名,以触发过渡,回到元素的原始状态;
6.等待过渡结束;
7.调用afterEnter钩子。
渐近过渡
transition 与 v-for 一起用时可以创建渐近过渡。给过渡元素添加一个特性 stagger, enter-stagger 或 leave-stagger, 如下代码:

<div v-for="list" transition stagger="100"></div>

或者,提供一个钩子 stagger, enter-stagger 或 leave-stagger,以更好的控制. 如下代码:

Vue.transition('stagger', {
  stagger: function (index) {
    // 每个过渡项目增加 50ms 延时
    // 但是最大延时限制为 300ms
    return Math.min(300, index * 50)
  }
})

如下实例html代码:

<div id="demo">
    <input v-model="query">
    <ul>
        <li v-for="item in list | filterBy query"
            transition="staggered"
            stagger="100">
          {{item.msg}}
         </li>
    </ul>
</div>

js代码:

 new Vue({
    el: '#demo',
    data: {
        query: '',
        list: [
            { msg: 'Bruce Lee' },
            { msg: 'Jackie Chan' },
            { msg: 'Chuck Norris' },
            { msg: 'Jet Li' },
            { msg: 'Kung Fury' }
        ]
    }
})

CSS代码:

ul {
    padding-left: 0;
    font-family: Helvetica, Arial, sans-serif;
}
.staggered-transition {
    transition: all .5s ease;
    overflow: hidden;
    margin: 0;
    height: 20px;
}
.staggered-enter, .staggered-leave {
    opacity: 0;
    height: 0;
}

以上代码的效果为:当我们在文本框中输入值时,会看到列表逐渐消失,删除内容时,会看到列表显示。

组件

使用组件
在Vue中,可以用 Vue.extend() 创建一个组件构造器:

var MyComponent = Vue.extend({
  template:'..........' //选项
})

要把这个构造器用作组件,需要用 Vue.component(tag, constructor) 注册 :

// 全局注册组件,tag 为 my-component
Vue.component('my-component', MyComponent)

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

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

js代码如下:

// 定义
var MyComponent = Vue.extend({
  template: '<div>A custom component!</div>'
})
// 注册
Vue.component('my-component', MyComponent)
// 创建根实例
new Vue({
  el: '#example'
})

渲染为:

<div id="example">
  <div>A custom component!</div>
</div>

Props 传递数据
组件实例的作用域是孤立的。这意味着不能并且不应该在子组件的模板内直接引用父组件的数据。可以使用 props 把数据传给子组件。
“prop” 是组件数据的一个字段,期望从父组件传下来。子组件需要显式地用 props 选项声明 props:
···
Vue.component(‘child’, {
// 声明 props
props: [‘msg’],
// prop 可以用在模板内
// 可以用 this.msg 设置
template: ‘{{ msg }}’
})
···
然后向它传入一个普通字符串:

<child msg="hello!"></child>

动态Props
 HTML 特性不区分大小写。名字形式为 camelCase 的 prop 用作特性时,需要转为 kebab-case(短横线隔开):

Vue.component('child', {
  // camelCase in JavaScript
  props: ['myMessage'],
  template: '<span>{{ myMessage }}</span>'
})
<!-- kebab-case in HTML -->
<child my-message="hello!"></child>

类似于绑定一个普通的特性到一个表达式,也可以用 v-bind 绑定动态 Props 到父组件的数据。每当父组件的数据变化时,也会传递给子组件:

<div>
  <input v-model="parentMsg">
  <br>
  <child v-bind:my-message="parentMsg"></child>
</div>

Prop 绑定类型
prop 默认是单向绑定:当父组件的属性变化时,将传导给子组件,但是反过来不会。这是为了防止子组件无意修改了父组件的状态——这会让应用的数据流难以理解。不过,也可以使用 .sync 或 .once 绑定修饰符显式地强制双向或单次绑定。

<!-- 默认为单向绑定 -->
<child v-bind:my-message="parentMsg"></child>
<!-- 双向绑定 -->
<child v-bind:my-message.sync="parentMsg"></child>
<!-- 单次绑定 -->
<child v-bind:my-message.once="parentMsg"></child>

双向绑定会把子组件的 my-message 属性同步回父组件的 parentMsg 属性。单次绑定在建立之后不会同步之后的变化。
自定义事件
Vue 实例实现了一个自定义事件接口,用于在组件树中通信。这个事件系统独立于原生 DOM 事件,做法也不同。
  每个 Vue 实例都是一个事件触发器:

  • 使用 $on() 监听事件;

  • 使用 $emit() 在它上面触发事件;

  • 使用 $dispatch() 派发事件,事件沿着父链冒泡;

  • 使用 $broadcast() 广播事件,事件向下传导给所有的后代。

    子组件可以用 this. p a r e n t 访 问 它 的 父 组 件 , 而 父 组 件 有 一 个 数 组 t h i s . parent 访问它的父组件,而父组件有一个数组 this. parent访,this.children,包含它所有的子元素。

<!-- 子组件模板 -->
<template id="child-template">
  <input v-model="msg">
  <button v-on:click="notify">Dispatch Event</button>
</template>
<!-- 父组件模板 -->
<div id="events-example">
  <p>Messages: {{ messages | json }}</p>
  <child></child>
</div>
// 注册子组件
// 将当前消息派发出去
Vue.component('child', {
  template: '#child-template',
  data: function () {
    return { msg: 'hello' }
  },
  methods: {
    notify: function () {
      if (this.msg.trim()) {
        this.$dispatch('child-msg', this.msg)
        this.msg = ''
      }
    }
  }
})
// 启动父组件
// 将收到消息时将事件推入一个数组
var parent = new Vue({
  el: '#events-example',
  data: {
    messages: []
  },
  // 在创建实例时 `events` 选项简单地调用 `$on`
  events: {
    'child-msg': function (msg) {
      // 事件回调内的 `this` 自动绑定到注册它的实例上
      this.messages.push(msg)
    }
  }
})

关于组件的介绍我们就先讲到这里,更多介绍在请参考这里


  • $index可以获取当前数组的索引值,也可以使用v-for="(index, ls) in languageSkills"的方式。

  • 默认情况下,数组中有相同值的元素会报错(对象数组是同一个对象),添加一个track-by="$index"指令可以解决

<p>我会的语言有:</p>
<ul>
    <li v-for="ls in languageSkills" tack-by="$index">{{ls}}---{{$index}}</li>
</ul>
<script>
    new Vue({
        data: {
            languageSkills: ['css', 'css']
        }
    }).$mount('#app');
</script>
  • v-pre
    不会编译这个元素的内容。例如使用插值语法时内容不会替换。
<p v-pre>{{msg}}</p>
<script>
    new Vue({
        data: {
            msg: 'hello Vue!'
        }
    }).$mount('#app');
</script>
  • v-cloak
    使用插值与法的时候,在文档加载第一次时插值语法不会替换成数据,会原原本本的显示在那,使用这个指令就可以避免这种情况,也可以使用v-text或v-html代替。
<style>
    [v-cloak]{ display: none; }
</style>
<p v-cloak>{{msg}}</p>
<script>
    new Vue({
        data: {
            msg: 'hello Vue!'
        }
    }).$mount('#app');
</script>
  • 内置指令
Vue指令Angular指令简述
v-textng-bind代替插值语法
v-htmlng-bind可以解析html代码
v-showng-show显示或隐藏元素
v-ifng-if删除或插入元素
v-else和if else一个道理
v-forng-repeat遍历元素
v-modelng-model双向绑定
v-pre不去编译指定元素
v-cloakng-cloak防止插值语法的闪烁
v-bindng-src等等绑定节点属性
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值