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>
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>
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技术
VueJS 实际开发中会遇到的问题,主要写一些 官方手册 上没有写,但是实际开发中会遇到的问题,需要一定知识基础。
Vue.js是一套构建用户界面的渐进式的前端框架。 vueJS与后台交互数据的方法我所了解的有以下几种
深入理解Vue.js响应式原理。Vue教程有关的视频都讲到,我习惯响应式开发,在更早的Angular1时代,我们叫它:数据绑定(Data Binding)。你只需要在Vue实例的 data() 块中定义一些数据,并绑定到HTML
在vue组件中,为了使样式私有化(模块化),不对全局造成污染,可以在style标签上添加scoped属性以表示它的只属于当下的模块,这是一个非常好的举措,但是为什么要慎用呢?因为scoped往往会造成我们在修改公共组件(三方库或者项目定制的组件)的样式困难,需要增加额外的工作量
vue现在使用的人越来越多了,这篇文章主要整理一些比较优秀的移动端ui框架,推荐给大家,例如:mint UI、vux、vonic、vant、cube-ui、Muse-ui、Vue-Carbon、YDUI等
webpack是开发Vue单页应用必不可少的工具,它能管理复杂的构建步骤,并且优化你的应用大小和性能, 使你的开发工作流更加简单。在这篇文章中,我将解释使用webpack提升你的Vue应用的4种方式,包括:单文件组件、优化Vue构建过程、浏览器缓存管理、代码分离
Vue-Access-Control是一套基于Vue/Vue-Router/axios 实现的前端用户权限控制解决方案,通过对路由、视图、请求三个层面的控制,使开发者可以实现任意颗粒度的用户权限控制。
Web 中的组件其实就是页面组成的一部分,具有高内聚性,低耦合度,互冲突等特点,有利于提高开发效率,方便重复使用,简化调试步骤等。vue 中的组件是一个自定义标签形式,扩展原生的html元素,封装可重用的代码。
Vue的实例是Vue框架的入口,其实也就是前端的ViewModel,它包含了页面中的业务逻辑处理、数据模型等,当然它也有自己的一系列的生命周期的事件钩子,辅助我们进行对整个Vue实例生成、编译、挂着、销毁等过程进行js控制。
主要讲Vue三种方式调用组件:v-model或者.sync显式控制组件显示隐藏,通过js代码调用,通过Vue指令调用,在写组件的时候很多写法、灵感来自于element-ui
内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权或违规,请与小编联系!情况属实本人将予以删除!