Vue学习札记
Episode1:初识vue
vue渐进式JavaScript框架
渐进式:以核心库为基础,通过安装插件来实现基础功能以外的其他功能
英文官网:https://vuejs.org/
中文官网:https://cn.vuejs.org/
- 特点:
- 遵循MVVM模式
- 编码简介,体积小,运行效率高,适合移动/PC端开发
- 可轻松引入vue插件或第三方库开发项目
- 与已有框架之间的关系:
- 借鉴Angular.js的数据绑定技术和模板
- 借鉴React.js的组件化和虚拟DOM技术
- vue扩展插件:
- vue-cli:vue脚手架
- vue-resource(axios):ajax请求
- vue-router:路由
- vuex:状态管理
- vue-lazyload:图片懒加载
- vue-scroller:页面滑动相关
- mint-ui:基于vue的ui组件库(移动端)
- element-ui:基于vue的ui组件库(PC端)
Episode2:vue的基本使用
hello,world!实例:
直接上代码:
<head>
</head>
<body>
<--!>
1.引入Vue.js
2.创建Vue对象
el:指定根element(选择器)
data:初始化数据
3.双向数据绑定:v-model
4.显示数据:{{xxx}}
5.理解vue的MVVM实现
</--!>
<div id="app">
<input type="text" v-model="username">
<p>Hello{{username}}</p>
</div>
<script type="text/javascript" src="../**/vue.js"></script>
<script>
//创建vue实例
const vm = new Vue({ //配置对象
el:'#app', //element:选择器
data:{ //数据(model)
username:'wuhuqifei'
}
})
</script>
</body>
Episode3:vue模板语法
- 模板的理解: 动态的HTML页面,包含了一些js语法代码,双大括号表达式,指令(以v-开头的自定义标属性)
- 双大括号表达式: 语法:{{exp}}或{{{exp}}} 功能:想页面输出数据,可以调用对象的方法
- 指令一:强制数据绑定 功能:指令变化的属性值 完整写法: v-bind:xxx=‘yyy’ //yyy会作为表达式解析执行 简洁写法: :xxx=‘yyy’
- 指令二:绑定事件监听 功能绑定事件名的回调函数 完整写法: v-on:click=‘xxx’ 简洁写法: @click=’'
直接上代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>episode3_模板语法</title>
</head>
<body>
<!--
1.模板的理解:
动态的HTML页面,包含了一些js语法代码,双大括号表达式,指令(以v-开头的自定义标属性)
2.双大括号表达式:
语法:{{exp}}或{{{exp}}}
功能:想页面输出数据,可以调用对象的方法
3.指令一:强制数据绑定
功能:指令变化的属性值
完整写法:
v-bind:xxx='yyy' //yyy会作为表达式解析执行
简洁写法:
:xxx='yyy'
4.指令二:绑定事件监听
功能绑定事件名的回调函数
完整写法:
v-on:click='xxx'
简洁写法:
@click=''
-->
<div id="app">
<h2>1.双大括号表达式</h2>
<p>{{msg}}</p> <!--textContent-->
<p>{{msg.toUpperCase()}}</p>
<p>{{{msg}}}</p> //旧版本语法,现已不再使用
<p>{v-text="msg"}</p> <!--textContent-->
<p>{v-html="msg"}</p> <!--innerHTML-->
<h2>2.指令一:强制数据绑定</h2>
<img v-bind:src="imgUrl"></img> <!--会被理解成文本,无法显示图片-->
<img v-bind:src="imgUrl"></img>
<img :src="imgUrl"></img>
<h2>3.指令二:绑定事件监听</h2>
<button v-on:click="test">test1</button>
<button @alick="test1(abc)">test2</button>
<button @alick="test1(msg)">test2</button>
</div>
<script type="text/javascript" src="../**/vue.js"></script>
<script type="text/javascript">
new Vue({
el:"#app",
data{
msg:'<a href="http://www.baidu.com/">度娘在这里</a>',
imgUrl:'https://cn.vuejs.org/images/logo.png'
},
methods:{
test(){
alert('hahahahahahaha')
},
test1(content){
alert(content)
}
}
})
</script>
</body>
</html>
Episode4:计算属性与监视
-
计算属性
在computed属性对象中定义计算属性的方法
在页面中使用{{方法名}}来显示计算的结果
-
监视属性:
通过vm对象的$watch()或watch()配置来监视指定的属性
当属性变化是,回到函数自动调用,在函数内部进行计算
-
计算属性高级:
通过getter/setter实现对属性数据的显示和监视
计算属性存在缓存,多次读取只执行一次getter计算
getter:属性的get()方法,setter:sttter:属性的set()方法
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>episode3_模板语法</title> </head> <body> <div id="demo"> 姓:<input type="text" placeholder="First Name"><br> 名:<input type="text" placeholder="Last Name"><br> 姓名1(单向):<input typw="text" placeholder="Full Name1" v-model="fullName1"><br><!--通过计算属性实现--> 姓名2(单向):<input type="text" placeholder="Full Name2" v-model="fullName2"><br><!--通过监视实现--> 姓名3(双向):<input type="text" placeholder="Full Name3" v-model="fullName3"><br><!--通过计算属性实现双向更新数据--> </div> <script type="text/javascript" src="../**/vue.js"></script> <script type="text/javascript">new Vue({ el:'#demo', data:{ firstName:'A', lastName:'B', fullName:'A B' }, computed:{ //设么时候执行?初始化显示/相关的data属性数据发生改变时 fullName1(){ //计算属性中的一个方法,方法的返回作为属性值 console.log('fullName1') return this.firstName+' '+this.lastName }, fullName3:{ //回调函数的特点:1.你定义的 2.你没有调用 3.但最终它执行了 //注意:1.什么时候调用 2.用来做什么 //回调函数 当需要读取当前属性值时回调,根据相关的数据计算并返回当前属性的值 get(){ return this.firstName+' '+this.lastName }, //回调函数,当属性值发生改变时回调,更新相关的属性数据 set(value){ //value就是fullName3当前的值,set()方法作用为监视当前的属性值 const names = vlaues.split(' ') this.firstName = names[0] this.lastName = names[1] } } }, watch:{ //配置监视 firstName:function(value){ //firstName发生了变化 console.log(this) //this就是vm对象 this.fullName2 = value+' '+this.lastName } } vm.$watch('lastName',function(value){ //更新fullName2 this.fullName2 = this.firstName + ' ' +value }) }) </script> </body> </html>
Episode5:class与style绑定
-
理解
在应用界面中,某个(些)元素的样式变化的
class/style绑定就是专门用来实现动态样式效果的技术
-
class绑定::class=‘xxx’
xxx是字符串,xxx是对象,xxx是数组
-
style绑定
:style=“{color:activeColor,fontSize:fontSize+‘px’}”
其中activeColor/fontSize是data属性
下面是代码示例:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>episode5_class与style绑定</title>
<style>
.aClass{
color:red;
}
.bClass{
color:blue;
}
.cClass{
font-size:30px;
}
</style>
</head>
<body>
<div id="demo">
<h2>1.class绑定,:class = 'xxx'</h2>
<p class="cClass":class="a">xxx是字符串,芜湖起飞</p>
<p :class="{aClass:true,bClass:false}">xxx是对象,芜湖起飞</p>
<p :class="{aClass:isA,bClass:isB}">xxx是对象,芜湖起飞</p>
<p :class="['aClass','cClass']">xxx是数组,芜湖起飞</p>
<h2>2.style绑定</h2>
<p :style = "{color:activeColor,fontSize:fontSize+'px'}"></p>
<button @click="update"></button>
</div>
<script type="text/javascript" src="../**/vue.js"></script>
<script type="text/javascript">new Vue({
el:'demo',
data{
a:'aClass',
isA:true,
isB:false,
activeColor:'red',
fontSize:20
},
methods{
update() {
this.a = 'bClass'
this.isA = false
this.isB = true
this.activeColor = 'green'
this.fontSize = 30
}
}
})
</script>
</body>
</html>
Episode6:条件渲染
- 条件渲染指令:v-if、v-else、v-show
- 比较v-if与v-show:如果需要频繁切换,v-show较好,前者为彻底删除对象,后者只是display:none,对象依然在内存中
以下为代码示例:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>episode6_条件渲染</title>
</head>
<body>
<div id="demo">
<p v-if="ok">成功了</p>
<p v-else>失败了</p>
<p v-show="ok">表白成功</p>
<p v-show="!ok">表白失败</p>
<button @click="ok=!ok">切换</button>
</div>
<script type="text/javascript" src="../**/vue.js"></script>
<script type="text/javascript">
new Vue({
el:'#demo',
data:{
ok = false,
}
})
</script>
</body>
</html>
Episode7:列表渲染
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>episode7_列表渲染</title>
</head>
<body>
<!--
1.列表显示
数组:v-for/index
对象:v-for/key
2.列表的更新显示
删除item
替换item
-->
<div id="demo">
<h2>测试v-for遍历数组</h2>
<ul>
<li v-for="(p,index) in persons" :key="index">
{{index}---{p.name}---{p.age}}
---<button @click="deleteP(index)">删除</button>
---<button @click="updateP(index,{name:'Cat',age:20})">更新</button>
</li>
</ul>
<h2>测试v-for遍历对象</h2>
<ur>
<li v-for="(value,key) in persons[1]" :key="key">
{{value}}-{{key}}
</li>
</ur>
</div>
<script type="text/javascript" src="../**/vue.js"></script>
<script type="text/javascript">
new Vue({
el:'#demo',
data:{
persons[
{name:'Tom',age:18},
{name:'Jack',age:16},
{name:'Bob',age:17},
{name:'Rose',age:15}
]
}
methods:{
deleteP(index){
//删除persons中指定index的p
this.persons.splice(index,1)
},
updateP(index,newP){
//并没有改变person本身,数组内部发生了变化,但并没有调用变异方法,vue不会更新界面
//this.persons[index] = newP
this.persons.splice(index,i,newP)
//this.persons = []
}
}
})
</script>
</body>
</html>
Episode8:列表的搜索和排序
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>episode8_列表的搜索和排序</title>
</head>
<body>
<!--
1.列表过滤
2.列表排序
-->
<div id="test">
<input type="text" v-model="searchName">
<ul>
<li v-for="(p,index) in filterPersons" :key="index">
{{index}}---{{p.name}}---{{p.age}}
</li>
<button @click="setOrderType(1)">年龄升序</button>
<button @click="setOrderType(2)">年龄降序</button>
<button @click="setOrderType(0)">原本顺序</button>
</ul>
</div>
<script type="text/javascript" src="../**/vue.js"></script>
<script type="text/javascript">
new Vue({
el:'#test',
data:{
searchName:'',
orderName:0, //0代表原顺序,1代表升序,2代表降序
persons[
{name:'Tom',age:18},
{name:'Jack',age:16},
{name:'Bob',age:17},
{name:'Rose',age:15}
]
},
computed:{
filterPersons(){
//取出相关的数据
const {searchName,persons} = this
//最终要显示的数组
let fPersons;
//对persons进行过滤
fPersons.fiter(p => p.name,indexOf()searchName)!==-1)
//排序
if(orderType!==0){
fPersons.sort(function(p1,p2){ //如果返回负数,p1在前,返回正数,p2在前
//1代表升序,2代表降序
if(orderType===2){
return p2.age-p1.age
}else{
return p1.age-p2.age
}
})
}
return fPersons
}
},
methods:{
setOrderType(orderType){
this.orderType = orderType
}
}
})
</script>
</body>
</html>
Episode9:事件处理
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>episode9_事件处理</title>
</head>
<body>
<div id="example">
<h2>1.绑定监听</h2>
<button @click="test1()">test1</button>
<button @click="test2(Oooops)">test1</button>
<button @click="test3($event)">test1</button><!--event会默认被传,写与不写等效-->
<button @click="test4(123,$event)">test1</button>
<h2>2.事件修饰符</h2>
<!--阻止冒泡事件的发生-->
<div style="width:200px; height:200px; background:red;" @click="test5">
<div style="width:100px; height:100px; background:blue;" @click.stop="test6"></div>
</div>
<!--阻止默认行为
@click.prevent
-->
<a href="https://www.baidu.com/" @click.prevent="test7">去百度</a>
<h2>3.按键修饰符</h2>
<!--像@keyup.13、@keyup.13这样可以指定在某个按键按下的时候触发对应的方法(keycode和按键名皆可,仅有少数按键有按键名)-->
<input type="text" @keyup.13="test8">
<input type="text" @keyup.enter="test8">
</div>
<script type="text/javascript" src="../**/vue.js"></script>
<script type="text/javascript">
new Vue({
el:'#example',
data:{
test1(){
alert('test1')
},
test2(msg){
alert(msg)
},
test3(event){
alert(event.target.innerHTML)
},
test5(){
slert('out')
},
test6(){
//event.stopPropagation()
alert('inner')
},
test7(){
//event.preventDefault()
alert('点击了')
},
test8(event){
alert(event.target.value)
}
}
})
</script>
</body>
</html>
Episode10:表单数据的自动收集
使用v-model(双向数据绑定)自动收集数据
text/textarea
checkbox
radio
select
下面直接附上示例代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>episode10_表单数据的自动收集</title>
</head>
<body>
<div id="demo">
<form action="/xxx">
<span>用户名:</span>
<input type="text" v-model="username"></br>
<span>密码:</span>
<inuput type="password" v-model="password"></br>
<span>性别:</span>
<input type="radio" id="female" vlaue="女" v-model="sex">
<label for="female">女</label>
<input type="radio" id="male" value="男" v-model="sex">
<label for="male">男</label>
<span>爱好:</span>
<input type="radio" id="basket" v-model="likes">
<label for="basket">篮球</label>
<input type="radio" id="socker" v-model="likes">
<label for="socker">足球</label>
<input type="radio" id="pingpang" v-model="likes">
<label for="pingpang">乒乓球</label><br>
<span>城市:</span>
<select v-model="cityId">
<option value="">未选择</option>
<option :vlaue="city.id" v-for="(city,index) in allCitys">{{city.name}}</option>
</select><br>
<span>介绍:</span>
<textarea rows="10" v-model="desc"></textarea><br><br>
<input type="submit" value="注册" @click.prevent="handleSubmit"><!--@click.prevent阻止提交按钮的默认提交行为-->
</form>
</div>
<script type="text/javascript" src="../**/vue.js"></script>
<script type="text/javascript">
new Vue({
data:{
el:'#demo',
username:'',
password:'',
sex:'男', //默认选中性别为男
likes:['socker'], //默认选中爱好为足球
allCitys:[{id:1,name:'BJ'},{id:2,name:'SH'},{id:3,name:'GD'}],
cityId:'3',
desc:''
},
methods:{
handleSubmit(){
console.log(this.username,this.password,this.sex,this.likes,this.cityId,this.desc)
}
}
})
</script>
</body>
</html>
Episode11:生命周期(钩子函数)
一、vue对象的生命周期的3个阶段:
-
初始化显示
-
beforeCreate()
-
created()
-
beforeMount()
-
mounted()
-
-
更新显示:this.xxx = value
-
beforeUpdate()
-
updated()
-
-
销毁vue实例:vm.$destroy()
-
beforeDestroy()
-
destroyed()
-
二、常用的生命周期函数:
created()/mounted():发送ajax请求,如:启动定时器异步任务
beforeDestroy():做收尾工作,如:清除定时器
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>episode11_生命周期</title>
</head>
<body>
<div id="test">
<button @click="destroyVM">destroy</button>
<p v-show="isShow">锋哥最棒~</p>
</div>
<script type="text/javascript" src="../**/vue.js"></script>
<script type="text/javascript">
new Vue({
el:'#test',
data:{
isShow:true
},
//1.初始阶段
beforeCreate(){
console.log('beforeCreate()')
},
created(){
console.log('created()')
},
beforeMount(){
console.log('beforeMount()')
},
mounted(){ //初始化显示后立即调用1次
this.intervalId = setInterval(()=>{
console.log('---------')
this.isShow = !this.isShow //更新数据
},1000)
},
//2.更新阶段
beforeUpdate(){
console.log('beforeUpdate()')
},
updated(){
console.log('updated()')
},
//3.死亡阶段
beforeDestroy(){ //死亡之前调用1次
console.log('beforeDestroy')
//消除定时器
clearInterval(this.intervalId)
},
destroyed(){
conole.log('destroyed')
},
methods:{
destroyVM(){
//干掉VM
this.$destroy()
}
}
})
</script>
</body>
</html>
Episode12:Vue过滤器
下面示例代码通过过滤器实现将输入的字符串转化为特定格式的日期时间:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>episode11_生命周期</title>
</head>
<body>
<div id="test">
<h2>显示格式化日期时间</h2>
<p>{{date}}</p>
<p>完整版:{{date | dataString}}</p>
<p>年月日:{{date | dataString('YYYY-MM-DD')}}</p>
<p>时分秒:{{date | dataString('HH:mm:ss')}}</p>
</div>
<script type="text/javascript" src="../**/vue.js"></script>
<script type="text/javascript" src="https://cdn.bootcss.com/moment.js/2.21.0/moment.js"> </script>
//引入moment.js库cdn
</script>
//自定义过滤
Vue.filter('dateString',function(value,format){
return moment(value).format(format || 'YYYY-MM-DD HH:mm:ss')
})
new Vue({
el:'#test',
data:new Date()
})
</script>
</body>
</html>
Epidode13:Vue中Ajax请求
vue项目中常用2个Ajax库
-
vue-resource
vue插件,非官方库,在vue 1.x中使用广泛
-
axios
通用的ajax请求库,官方推荐,在vue 2.x中使用广泛
以下附上示例代码展示两种库的使用方法(在App.vue中):
<!--BELOW is App.vue-->
<template>
<div>
<div v-if="!repoUrl">loading...</div>
<div v-else>The most star repo is<a :href="repoUrl">{{repoName}}</a></div>
</div>
</template>
<script>
import axios from 'axios'
export default{
data(){
return{
repoUrl:'',
repoName:''
}
},
mounted(){
//在初始化时请求数据
const url = `https://api.github.com/search/repositories?q=v&sort=stars`
this.$http.get(url).then(
response =>{
//成功得到数据
const result = response.data
//得到最受欢迎的repo
const mostRepo = result.items[0]
this.repoUrl = mostRepo.html_url
this.repoName = mostRepo.name
},
response =>{
alert('vue-resource请求失败')
}
)
//使用axios发送ajax请求
axios.get(url).then(response =>{
//成功得到数据
const result = response.data
//得到最受欢迎的repo
const mostRepo = result.items[0]
this.repoUrl = mostRepo.html_url
this.repoName = mostRepo.name
}).catch(error =>{
alert('axios请求失败')
})
}
}
</script>
<style>
</style>
以下是对应的main.js:
import Vue from 'vue'
import App from './App.vue'
import VueResource from 'vue-resource'
//声明使用插件
Vue.use(VueResource)//内部会给vm对象和组件对象添加一个属性:$http
new Vue({
el:'#app', //index.html中div对应的id
components:{App},
template:'<App/>'
})