一、vue介绍
1.vue是什么?
一套用于构建用户界面的“渐进式”js框架(vue关注你给定数据,我构建界面)
渐进式:(逐渐、递进、方式)
简单应用:只需要一个轻量的核心库,只需要100kb
复杂应用:可以引入各式各样的vue插件
2.vue是谁开发的?
尤雨溪
2013年在谷歌工作,受到Angular框架的启发,觉得Angular太重了,开始开发的轻量级框架,
3.vue特点
3-1.采用组件化模式,提高代码复用率,且让代码更好维护,比如:轮播是一个组件,侧边栏是一个组件(html、js、css)
3-2.声明式编码,让编码人员无需直接操作DOM,提高开发效率,比如:之前是用原生的js"命令式编码" vue用的“声明式编码”使用v-for去遍历
3-3.使用虚拟DOM+优秀的Diff算法,尽量复用DOM节点
4.学习vue之前要掌握的js基础知识?
ES6语法规范:解构赋值、模板函数、箭头函数
ES6模块化:默认暴露、分别暴露、统一暴露、
包管理器:npm cnpm
原型、原型链:重点
数组常用方法:过滤数组、加工数组、筛选最值
axios
promise
异步和同步
...
二、官网使用指南
教程和API参考是最重要的
风格指南 代码规范性
示列
cookbook {js和vue}代码是否写的太复杂了,没有做二次封装 教你技巧
生态系统的-工具-核心插件
vue cli脚手架
三、搭建vue环境
Download the Vue Devtools extension for a better development experience:缺少vue开发者工具
Vue Devtools
在浏览器上面,打印Vue.config,可以在vue官网API中,看到全局配置信息
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<!-- 引入vue -->
<script type="text/javascript" src="./js/vue.js"></script>
</head>
<style>
.box1{
width: 500px;
height: 500px;
background: red;
}
.box2{
width: 250px;
height: 250px;
background: greenyellow;
}
</style>
<body>
<!-- 容器root -->
<!--
一、vue实例
1.想让vue工作,就必须创建一个vue实例,且要传入一个配置对象
2.root容器里的代码依然符合html规范,只不过混入了一些特殊的vue语法
3.root容器里的代码被称为【vue模板】
二、vue实例的特点
1.vue实例和容器是一一对应的
2.真实开发中只有一个vue实例,并且会配合着组件一起使用
三、vue模板语法有2大类
1.插值语法:
功能:用于解析标签体内容
写法:{{xxx}},xxx是js表达式,并且可以直接读取到data中所有属性
1-1.{{xxx}}中的xxx要写js表达式,并且xxx可以自动读取到data中的所有属性
1-2.一旦data中的数据发生改变,那么页面中用的该数据的地方也会自动更新
注意区分:js表达式 和 js代码(语句)
1-2-1.表达式:一个表达式会产生一个值,可以放在任何一个需要值的地方:
(1).a
(2).a+b
(3).demo(1)
(4). x===y? 'a':'b'
1-2-2.js代码(语句)
(1).if(){}
(2).for(){}
2.指令语法:
功能:用于解析标签(包括:标签属性、标签体内容、绑定事件。。。。。)
举例:v-bind:href='xxx' 或 简写为:href='xxx',xxx统一要写js表达式,并且可以直接读取到data中的所有属性
备注:vue中有很多的指令,并且形式都是:v-???,此处我们只拿v-bind举例
四、vue的数据绑定
1.单向的数据绑定(v-bind),数据只能从data流向页面
2.双向的数据绑定(v-model),数据不仅能从data流向页面,还可以从页面流向data
3.备注:
3-1.双向绑定一般都应用在表单类元素上(如:input、select等)
3-2.v-model:value 可以简写为v-moderl,因为v-model默认收集的值就是value值
五、el与data的2种写法
1.vue实例中:
1-1.带$符号都是提供给程序员用的
1-2.不带$符合的是vue底层在用
2.el有2种写法
(1).new Vue时候配置el属性。
(2).先创建Vue实例,随后再通过vm.$mount('#root')指定el的值。
3.data有2种写法
(1).对象式
(2).函数式
如何选择:目前哪种写法都可以,以后学习到组件时,data必须使用函数式,否则会报错。
4.一个重要的原则:
由Vue管理的函数,一定不要写箭头函数,一旦写了箭头函数,this就不再是Vue实例了。
六、理解MVVM
MVVM模型
1. M:模型(Model) :data中的数据
2. V:视图(View) :模板代码(标签)
3. VM:视图模型(ViewModel):Vue实例vm
简述:模型(Model)中的数据-经过vm视图模型-在V视图中展示页面
如果V视图中的数据要进行更改-经过vm视图模型-最终回到(模型(Model)中的数据)
观察发现:
1.data中所有的属性,最后都出现在了vm身上。
2.vm身上所有的属性 及 Vue原型上所有属性,在Vue模板中都可以直接使用。
七、回顾Object.defineProperty方法
1.vue的数据劫持用到了这个方法
2.数据代理用到了这个方法
3.计算属性用到了这个方法
八、js中的数据代理
1.通过一个对象代理对另一个对象中属性的操作 读/写
九、vue中的数据代理
1.Vue中的数据代理:
通过vm对象来代理data对象中属性的操作(读/写)
2.Vue中数据代理的好处:
更加方便的操作data中的数据
3.基本原理:
通过Object.defineProperty()把data对象中所有属性添加到vm上。
为每一个添加到vm上的属性,都指定一个getter/setter。
在getter/setter内部去操作(读/写)data中对应的属性。
4._data是=data _data里面的不是数据代理,是数据劫持
十、事件处理
1.使用v-on:xxx 或 @xxx 绑定事件,其中xxx是事件名;
2.事件的回调需要配置在methods对象中,最终会在vm上;
3.methods中配置的函数,不要用箭头函数!否则this就不是vm了;
4.methods中配置的函数,都是被Vue所管理的函数,this的指向是vm 或 组件实例对象;
5.@click="demo" 和 @click="demo($event)" 效果一致,但后者可以传参;
十一、事件修饰符
0.可以多个写法:prevent.stop
1.prevent:阻止默认事件(常用);
2.stop:阻止事件冒泡(常用);
3.once:事件只触发一次(常用);
4.capture:使用事件的捕获模式;
5.self:只有event.target是当前操作的元素时才触发事件;
6.passive:事件的默认行为立即执行,无需等待事件回调执行完毕;
十二、键盘事件
0.多个写法keyup.ctrl.y
1.Vue中常用的按键别名:
回车 => enter
删除 => delete (捕获“删除”和“退格”键)
退出 => esc
空格 => space
换行 => tab (特殊,必须配合keydown去使用)
上 => up
下 => down
左 => left
右 => right
2.Vue未提供别名的按键,可以使用按键原始的key值去绑定,但注意要转为kebab-case(短横线命名)
3.系统修饰键(用法特殊):ctrl、alt、shift、meta
(1).配合keyup使用:按下修饰键的同时,再按下其他键,随后释放其他键,事件才被触发。
(2).配合keydown使用:正常触发事件。
4.也可以使用keyCode去指定具体的按键(不推荐)
5.Vue.config.keyCodes.自定义键名 = 键码,可以去定制按键别名
十三、姓名案列使用插值语法实现
十四、姓名案列使用vue计算属性实现
1.定义:要用的属性不存在,要通过已有属性计算得来。
2.原理:底层借助了Objcet.defineproperty方法提供的getter和setter。
3.get函数什么时候执行?
(1).初次读取时会执行一次。
(2).当依赖的数据发生改变时会被再次调用。
4.优势:与methods实现相比,内部有缓存机制(复用),效率更高,调试方便。
5.备注:
1.计算属性最终会出现在vm上,直接读取使用即可。
2.如果计算属性要被修改,那必须写set函数去响应修改,且set中要引起计算时依赖的数据发生改变。
6.计算属性的简写方式,只有get没用set
十五、天气案列
绑定事件的时候:@xxx="yyy" yyy可以写一些简单的语句
<button @click="isHot = !isHot">切换天气</button>
十六、监视属性
0.如果要监测对象下的a.需要使用字符串抱起来'numberlist.a':{}
1.当被监视的属性变化时, 回调函数自动调用, 进行相关操作
2.监视的属性必须存在,才能进行监视!!
3.监视的两种写法:
(1).new Vue时传入watch配置
(2).通过vm.$watch监视
-->
<div id="root">
<h1>插值,{{name}}</h1>
<h2> {{Date.now()}}</h2>
<h3>{{yingwen.toUpperCase()}}</h3>
<h4>
<a v-bind:href="url" >百度{{$options}}</a>
</h4>
单向的数据绑定<input type="text" :value = 'iptValueOne'><br>
双向的数据绑定<input type="text" v-model = 'iptValueTwo'>
<!-- 双向的数据绑定<input type="text" v-model:value = 'iptValueTwo'> -->
</div>
<div id="root1">
<button v-on:click="showInfo1">点我提示消息1</button>
<button @click="showInfo2(66,$event)">点我提示消息2</button>
<a :href="url" @click.prevent="showInfo3">prevent阻止默认事件(常用)</a>
<div class="box2" @click='showInfo3'>
<button @click.stop='showInfo3'>阻止冒泡事件</button>
</div>
<button @click.once='showInfo3'>事件只执行一次后,就不会执行了</button>
<div class="box1" @click.capture="showMsg(1)">
<div class="box2" @click="showMsg(2)">使用事件的捕获模式</div>
</div>
<input type="text" @keyup.down="keyfun"><br>
<input type="text" v-model="xing"><br>
<input type="text" v-model="ming"><br>
全名:{{xingMing()}}<br>
全名:{{quanming}}<br>
全名:{{quanmin}}<br>
在模板语法里面,用插值语法调方法
没加小括号:把函数展示到页面上,不会有值
加小括号:我是想要把方法里的返回值展示到页面上来,存在值
事件里面加与不加没有区别,有区别的是在插值语法里面<br>
<!-- <div>今天天气很{{isHot?'炎热':'凉爽'}}</div> -->
<div>今天天气很{{isHota}},{{num}}</div>
<button @click='isHot = !isHot'>切换天气</button>
<button @click='tianQiClick'>切换天气</button>
<p>a的值{{numberlist.a}}</p>
<button @click='numberlist.a++'>点击+1</button>
<p>b的值{{numberlist.b}}</p>
<button @click='numberlist.b++'>点击+1</button>
</div>
<script type="text/javascript">
Vue.config.productionTip = false//阻止 vue在启动时生成生产提示
//创建vue实例
const vm = new Vue({
// el:'#root',//el用于指定当前vue实例为哪个容器服务,值通常为css选择器字符串-el第一种写法
// data:{//data中用于存储数据,数据供el所指定的容器去使用,值我们暂时先写成一个对象-data第一种写法
// name:'学习',
// yingwen:'agese',
// url:'http://www.baidu.com',
// iptValueOne:'单向的数据绑定',
// iptValueTwo:'双向的数据绑定',
// }
//data的第二种写法
// data:function(){//简写:为下面写法
// data:()=>{//如果写成箭头函数,那么this,就会变成Window对象,因为箭头函数会往外面找,找到Window
data(){
console.log("this指向为vue的实例对象",this)
return{
name:'学习',
yingwen:'agese',
url:'http://www.baidu.com',
iptValueOne:'单向的数据绑定',
iptValueTwo:'双向的数据绑定',
}
}
})
console.log(vm)
vm.$mount("#root")//el第二种写法,mount方法为v下面的Prototype下面的$mount
</script>
<script type="text/javascript">
let obj1 = {x:100}
let obj2 = {y:200}
Object.defineProperty(obj2,'x',{
get:()=>{
return obj1.x
},
set(value){
obj1.x = value
}
})
</script>
<script type="text/javascript">
Vue.config.productionTip = false//阻止 vue在启动时生成生产提示
const vm1 = new Vue({
el:"#root1",
data(){
return{
name:'xx',
url:'http://www.baidu.com',
xing:'张',
ming:'小明',
isHot:false,
num:0,
numberlist:{
a:0,
b:1
}
}
},
computed:{
quanming:{
//get有什么作用?当有人读取quanming时,get就会被调用,且返回值就作为fullName的值
//get什么时候调用?1.初次读取quanming时。2.所依赖的数据发生变化时。
get(){
return this.xing + '-' + this.ming
},
//set什么时候调用? 当quanming被修改时。
set(value){
let arr = value.split('-');
console.log(value,arr)
this.xing = arr[0];
this.ming = arr[1];
}
},
quanmin(){//计算属性的简写方式,只有get没用set
return this.xing + '-' + this.ming
},
isHota(){
return this.isHot?'炎热':'凉爽'
}
},
watch:{
isHot:{
immediate:true,//初始化的时候让handler执行一次
//当isHot发生了变化时,handler会被调用
handler(newValue,oldValue){
console.log('isHot发生了变化',newValue,oldValue)//新的值、旧的值
}
},
isHota:{
immediate:true,//初始化的时候让handler执行一次
//当isHot发生了变化时,handler会被调用
handler(newValue,oldValue){
console.log('isHot发生了变化',newValue,oldValue)//新的值、旧的值
}
},
//监视多级结构中某个属性的变化
'numberlist.a':{
handler(newValue,oldValue){
console.log('numberlist.a发生了变化',newValue,oldValue)//新的值、旧的值
}
},
//监视多级结构中所有属性的变化
numberlist:{
immediate:true,//初始化的时候让handler执行一次
deep:true,//开启深度监测
handler(newValue,oldValue){
console.log('numberlist发生了变化',newValue,oldValue)//新的值、旧的值
}
},
//简写
/* numberlist(newValue,oldValue){
console.log('isHot被修改了',newValue,oldValue,this)
} */
},
methods:{
showInfo1(event){
// alert('弹出消息',event)
console.log('2',event.target.innerText,this)
},
showInfo2(number,event){
// alert('弹出消息',event)
console.log('有event',event.target.innerText,this)
console.log('无event的时候',number,event)
},
showInfo3(){
alert('事件执行了')
},
showMsg(num){
console.log(num)
},
keyfun(e){
console.log(e.key)
if(e.keyCode === 13){
console.log(e.target.value)
console.log(e.keyCode)
}
},
xingMing(){//插值语法实现
return this.xing.slice(0,3)+'--'+this.ming
},
tianQiClick(){
this.num++
this.isHot = !this.isHot
console.log(this.isHot)
}
},
})
vm1.$watch('isHot',{
handler(newValue,oldValue){
console.log('isHot发生了变化11',newValue,oldValue)//新的值、旧的值
}
})
//简写
/* vm.$watch('isHot',(newValue,oldValue)=>{
console.log('isHot被修改了',newValue,oldValue,this)
}) */
</script>
</body>
</html>