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

时间: 2017-11-09阅读: 2484标签: 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.extend拓展

Vue.extend返回的是一个“拓展实例构造器”,也就是预设了部分选项的Vue实例构造器。经常服务于Vue.component用来生成组件,可以简单理解为当在模板中遇到该组件名称作为标签的自定义元素时

Vue基于snabbdom做了哪些事

Snabbdom 核心代码大约只有 200 行。它提供了模块化架构,具有丰富的功能,可通过自定义模块进行扩展。在了解核心 patch 前,需要先了解 snabbdom 的模块化架构思想。

尤雨溪:Vue Function-based API RFC【转】

将 2.x 中与组件逻辑相关的选项以 API 函数的形式重新设计。组件 API 设计所面对的核心问题之一就是如何组织逻辑,以及如何在多个组件之间抽取和复用逻辑。

vue中修改Modal的重置功能怎么写?

工作中遇到弹出模态框形式的修改功能,模态框里面是Form表单,Form表单中的内容是从后台获取的,这时候用户修改完没有提交,而是想重置然后重新修改,怎么办呢?

详细分析Vue.nextTick()实现

刚开始接触Vue的时候,哇nextTick好强,咋就在这里面写就是dom更新之后,当时连什么macrotask、microtask都不知道(如果你也不是很清楚,推荐点这里去看一下,也有助于你更好地理解本文),再后来,写的多了看得多了愈发膨胀了,就想看看这个nextTick到底是咋实现的

vue混入

混入是一种分发Vue组件中可复用功能非常灵活的方式。混入对象可以包含任意组件选项。当组件使用混入对象时,所有混入对象的选项将被混入该组件本身的选项。当组件和混入对象含有同名选项时,这些选项将以恰当的方式混合。

Vue基础之计算属性

设想一个场景,你需要得到一个复杂运算/逻辑的返回值,利用模板内的表达又过长且难以阅读和维护,这时计算属性就可以很好的解决你的问题。看下面的例子:

vue 自定义指令

接下来我们来看一下钩子函数的参数 (即 el、binding、vnode 和 oldVnode)。但有一些是没有相对应的指令进行操作。在这里以progress(h5的新标签进度条)为例,向大家介绍Vue的一个用于指令扩展的方法:directive(自定义指令)。

对Vue.js的认知

MVVM是Model-View-ViewModel的缩写。MVVM是一种设计思想。Model 层代表数据模型,也可以在Model中定义数据修改和操作的业务逻辑;View 代表UI 组件,它负责将数据模型转化成UI 展现出来,ViewModel 是一个同步View 和 Model的对象。

谈谈vue的render函数?

使用vue 这么长时间,对vue 对源码了解还是不多,作为一个不甘平庸的前端小白,决定奋起,那么今天我们就来谈谈vue 的render 函数;打开源码,我发现render 函数返回一个VNode; 可是我们并未在模版中写render 呀,这又是一个什么样的过程呢?

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

广告赞助文章投稿关于web前端网站点搜索站长推荐网站地图站长QQ:522607023

小程序专栏: 土味情话心理测试脑筋急转弯幽默笑话段子句子语录成语大全