vue简介
尤雨溪
渐进式:类似于迭代开发 ,vue.js只是一些核心代码,可以让你搭建基本页面
如果页面功能相对比较丰富,那么需要相关的一些插件去完成。插件:就是一些功能代码模块。它是为了给已经完成的功能代码,额外去添加功能用的。
官方插件:vuex vue-router......官方出品的 都是vue官方的插件
第三方插件:也是为了给vue去添加功能用的,但是是别的人写的。比如axios数据为尊 动态显示页面
为什么使用vue?
动态数据生成页面结构及修改数据后的区别
原生写法
//动态数据驱动页面
let arr = ['赵丽颖','杨幂','迪丽热巴']
let str = '<ul>'
for(let i = 0; i <arr.length; i++){
str += `<li>${arr[i]}</li>`
}
str += '</ul>'
document.getElementById('app').innerHTML = str
// 后期数据更改了,效率极低,没有虚拟dom,所有的元素都要进行重绘重排
str = '<ul>'
arr = ['旺财','小黑','大黄']
for(let i = 0; i <arr.length; i++){
str += `<li>${arr[i]}</li>`
}
str += '</ul>'
document.getElementById('app').innerHTML = str
vue写法
let vm = new Vue({
el:'#app',
data:{
arr:['赵丽颖','杨幂','迪丽热巴']
}
})
vm.arr = ['旺财','小黑','大黄']
原生的初始化渲染是不会拖慢效率的,甚至比react和vue还要快,因为不需要创建虚拟dom
但是数据一旦更改,那么react和vue比原生的效率要高的多,因为有diffing算法的介入
虚拟dom会进行对比,减少真实dom的重绘重排
vue的基本使用和单向数据绑定
挂载点:<div id="app">
挂载点的内部就是模板,但是不包含挂载点
模板是在挂载点内部,不再是单纯的html了
它是由html + js组成
模板有模板语法:
分为两种:
插值语法{{}},它主要是给标签插入内容,
指令语法 它主要是用来操作标签的,包含属性也包含内容,
但是指令比较多,每个指令只能做一件事情
指令操作属性和插值语法操作内容,我们所书写的都不再是字符串了
全部都变为js表达式
使用指令后,属性值的双引号就不再是字符串的边界,而是js的边界
<p>{{msg.toUpperCase()}}</p>
<a v-bind:href="url">点击去百度</a>
<!-- 简写 -->
<a :href="url + '哈哈'">点击去百度</a>
1、引入vue
2、书写模板挂载点
3、书写配置项 new Vue
new Vue({
el:'#app', //这个值是一个css选择器字符串,它其实后期通过这个css找挂载点,
data:{
msg:'i love you!',
url:'https://www.baidu.com'
},
// template:'<p>{{msg}}</p>' //模板,这样的写法以后不用,1、没提示2、嵌套起来很复杂
})
数据代理
<body>
<div id="app">
<p>{{this.msg}}</p>
</div>
<script src="../js/vue.js"></script>
<script>
let vm = new Vue({
el:"#app",
data(){
return {
msg:'我爱你'
}
}
})
</script>
</body>
msg到底是谁的?
模板当中msg其实是this的,this代表的其实是vm vm是实例化的对象
vue当中模板当中的数据全部都是vm的,所有的方法也是vm的
数据是一上来要经过数据代理,把data当中的msg,代理到vm身上
vm身上也就有一个同名属性msg,但是并没有真正的值而是多了getter和setter
data里面所有的数据最终都会跑到vm身上
双向数据绑定
<body>
<div id="app">
<!-- v-model就是双向数据绑定,针对表单类元素前期 -->
<input type="text" v-model="msg">
<span>我爱你{{msg}}</span>
</div>
<script src="../js/vue.js"></script>
<script>
let vm = new Vue({
el:'#app',
data(){
return {
msg:'赵丽颖'
}
}
})
</script>
</body>
双向数据绑定和MVVM
双向: v-model 一般表单类元素才能双向绑定
MVVM:
M:model 模型的意思 本质就是我的data数据
V:view 视图的意思 本质就是我的页面元素
VM:ViewModel 视图模型的意思 本质就是我的vm实例
事件的绑定和处理 v-on:click 简写 @click
事件绑定:两个东西 事件类型 事件回调
vue当中的方法要在methods当中去配置,并且这些方法最终都也会变成vm的方法
<body>
<div id="app">
<p>{{msg}}</p>
<!-- <button v-on:click="test">点击切换</button> -->
<button @click="test">点击切换</button>
</div>
<script src="../js/vue.js"></script>
<script>
new Vue({
el:'#app',
data:{
// 这里面的数据最终都会代理到vm身上
msg:'赵丽颖'
},
methods: {
// 以后无论是自己定义的函数方法或者是回调函数
// 都在这个配置当中去写
test(){
// 配置项当中methods的方法,this都是指向vm
this.msg = '杨幂'
}
},
})
</script>
</body>
3个重要点
1). vue控制的所有回调函数的this都是vm
2). 所有data/computed/methods中的属性/方法都会成为vm的属性/方法
3). 模板中表达式读取数据, 是读取vm的属性;模板中调用函数, 调用的是vm的方法
computed计算属性 和 watch监视
姓名案例:
初始化数据:firstName lastName
后期展示:fullName
<body>
<div id="app">
姓:<input type="text" v-model="firstName"> <br>
名:<input type="text" v-model="lastName"> <br>
<!-- 第一种办法 插值语法
这样的写法不是不行,是不好,模板当中最好简洁-->
姓名:<p>{{firstName + '-' + lastName}}</p>
<!-- 第二种办法
这样的写法也是可行,但是不好 ,因为多次使用会调用多次,效率不高-->
姓名:<p>{{getFullName()}}</p>
<!-- 姓名:<p>{{getFullName()}}</p>
姓名:<p>{{getFullName()}}</p>
姓名:<p>{{getFullName()}}</p> -->
<!-- 第三种办法:计算属性,
这样的写法很好,多次使用,只需要调用一次,因为内部有缓存机制 -->
<!-- 一般是当我们没有这个数据还想要用这个数据,这个数据和已有的数据有关系 -->
姓名: <p>{{fullName}}</p>
<!-- 姓名: <p>{{fullName}}</p>
姓名: <p>{{fullName}}</p>
姓名: <p>{{fullName}}</p> -->
姓名: <input type="text" v-model="fullName1">
</div>
<script src="../js/vue.js"></script>
<script>
Vue.config.productionTip = false
new Vue({
el:'#app',
data(){
return {
firstName:'zhao',
lastName:'liying',
}
},
methods: {
getFullName(){
console.log('函数被调用getFullName');
return this.firstName + '-' + this.lastName
}
},
computed: {
// 计算属性
// 计算属性全写,当我们计算的这个属性既可读又可写的时候,那么就得用全写
fullName1:{
get(){
return this.firstName + '-' + this.lastName
},
set(val){
// set和get不同,get是和watch进行对比的
// set没有,set只是监视数据变化后修改页面
let arr = val.split('-')
this.firstName = arr[0]
this.lastName = arr[1]
}
},
// 如果页面上只是在读取这个计算的属性,可以简写为函数
// 相当于是get
// 但是切记,计算属性虽然看似函数,其实是计算了一个新的数据叫fullName
// 计算属性计算出来的数据当data数据对待,也就是说也会代理到vm身上
fullName:function(){
// console.log('计算属性被调用fullName');
return this.firstName + '-' + this.lastName
// computed计算属性不能异步返回数据
// let result = 0
// setTimeout(() => {
// result = this.firstName + '-' + this.lastName
// }, 1000);
// return result
}
},
})
</script>
</body>
<body>
<div id="app">
姓:<input type="text" v-model="firstName"> <br>
名:<input type="text" v-model="lastName"> <br>
<!-- 第四种方案,使用监视 -->
姓名:<p>{{fullName}}</p>
</div>
<script src="../js/vue.js"></script>
<script>
Vue.config.productionTip = false
// 一般监视什么时候用:
// 必须有这个数据,才能监视,监视一般主要是用于数据发生改变,做一些事情的时候
new Vue({
el:'#app',
data(){
return {
firstName:'zhao',
lastName:'liying',
fullName:''
}
},
// 监视数据
watch: {
// 当firstName发生改变的时候,会自动调用handler回调做一些事
firstName:{
immediate:true, //立即 无论数据改不改变,先调一次handler
handler(newVal,oldVal){
// console.log(111);
// this.fullName = newVal + '-' + this.lastName
setTimeout(() => {
this.fullName = newVal + '-' + this.lastName
}, 2000);
}
},
lastName:{
immediate:true,
handler(newVal,oldVal){
this.fullName = this.firstName + '-' + newVal
}
}
},
})
</script>
</body>
1、复杂的插值表达式写法
2、methods方法实现(多次使用会调用多次,效率不高)
3、computed计算属性实现 (多次使用,只需要调用一次,因为内部有缓存机制)
4、methods和computed的区别
计算属性效率是比较高的,因为有缓存
5、watch监视属性
两种写法 配置项写法监视firstName vm.$watch监视lastName
6、watch监视实现computed的效果 immediate作用
computed和watch的区别
同步计算属性
computed计算属性,内部不能异步返回数据
原因是因为computed是需要return结果的,return是同步代码
异步watch
watch内部可以去写异步,原因是watch不需要返回数据
它是把一个响应式数据进行赋值操作
computed一般不写异步
watch可以写异步
什么时候用计算属性computed什么时候用watch监视
一般情况下:
没有数据想使用 考虑计算属性computed
有数据,想根据这个数据的变化去做一些事情
能用computed的一定能用watch实现
能用watch实现的不一定能用computed实现
不能因为watch能实现computed的功能,以后就全部使用watch,最终还是采用一般用法
他们作比较的时候 比较的是computed的getter和watch的区别,和computed里面的setter没关系
8、计算属性的setter,只是为计算属性添加了监视,如果数据后期修改,会发生响应式的变化(修改页面)