Vuejs讲解之:响应式、过渡效果、过渡状态

时间: 2017-11-09阅读: 1479标签: vue作者: gongyunit

1Vuejs高级之:响应式


1.1 如何追踪变化

Vue实例使用Object.defineProperty将普通js对象属性转为getter和setter

用户可以使用vue-devtools调试

每个Vue实例有相应的watch程序实例,可以检测并更新相关的组件

图形表示如下:


1.2 变化检测问题

受JS的限制,属性需要放在data对象上才能让它是相应的

动态设置响应属性,需要使用Vue.set(object,key,value)

Vm.$set是Vue.set的别名

如果想向已有对象添加一些属性,可以新建一个包含原有对象属性和新添加属性的对象


1.3 异步更新队列

Vue执行DOM更新是异步的

Vue.nextTick(callback)


1.4 响应式原理的示例
<!DOCTYPE html>
<html>
  <head>
  <meta charset="UTF-8">
  <title></title>
  </head>
  <body>
  <div id="demo">
  <h5>a是data内部的,是响应的:{{a}}</h5>
  <h5>b是vm.b设置的,是非响应的:{{b}}</h5>
  <h5>c是通过Vue.set响应的:{{extendData.c}}</h5>
  <h5> Vue 不允许动态添加根级响应式属性,所以你必须在初始化实例前声明根级响应式属性,哪怕只是一个空值: {{message}}</h5>
  </div>
  <script src="vue.js" type="text/javascript" charset="utf-8"></script>
  <script type="text/javascript">
  var vm = new Vue({
  el:'#demo',
  data:{
  a:'a',
  extendData:{},
  // 声明 message 为一个空值字符串
      message: 'hello'
  }
  });
  vm.b = 'b';
  Vue.set(vm.extendData,'c','c');
  // 之后设置 `message`
  vm.message = 'new hello'
  vm.$el.textContent === 'new hello' // false
  Vue.nextTick(function () {
    vm.$el.textContent === 'new hello' // true
  })
  </script>
  </body>
</html>


2Vuejs高级之:过渡效果


2.1 主要过渡效果依赖的工具

在 CSS 过渡和动画中自动应用 class

可以配合使用第三方 CSS 动画库,如 Animate.css

在过渡钩子函数中使用 JavaScript 直接操作 DOM

可以配合使用第三方 JavaScript 动画库,如 Velocity.js


2.2 单元素/组件的过渡

Vue 提供了 transition 的封装组件,在下列情形中,可以给任何元素和组件添加 entering/leaving 过渡

条件渲染 (使用 v-if)

条件展示 (使用 v-show)

动态组件

组件根节点


2.3 单元素/组件的过渡的示例
<!DOCTYPE html>
<html>
  <head>
  <meta charset="UTF-8">
  <title></title>
  <style type="text/css">
  .fade-enter-active, .fade-leave-active {transition: opacity .5s}
  .fade-enter, .fade-leave-active {opacity: 0}
  </style>
  </head>
  <body>
  <div id="demo">
  <button v-on:click="show = !show">
  Toggle
  </button>
  <transition name="fade">
  <p v-if="show">hello</p>
  </transition>
  </div>
  <script src="vue.js" type="text/javascript" charset="utf-8"></script>
  <script type="text/javascript">
  var vm = new Vue({
  el:'#demo',
  data:{
  show: true
  }
  });
  </script>
  </body>
</html>


2.4 过渡组件的注意事项

元素封装成过渡组件之后,在遇到插入或删除时,Vue 将

自动嗅探目标元素是否有 CSS 过渡或动画,并在合适时添加/删除 CSS 类名。

如果过渡组件设置了过渡的 JavaScript 钩子函数,会在相应的阶段调用钩子函数。

如果没有找到 JavaScript 钩子并且也没有检测到 CSS 过渡/动画,DOM 操作(插入/删除)在下一帧中立即执行。(注意:此指浏览器逐帧动画机制,与 Vue,和Vue的 nextTick 概念不同)


2.5 css动画过渡

常用的过渡都是使用 CSS 过渡。比如上一个例子。

CSS 动画用法同 CSS 过渡,区别是在动画中 v-enter 类名在节点插入 DOM 后不会立即删除,而是在 animationend 事件触发时删除。


2.6 css动画过渡的示例
<!DOCTYPE html>
<html>
  <head>
  <meta charset="UTF-8">
  <title></title>
  <style type="text/css">
  .bounce-enter-active {animation: bounce-in .5s;}
  .bounce-leave-active {animation: bounce-out .5s;}
  @keyframes bounce-in {
  0% {transform: scale(0);}
  50% {transform: scale(1.5);}
  100% {transform: scale(1);}
  }
  @keyframes bounce-out {
  0% {transform: scale(1);}
  50% {transform: scale(1.5);}
  100% {transform: scale(0);}
  }
  </style>
  </head>
  <body>
  <div id="example-2">
  <button @click="show = !show">Toggle show</button>
  <transition name="bounce">
  <p v-if="show">Look at me!</p>
  </transition>
  </div>
  <script src="vue.js" type="text/javascript" charset="utf-8"></script>
  <script type="text/javascript">
  new Vue({
  el: '#example-2',
  data: {
  show: true
  }
  })
  </script>
  </body>
</html>


2.7 自定义类名过渡

我们可以通过特性来自定义过渡类名:

enter-class

enter-active-class

leave-class

leave-active-class

他们的优先级高于普通的类名,这对于 Vue 的过渡系统和其他第三方 CSS 动画库,如 Animate.css 结合使用十分有用。


2.8 自定义过渡的示例
<!DOCTYPE html>
<html>
  <head>
  <meta charset="UTF-8">
  <title></title>
  <link rel="stylesheet" type="text/css" href="animate.min.css" />
  </head>
  <body>
  <div id="example-3">
  <button @click="show = !show">
  Toggle render
  </button>
  <transition name="custom-classes-transition"
   enter-active-class="animated tada"
   leave-active-class="animated bounceOutRight">
  <p v-if="show">hello</p>
  </transition>
  </div>
  <script src="vue.js" type="text/javascript" charset="utf-8"></script>
  <script type="text/javascript">
  new Vue({
  el: '#example-3',
  data: {
  show: true
  }
  })
  </script>
  </body>
</html>


2.9 初始渲染的过渡

可以通过appear特性设置节点在初始渲染的过渡

<transition appear>
<!-- ... -->
</transition>

可以自定义CSS类名,代码如图:

自定义JavaScript钩子,代码如图:


2.10 多个组件的过渡

多个组件的过渡很简单很多 - 我们不需要使用 key 特性。相反,我们只需要使用动态组件

new Vue({
el: '#transition-components-demo',
data: {
view: 'v-a'
},
components: {
'v-a': {
template: '<div>Component A</div>'
},
'v-b': {
template: '<div>Component B</div>’}
}})


2.11 多个组件的过渡的示例
<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <title></title>
  <style type="text/css">
  .component-fade-enter-active,.component-fade-leave-active {transition: opacity .3s ease;}
  .component-fade-enter,.component-fade-leave-active {opacity: 0;}
  </style>
  </head>
  <body>
  <div id="example-3">
  <input type="radio" v-model="view" value="v-a"/>A
  <input type="radio" v-model="view" value="v-b"/>B
  <transition name="component-fade" mode="out-in">
  <component v-bind:is="view"></component>
  </transition>
  </div>
  <script src="vue.js" type="text/javascript" charset="utf-8"></script>
  <script type="text/javascript">
  new Vue({
  el: '#example-3',
  data: {
  view: 'v-a'
  },
  components: {
  'v-a': {
  template: '<div>Component A</div>'
  },
  'v-b': {
  template: '<div>Component B</div>'
  }
  }
  })
  </script>
  </body>
</html>


2.12 列表过渡

列表的进入和离开过渡

列表的位移过渡

列表的渐进过渡


2.13 列表进入和离开过渡的示例
<!DOCTYPE html>
<html>
  <head>
  <meta charset="UTF-8">
  <title></title>
  </head>
  <style type="text/css">
  .list-item {display: inline-block;margin-right: 10px;}
  ist-enter-active,.list-leave-active {transition: all 1s;}
  .list-enter,.list-leave-active {opacity: 0;transform: translateY(30px);}
  </style>
  <body>
  <div id="list-demo" class="demo">
  <button v-on:click="add">Add</button>
  <button v-on:click="remove">Remove</button>
  <transition-group name="list" tag="p">
  <span v-for="item in items" v-bind:key="item" class="list-item">{{ item }}</span>
  </transition-group>
  </div>
<script src="vue.js" type="text/javascript" charset="utf-8"></script>
  <script type="text/javascript">
new Vue({
  el: '#list-demo',
  data: {
  items: [1, 2, 3, 4, 5, 6, 7, 8, 9],
  nextNum: 10
  },
  methods: {
  randomIndex: function() {
  return Math.floor(Math.random() * this.items.length)
  },
  add: function() {
  this.items.splice(this.randomIndex(), 0, this.nextNum++)
  },
  remove: function() {
  this.items.splice(this.randomIndex(), 1)
  },
  }
  })
  </script>
  </body>
</html>


2.14 列表位移过渡的示例
<!DOCTYPE html>
<html>
  <head>
  <meta charset="UTF-8">
  <title></title>
  </head>
  <style type="text/css">
  .flip-list-move {transition: transform 1s;}
  </style>
  <body>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.14.1/lodash.min.js"></script>
  <div id="flip-list-demo" class="demo">
  <button v-on:click="shuffle">Shuffle</button>
  <transition-group name="flip-list" tag="ul">
  <li v-for="item in items" v-bind:key="item">
  {{ item }}
  </li>
  </transition-group>
  </div>
  <script src="vue.js" type="text/javascript" charset="utf-8"></script>
  <script type="text/javascript">
  new Vue({
  el: '#flip-list-demo',
  data: {
  items: [1, 2, 3, 4, 5, 6, 7, 8, 9]
  },
  methods: {
  shuffle: function() {
  this.items = _.shuffle(this.items)
  }
  }
  })
  </script>
  </body>
</html>


2.15 列表渐进过渡的示例
<!DOCTYPE html>
<html>
  <head>
  <meta charset="UTF-8">
  <title></title>
  </head>
  <style type="text/css">
  .list-item {display: inline-block;margin-right: 10px;}
  .list-enter-active,.list-leave-active {transition: all 1s;}
  .list-enter,.list-leave-active {opacity: 0;transform: translateY(30px);}
  </style>
  <body>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/velocity/1.2.3/velocity.min.js"></script>
  <div id="staggered-list-demo">
  <input v-model="query">
  <transition-group name="staggered-fade" tag="ul" v-bind:css="false" v-on:before-enter="beforeEnter" v-on:enter="enter" v-on:leave="leave">
  <li v-for="(item, index) in computedList" v-bind:key="item.msg" v-bind:data-index="index">{{ item.msg }}</li>
  </transition-group>
  </div>
  <script src="vue.js" type="text/javascript" charset="utf-8"></script>
  <script type="text/javascript">
  new Vue({
  el: '#staggered-list-demo',
  data: {
  query: '',
  list: [{ msg: 'Bruce Lee' },{ msg: 'Jackie Chan' },{ msg: 'Chuck Norris' },{ msg: 'Jet Li' },{ msg: 'Kung Fury' }]
  }
  computed: {
  computedList: function() {
  var vm = this
  return this.list.filter(function(item) {
  return item.msg.toLowerCase().indexOf(vm.query.toLowerCase()) !== -1
  })
  }
  },
  methods: {
  beforeEnter: function(el) {
  el.style.opacity = 0
  el.style.height = 0
  },
  enter: function(el, done) {
  var delay = el.dataset.index * 150
  setTimeout(function() {
  Velocity(
  el, { opacity: 1, height: '1.6em' }, { complete: done }
  )
  }, delay)
  },
  leave: function(el, done) {
  var delay = el.dataset.index * 150
  setTimeout(function() {
  Velocity(
  el, { opacity: 0, height: 0 }, { complete: done }
  )
  }, delay)
  }
  }
  })
  </script>
  </body>
</html>


3Vuejs高级之:过渡状态


3.1 过渡状态

Vue 的过渡系统提供了非常多简单的方法设置进入、离开和列表的动效。那么对于数据元素本身的动效呢,比如:

§数字和运算

§颜色的显示

§SVG 节点的位置

§元素的大小和其他的属性

所有的原始数字都被事先存储起来,可以直接转换到数字。做到这一步,我们就可以结合 Vue 的响应式和组件系统,使用第三方库来实现切换元素的过渡状态。

动态动画与watcher

通过 watcher 我们能监听到任何数值属性的数值更新。例子如下:

<script src="https://unpkg.com/tween.js@16.3.4"></script>
<div id="animated-number-demo">
<input v-model.number="number" type="number" step="20">
<p>{{ animatedNumber }}</p>
</div>
new Vue({
el: '#animated-number-demo',
data: {
number: 0,
animatedNumber: 0
},
watch: {
number: function(newValue, oldValue) {
var vm = this
function animate (time) {
requestAnimationFrame(animate)
TWEEN.update(time)
}
new TWEEN.Tween({ tweeningNumber: oldValue })
.easing(TWEEN.Easing.Quadratic.Out)
.to({ tweeningNumber: newValue }, 500)
.onUpdate(function () {
vm.animatedNumber = this.tweeningNumber.toFixed(0)
})
.start()
animate()
}
}
})


动态状态转换

  就像 Vue 的过渡组件一样,数据背后状态转换会实时更新,这对于原型设计十分有用。当你修改一些变量,即使是一个简单的 SVG 多边形也可是实现很多难以想象的效果。

通过组件组织过渡

  管理太多的状态转换的很快会接近到 Vue 实例或者组件的复杂性,幸好很多的动画可以提取到专用的子组件。


3.2 过渡状态的示例
<!DOCTYPE html>
<html>
  <head>
  <meta charset="UTF-8">
  <script src="tween.js"></script>
  <title></title>
  </head>
  <body>
  <div id="example-8">
  <input v-model.number="firstNumber" type="number" step="20"> +
  <input v-model.number="secondNumber" type="number" step="20"> = {{ result }}
  <p>
  <animated-integer v-bind:value="firstNumber"></animated-integer> +
  <animated-integer v-bind:value="secondNumber"></animated-integer> =
  <animated-integer v-bind:value="result"></animated-integer>
  </p>
  </div>
  <script src="vue.js" type="text/javascript" charset="utf-8"></script>
  <script type="text/javascript">
  Vue.component('animated-integer', {
  template: '<span>{{ tweeningValue }}</span>',
  props: {
  value: {
  type: Number,
  required: true
  }
  },
  data: function() {
  return {
  tweeningValue: 0
  }
  },
  watch: {
  value: function(newValue, oldValue) {
  this.tween(oldValue, newValue)
  }
  },
mounted: function() {
  this.tween(0, this.value)
  },
  methods: {
  tween: function(startValue, endValue) {
  var vm = this
  function animate(time) {
  requestAnimationFrame(animate)
  TWEEN.update(time)
  }
  new TWEEN.Tween({ tweeningValue: startValue })
  .to({ tweeningValue: endValue }, 500)
  .onUpdate(function() {
  vm.tweeningValue = this.tweeningValue.toFixed(0)
  })
  .start()
  animate()
  }
  }
  })
  // All complexity has now been removed from the main Vue instance!
  new Vue({
  el: '#example-8',
  data: {
  firstNumber: 20,
  secondNumber: 40
  },
  computed: {
  result: function() {
  return this.firstNumber + this.secondNumber
  }
  }
  })
  </script>
  </body>
</html>

转载于:工云IT技术

Vue.js中的computed工作原理_深入理解 Vue的Computed计算属性

Computed 计算属性是 Vue 中常用的一个功能,但你理解它是怎么工作的吗?我们通过实现一个简单版的和Vue中computed具有相同功能的函数来了解computed是如何工作的。

Vue高版本中一些新特性的使用

Vue高版本中一些新特性的使用:深度作用选择器、组件配置项inheritAttrs、组件实例属性$attrs和$listeners、组件选项 provide/inject、作用域插槽 slot-scope、Vue的错误捕获

vue去掉#,history模式

现在网站大多有三方登录,支付等功能,存在#,项目开发就存在很大的障碍。vue把#当做自己的根目录,静态资源,去掉#后,要采用相对路径去引用,如果图片引用是在js内,则要采用require()方法进行引用。

vue2.0之监听属性的使用心得及搭配计算属性的使用

在工作中常常需要监听某一个属性值的变化,这个时候我们就需要用到了监听属性watch,在这里我总结watch属性的三种场景使用希望对你有所帮助

vue之nextTick全面解析

vue是非常流行的框架,他结合了angular和react的优点,从而形成了一个轻量级的易上手的具有双向数据绑定特性的mvvm框架。本人比较喜欢用之。在我们用vue时,我们经常用到一个方法是this.$nextTick

Vue组件中prop属性使用说明

props 把数据传给子组件!prop是组件数据的一个字段,期望从父作用域传下来。子组件需要显式地用 props 选项。props的大小写、静态的和动态的 Prop、传入一个数字、传入一个布尔值、Vue的组件中的props属性单向数据流

Vue常用经典开源项目汇总参考-海量

本文主要是收集与整理Vue相关的开源资料,以供需要的朋友参考。主要包含以下几方面的内容:UI组件、开发框架、实用库、服务端、辅助工具、应用实例、Demo示例

vue引用js文件的多种方式

vue引用js文件的多种方式,这里以为引入jquery为例。js引入文件方式包括: vue-cli webpack全局引入jquery、vue组件引用外部js的方法、单vue页面引用内部js方法

Vue中的scoped及穿透方法

由于scoped看起来很美好,但是含有很多的坑,所以,不推荐不使用scoped属性,而通过在外层dom上添加唯一的class来区分不同组件。这种方法既实现了类似于scoped的效果,又方便修改各种第三方组件的样式,代码看起来也相对舒适

在Vue项目里面使用d3.js

在Vue里面使用D3.js的方法,npm 上面的D3相对来说 可以说是很不人性化了 完全没有说 在webpack上怎么使用D3.js,将视图从逻辑中分离出来,并且使用Vue钩子,方法和data对象。