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

时间: 2017-11-09阅读: 1751标签: 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引入图片,必须require进来

需求:如何components里面的index.vue怎样能把assets里面的图片拿出来。 1.在img标签里面直接写上路径,2.利用数组保存再循环输出

vue-router响应路由参数的变化

当使用路由参数时,例如从 /user/foo 导航到 /user/bar,原来的组件实例会被复用。因为两个路由都渲染同个组件,比起销毁再创建,复用则显得更加高效。不过,这也意味着组件的生命周期钩子不会再被调用

Vue.js中 watch 的高级用法

上面的代码的效果是,当我们输入firstName后,wacth监听每次修改变化的新值,然后计算输出fullName。app.$watch调用后会返回一个值,就是unWatch方法,你要注销 watch 只要调用unWatch方法就可以了

vue2.0/3.0在main.js引入scss文件报错

在vue2.0的main.js中引入scss文件报错原因是:在build文件夹下的webpack.base.conf.js的rules里面添加配置,vue3.0写入.scss文件在mian.js中 import ‘./styles/index.scss‘后出现下图报错解决方法:在vue.config.js文件中添加以下代码

在vue项目中使用canvas-nest.js,报parameter 1 is not of type Element

canvas-nest.js是一款轻量的网页特效。在vue项目中,使用时配置,引入canvas-nest.js后,直接在created中 new CanvasNest(element, config)。遇到parameter 1 is not of type Element这样类型的报错,需要检查dom是否渲染完毕。

Vue项目打包常见问题整理

Vue 项目在开发时运行正常,打包发布后却出现各种报错,这里整理一下遇到的问题,以备忘。js 路径问题、img 路径问题、favicon.ico 问题、IE9+ 兼容性问题、禁止生成 .map 文件

Vue2中render:h => h(App)的理解

render函数是渲染一个视图,然后提供给el挂载,如果没有render那页面什么都不会出来,Vue 在调用 render 方法时,会传入一个 createElement 函数作为参数,也就是这里的 h 的实参是 createElement 函数

Vue 中的受控与非受控组件

熟悉 React 的开发者应该对“受控组件”的概念并不陌生,实际上对于任何组件化开发框架而言,都可以实现所谓的受控与非受控,Vue 当然也不例外。并且理解受控与非受控对应的需求场景,可以让我们在设计一些基础组件时思路更加清晰,暴露出来的组件 API 也更加合理、统一。

Vue.js的复用组件开发流程

接下来我们会详细分析下如何完成由多个组件组成一个复用组件的开发流程。本节我们主要要完成这样一个列表功能,每一行的列表是一个组件,列表内可能出现按钮组件或者箭头组件,点击按钮组件可以自定义事件

解析Vue.js中的computed工作原理

我们通过实现一个简单版的和Vue中computed具有相同功能的函数来了解computed是如何工作的。写的十分的全面细致,具有一定的参考价值,对此有需要的朋友可以参考学习下

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