vue特性与其他框架的区别
关于vue
- vue是一个简洁且轻量化为主要特点的前端MVVM开发框架,vue使用组件化开发的范式,组件之间可以做到高度解耦,数据的绑定、更新、动态界面等特性也一气呵成。
特性
- 轻量----很小并不依赖其他基础库
- 数据绑定----MVVM
- 指令----指令控制DOM
- 插件化----vue-resourse、vue-cli等
vue与其他框架的区别
对比angular
- 都支持指令,支持过滤器,支持双向绑定,都不支持低端浏览器
- angular学习成本高,性能上,依赖对数据做脏检查,watcher越多越慢。
对比react
- react采用特殊的jsx语法,vue推崇编写.vue特殊的文件格式,都需要编译后使用
- 中心思想都是 组件,组件实例之间可以嵌套
- 都支持生命周期函数
- recat依赖虚拟DOM,vue使用的是DOM模板
- react采用的虚拟DOM会对渲染出来的结果进行脏检查, vue采用的是数据劫持,通过Object.defineProperty()来劫持各个属性的setter,getter,在数据变动时发布消息给订阅者,触发相应的监听回调。
vue实例
先上代码:
<div id="app">//id
{{ message }}//接受js表达式的值(ps:js语句是一种行为,不会产生值;js表达式会产生一个值)
</div>
<script>
var app = new Vue({//new一个实例
el: '#app',//连接DOM
data: {
message: 'Hello Vue!'//初始数据
}
})
</script>
关于构造器
- 每个vue.js都是通过构造函数vue创建 一个vue的根实例启动的
- (在实例化vue时,需要传入一个选项对象,他可以包括数据、模板、挂载元素、方法、生命周期钩子等选项。)
var vm = new Vue({
// 选项(数据、模板、挂载元素、方法、生命周期等)
})
- 可以扩展vue构造器,从而预定选项创建可复用的组件构造器(后期详细解释)
var MyComponent=Vue.extend({
//扩展选项
})
//所有的MyComponent 实例都将以预定义的扩展选项被创建
var MyComponent=new MyComponent();
//所有的 Vue.js 组件其实都是被扩展的 Vue 实例。
构造器属性与方法
- 每个vue实例都会代理其data对象里的所有的属性
var data={a:1}
var vm=new Vue({
data:data
})
vm.a===data.a //true
//设置属性也会影响到原始数据
vm.a=2;
console.log(data.a); //2
- 除了 data 属性, Vue 实例暴露了一些有用的实例属性与方法。这些属性与方法都有前缀 $:
- vm.$data===data ---//true vm上的数据
- vm.$el===document.getElementById('example')---// 当前的el元素
- vm.set(data,'sex', '男');
- vm.$options ---//vm上的所有的属性
- vm.$nextTick(()=>{console.log(vm)})---//异步方法,等待dom完成后可以操作dom,(每次数据改变之后想 要获取操作DOM,都可以使用nextTick)。
- vm.$watch---是一个实例方法 监听函数
- vm.$refs ---//关联ref属性的DOM元素,可以操作这个关联的元素
<div id='example'>
<p ref='mydom'>{{msg}}</p>
<p ref='mydom'>{{msg}}</p>
<div ref='mydiv' v-for="a in arr">{{a}}</div >
</div>
........
var data={msg:1,arr:[1,2,3]}
var vm=new Vue({
el:'#example',
data:data,
mounted(){
//如果dom元素不是通过v-for循环出来的,只能获取一个,通过-for循环出来的可以获取多个
console.log(this.$refs.mydom)//获取一个p
console.log(this.$refs.mydiv)//获取多个div
}
})
vm.$data===data ---//true vm上的数据
vm.$el===document.getElementById('example')---// 当前的el元素
vm.$set ---后加的属性实现响应式变化(因为如果在实例创建之后添加新的属性到实例上,它不会触发视图更新。) eg: vm.$set(data,'sex', '男');
vm.$options ---//vm上的所有的属性
vm.$nextTick(()=>{console.log(vm)})---//异步方法,等待dom完成后可以操作dom,(每次数据改变之后想 要获取操作DOM,都可以使用nextTick)。
vm.$watch---是一个实例方法 监听函数
vm.$refs ---//关联ref属性的DOM元素,可以操作这个关联的元素
- $watch是一个实例方法 监听函数
vm.$watch('a',function(newVal,oldVal){
//这个回调会在`vm.a`改变后调用
})
注:不要在实例属性或者回调函数中(如 vm.$watch('a', newVal => this.myMethod()))使用箭头函数。因为箭头函数绑定父上下文,所以 this 不会像预想的一样是 Vue 实例,而是 this.myMethod 未被定义。
vue模板
文本 : {{}}---Mustache” 语法
数据绑定最常见的形式就是使用 “Mustache” 语法(双大括号)的文本插值
<span>Message: {{ msg }}</span>
绑定的数据对象上 msg 属性发生了改变,插值处的内容都会更新。
<span v-once> v-once属性会让元素里边的值永远不会改变{{ msg }}</span>
纯html : v-html='数据'
双大括号会将数据解释为纯文本,而非 HTML 。为了输出真正的 HTML ,你需要使用 v-html 指令
<div v-html="rawHtml"></div>
被插入的内容都会被当做 HTML —— 数据绑定会被忽略
属性 : v-bind:propName='数据'
Mustache 不能在 HTML 属性中使用,应使用 v-bind 指令:
<div v-bind:id="dynamicId"></div>
数据可以使用js表达式加工生成
{{ number + 1 }}
{{ ok ? 'YES' : 'NO' }}
{{ message.split('').reverse().join('') }}
<div v-bind:id="'list-' + id"></div>
vue指令
是带有v-前缀的特殊属性。指令属性的值预期是单一js表达式。
指令的职责就是当其表达式的值改变时相应的将某些行为应用到DOM上。
参数:
一些指令能接受一个参数 在指令后以冒号指明,例如,v-bind指令被用来响应的更新HTML的属性:
<a v-bind:href='url'></a>
<a v-on:click="doSomething">
修饰符
修饰符是以半角句号 . 指明的特殊后缀,用于指出一个指令应该以特殊方式绑定。例如:prevent,stop,capture,self,once,
.prevent修饰符告诉v-on指令对于触发事件调用 event.preventDefault();
<form v-on:submit.prevent='onSubmit'>
v-if 显示隐藏
<div id="app-3">
<p v-if="seen">现在你看到我了1</p>
<p v-else>现在你看到我了2</p>
</div>
var app3 = new Vue({
el: '#app-3',
data: {
seen: true
}
})
template标签的使用
v-show (状态一直改变性能强于v-if)
<div id="app-3">
<p v-show="seen">现在你看到我了</p>
</div>
var app3 = new Vue({
el: '#app-3',
data: {
seen: true
}
})
v-for 循环
<div id="app-4">
<ol>
<li v-for="todo in todos">
{{ todo.text }} //渲染每一个text
</li>
</ol>
</div>
var app4 = new Vue({
el: '#app-4',
data: {
todos: [
{ text: '学习 JavaScript' },
{ text: '学习 Vue' },
{ text: '整个牛项目' }
]
}
})
v-model:双向绑定
<div id="app-3">
<p>{{ text}}</p>
<input v-model="text">
</div>
var app3 = new Vue({
el: '#app-3',
data: {
text: 'hello'
}
})
v-text='data' 相当于 {{data}}
v-html 相当于可以渲染DOM的 v-text
v-bind 绑定属性(可缩写为 :属性名=' data ')
<div id="app-2">
<span v-bind:title="message">//添加title属性(<span :title="message">)
鼠标悬停几秒钟查看此处动态绑定的提示信息!
</span>
</div>
var app2 = new Vue({
el: '#app-2',
data: {
message: '页面加载于 ' + new Date()
}
})
v-on绑定事件(可缩写为 @事件名=" 函数名 ")
<div id="app-5">
<p>{{ message }}</p>
<button v-on:click="reverseMessage">逆转消息</button>
//缩写为 <button @click="reverseMessage">逆转消息</button>
</div>
var app5 = new Vue({
el: '#app-5',
data: {
message: 'Hello Vue.js!'
},
methods: {
reverseMessage: function () {
this.message = this.message.split('').reverse().join('')
}
}
})
计算属性computed
先贴个示例
<div id="demo">{{ fullName }}</div>
//js代码
<script>
var vm = new Vue({
el: '#demo',
data: {
firstName: 'Foo',
lastName: 'Bar'
},
computed: {
fullName: function () {
return this.firstName + ' ' + this.lastName
}
}
})
</script>
计算属性的缓存 和 methods的比较
- 计算属性只有在它的相关依赖发生改变时才会重新求值(有缓存),相比methods节约了性能。
- 这就意味着只要 firstName,lastName还没有发生改变,多次访问 fullName计算属性会立即返回之前的计算结果,而不必再次执行函数。
计算属性 和 Watched属性的比较
- 当你有一些数据需要随着其它数据变动而变动时,你很容易滥用 watch。
- 通常更好的想法是使用 computed 属性而不是命令式的 watch 回调。
计算属性默认只拥有getter方法,但是可以自定义一个setter方法。
computed: {(最大的特点:不支持异步,如果需要异步执行要用watch)
fullName: {
// getter 监听获取的回调
get: function () {
return this.firstName + ' ' + this.lastName
},
// setter 监听设置的回调(给别人赋值,自身没有效果,所以一般不用set函数)
set: function (newValue) {
var names = newValue.split(' ')
this.firstName = names[0]
this.lastName = names[names.length - 1]
}
}
}
观察者属性watch(数据不变不触发,能异步,但是性能不及computed,一次只能监听一个数据的变动)
通过watch属性可以手动观察Vue实例上的数据变动,当然也可以调用实例上的vm.$watch达到相同的目的。
使用watch属性的灵活性在于,当监测到数据变化的时候,可以做一些设置中间状态之类的过渡处理。
var watchExampleVM = new Vue({
el: "#watch-example",
data: {
question: "",
answer: "I cannot give you an answer until you ask a question!"
},
watch: {
// 如果question发生改变,该函数就会运行
question: function (newQuestion) {
this.answer = "Waiting for you to stop typing..."
this.getAnswer()
}
},
})
watch只能监控对象的一层数据,不能深层监控
解决办法
watch:{
data:{//深度监控的数据
handler(){//默认写成函数,就相当于默认写了个handler
},deep:true
}
}
过滤器(vue2.0已经把过滤器删除需要自己实现)
实现方法:https://blog.csdn.net/dream_broken/article/details/73481046
过滤器可以放在两个地方:mustache 插值和 v-bind 表达式。
<!-- in mustaches -->
{{ message | capitalize }}
<!-- in v-bind -->
<div v-bind:id="rawId | formatId"></div>
内置过滤器
- capitalize用于将表达式中首字母转换为大写形式
{{'name'|capitalize}}--->'Name'
- uppercase将表达式中所有的字母转换为大写形式
{{'name'|uppercase}}--->'NAME'
- lowercase将表达式中所有的字母转换为小写形式
{{'NAME'|lowercase}}--->'name'
- json 相当于JSON.stringify 后边可以跟一个数字,表示json字符串首行缩进的个数
data:
obj:{name:'aa',age:'bb'}
{{obj|json 4}}
//输出
{ 'name': 'aa', 'age': 'bb'}
*limitBy 限制数组为开始的前N个元素
//只显示开始的前10个元素
<div v-for='item in items | limitBy 10'></div>
//只显示第5到15个元素
<div v-for='item in items | limitBy 10 5'></div>
- filterBy
//只显示包含hello字符串的item
<div v-for='item in items | filterBy "hello" '></div>
- orderBy返回排序后的数组 >0为升序 <0为降序
//升序排列
<div v-for='item in items | orderBy order>0'></div>
- currency过滤器 : 将输入的数字转换成现金的过滤器。可以跟上货币符号(默认$)和保留的小数位(默认2)。
<li v-for="product in products">
{{ product.name | capitalize }} - {{ product.price | currency }}
</li>
自定义过滤器
- 定义一个全局的自定义过滤器,需要使用Vue.filter()构造器。这个构造器需要两个参数。
Vue.filter()
1.filterId: 过滤器ID,用来做为你的过滤器的唯一标识;
2.filter function: 过滤器函数,用一个function来接收一个参数,
之后再将接收到的参数格式化为想要的数据结果。
定义一个filter
Vue.filter( 'discount' , function(value,discount) {
return value * ( discount / 100 ) ;
});
使用
<ul>
<li v-for="product in products">
{{ product.name | capitalize }} - {{ product.price | discount 25 | currency }}
</li>
</ul>
或者
let vm=new Vue({
el:'#app',
filters:{//自定义过滤器
toFixed(input,param1){//这里的this指向window
return input.toFixed(param1);//input代表的是管道符‘|’前面的内容,param1代表的是toFixed中传递的参数
}
}
})
使用还是用竖线
{{ product.price| toFixed(2)}}//保留两位小数
关于样式操作
class
对象语法
- 我们可以传给 v-bind:class 一个对象,以动态地切换 class:
<div v-bind:class="{ active: isActive }"></div>
- v-bind:class 指令也可以与普通的 class 属性共存
<div class="static"
v-bind:class="{ active: isActive, 'text-danger': hasError }">
</div>
data:
data: {
isActive: true,
hasError: false
}
结果渲染为:
<div class="static active"></div>
当 isActive 或者 hasError 变化时,class 列表将相应地更新。例如,如果 hasError 的值为 true,class 列表将变为 "static active text-danger"。
- 绑定的数据对象不必内联定义在模板里:
<div v-bind:class="classObject"></div>
data: {
classObject: {
active: true,
'text-danger': false
}
}
数组语法
<div v-bind:class="[activeClass, errorClass]"></div>
data: {
activeClass: 'active',
errorClass: 'text-danger'
}
渲染为
<div class="active text-danger"></div>
用三元表达式:
<div v-bind:class="[isActive ? activeClass : '', errorClass]"></div>
style
对象语法
div v-bind:style="{ color: activeColor, fontSize: fontSize + 'px' }"></div>
data: {
activeColor: 'red',
fontSize: 30
}
直接绑定到一个样式对象
<div v-bind:style="styleObject"></div>
data: {
styleObject: {
color: 'red',
fontSize: '13px'
}
}
同样的,对象语法常常结合返回对象的计算属性使用。
数组语法
v-bind:style 的数组语法可以将多个样式对象应用到同一个元素上
<div v-bind:style="[baseStyles, overridingStyles]"></div>
data: {
baseStyles: {
color: 'red',
fontSize: '13px'
},
overridingStyles:{
background:'#ccc',
}
}
自动添加前缀
当v-bind:style
使用需要添加浏览器引擎前缀的 CSS 属性时,如transform
,Vue.js 会自动侦测并添加相应的前缀。
事件
一般写法---------------- v-on:click=function
简写------------------- @click=''
事件对象------------------ @click=show($event);
事件冒泡阻止冒泡 -----------1)ev.cancelBubble=true;=2)@click.stop 推荐
默认行为-----------阻止默认行为1)ev.preventDefault() 2)@contextmenu.prevent 推荐
键盘类的事件
@keydown $event ev.keyCode
回车
@keyup.enter
@keyup.13
上下左右
@keyup/keydown.left/right/up/down
method配置
注意事项
- methods重定义的this始终指向Vue实例
- 与事件绑定的方法支持参数event即原生DOM事件的传入
- 方法用在普通元素上,只能监听原生DOM事件,用在自定义元素组件上,也可以监听子组件触发的自定义事件
$event的使用
<button @click='say("hello",$event)'>submit</button>
method:{
say:function(msg,event){
console.log(msg);
event.preventDefault();
}
}
修饰符
- 阻止默认行为prevent
<button @submit.prevent='submit("hello",$event)'>submit</button>
- 阻止事件冒泡stop
<button @submit.stop='submit("hello",$event)'>submit</button>
- 捕获模式capture
<button @submit.capture='submit("hello",$event)'>submit</button>
- 事件只在该元素本身触发时执行self
<button @submit.self='submit("hello",$event)'>submit</button>
- 事件的修饰符可以串联使用
<button @click.stop.prevent='doSomething'>submit</button>
- 键盘事件
<input @keyup.enter='submit'>//enter事件
<input @keyup.tap='submit'>//tap事件
<input @keyup.up='submit'>//向上up事件
<input @keyup.delete='submit'>//delete事件
<input @keyup.space='submit'>//space空格事件