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

更新日期: 2017-11-09阅读: 5.4k标签: 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技术

链接: https://www.fly63.com/article/detial/73

VueJS 实际开发中会遇到的问题

VueJS 实际开发中会遇到的问题,主要写一些 官方手册 上没有写,但是实际开发中会遇到的问题,需要一定知识基础。

vue与后台交互ajax数据

Vue.js是一套构建用户界面的渐进式的前端框架。 vueJS与后台交互数据的方法我所了解的有以下几种

Vue响应式开发,深入理解Vue.js响应式原理

深入理解Vue.js响应式原理。Vue教程有关的视频都讲到,我习惯响应式开发,在更早的Angular1时代,我们叫它:数据绑定(Data Binding)。你只需要在Vue实例的 data() 块中定义一些数据,并绑定到HTML

vue中慎用style的scoped属性

在vue组件中,为了使样式私有化(模块化),不对全局造成污染,可以在style标签上添加scoped属性以表示它的只属于当下的模块,这是一个非常好的举措,但是为什么要慎用呢?因为scoped往往会造成我们在修改公共组件(三方库或者项目定制的组件)的样式困难,需要增加额外的工作量

基于vue移动端UI框架有哪些?vue移动端UI框架总汇

vue现在使用的人越来越多了,这篇文章主要整理一些比较优秀的移动端ui框架,推荐给大家,例如:mint UI、vux、vonic、vant、cube-ui、Muse-ui、Vue-Carbon、YDUI等

使用webpack提升vue应用的4种方式

webpack是开发Vue单页应用必不可少的工具,它能管理复杂的构建步骤,并且优化你的应用大小和性能, 使你的开发工作流更加简单。在这篇文章中,我将解释使用webpack提升你的Vue应用的4种方式,包括:单文件组件、优化Vue构建过程、浏览器缓存管理、代码分离

Vue2.0用户权限控制解决方案

Vue-Access-Control是一套基于Vue/Vue-Router/axios 实现的前端用户权限控制解决方案,通过对路由、视图、请求三个层面的控制,使开发者可以实现任意颗粒度的用户权限控制。

组件化的概念/特性/优点,Vue组件的使用

Web 中的组件其实就是页面组成的一部分,具有高内聚性,低耦合度,互冲突等特点,有利于提高开发效率,方便重复使用,简化调试步骤等。vue 中的组件是一个自定义标签形式,扩展原生的html元素,封装可重用的代码。

Vue2实例详解与生命周期

Vue的实例是Vue框架的入口,其实也就是前端的ViewModel,它包含了页面中的业务逻辑处理、数据模型等,当然它也有自己的一系列的生命周期的事件钩子,辅助我们进行对整个Vue实例生成、编译、挂着、销毁等过程进行js控制。

Vue组件的三种调用方式

主要讲Vue三种方式调用组件:v-model或者.sync显式控制组件显示隐藏,通过js代码调用,通过Vue指令调用,在写组件的时候很多写法、灵感来自于element-ui

点击更多...

内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权或违规,请与小编联系!情况属实本人将予以删除!