一、计算属性
1.1计算属性的本质
-
fullname:{set(),get()}
1.2计算属性和methods对比
-
计算属性在多次使用时,只会调用一次
-
它是有缓存的
-
methods多次使用时需要多次调用
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<h2>{{getFullName()}}</h2>
<h2>{{getFullName()}}</h2>
<h2>{{getFullName()}}</h2>
<h2>{{fullName}}</h2>
<h2>{{fullName}}</h2>
<h2>{{fullName}}</h2>
</div>
<script src="../js/vue.js"></script>
<script>
const app=new Vue({
el:'#app',
data:{
firstName:'Kobe',
lastName:'Bryant'
},
//根据次数决定后台输出次数
methods:{
getFullName:function () {
console.log("methods");
return this.firstName+" "+this.lastName;
}
},
//后台输出一次效果较好
computed:{
fullName:function () {
console.log("computed");
return this.firstName+" "+this.lastName;
}
}
})
</script>
</body>
</html>
从后台数据我们也可以看到methods和computed的被调用次数。
二、事件监听
2.1事件监听基本使用
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
//以计数为例
<div id="app">
<h2>{{counter}}</h2>
<!-- <button v-on:click="increment">+</button>-->
<!-- <button v-on:click="decrement">-</button>-->
//v-on属性绑定可直接用@来代替
<button @click="increment">+</button>
<button @click="decrement">-</button>
</div>
<script src="../js/vue.js"></script>
<script>
const app=new Vue({
el:'#app',
data:{
counter:0,//定义初始化数据
},
methods:{
increment(){
this.counter++;
},
decrement(){
this.counter--;
}
}
})
</script>
</body>
</html>
2.2参数问题
-
btnClick
-
btnClick(event)
-
btnClick(abc,event) -> $event
2.3修饰符
-
stop
-
prevent
-
.enter
-
.once
-
.native
三、条件判断
3.1 v-if/v-else-if/v-else
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
//第一种方法:采用js的v-if/v-else-if/v-else
<h2 v-if="score>=90">优秀</h2>
<h2 v-else-if="score>=80">良好</h2>
<h2 v-else-if="score>=60">及格</h2>
<h2 v-else>不及格</h2>
<h1>{{result}}</h1>
</div>
<script src="../js/vue.js"></script>
<script>
const app=new Vue({
el:'#app',
data:{
score:82
},
//第二种方法:调用computed属性,利用基本的if/else if/else方法
computed:{
result(){
let showMessage='';
if(this.score>=90){
showMessage="优秀";
}else if(this.score>=80){
showMessage='良好';
}else if(this.score>=60){
showMessage='及格';
}else{
showMessage='不及格';
}
return showMessage;
}
}
})
</script>
</body>
</html>
3.2 登录小案例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<span v-if="isUser">
<label for="userName">用户账号</label>
<!-- input复用问题需要唯一标识key来确认,否则上级输入的信息切换后信息不改变 -->
<input type="text" id="userName" placeholder="用户账号" key="userName"/>
</span>
<span v-else>
<label for="userEmail">用户邮箱</label>
<input type="text" id="userEmail" placeholder="用户邮箱" key="UserEmail"/>
</span>
<button @click="isUser=!isUser">切换类型</button>
</div>
<script src="../js/vue.js"></script>
<script>
const app=new Vue({
el:'#app',
data:{
isUser:true,
}
})
</script>
</body>
</html>
3.3 v-show
-
v-show和v-if的区别
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<!-- 当条件为false时,v-if就不存在dom中-->
<h2 v-if="isShow" id="aaa">{{message}}</h2>
<!-- 当条件为false,就会给v-show添加一个行内样式,其行内样式为none-->
<h2 v-show="isShow" id="bbb">{{message}}</h2>
</div>
<script src="../js/vue.js"></script>
<script>
const app=new Vue({
el:'#app',
data:{
message:"hello",
isShow:false
}
})
</script>
</body>
</html>
四、循环遍历
4.1遍历数组
-
使用v-for遍历数组
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<ul>
<!-- 在遍历中没有使用索引值index-->
<li v-for="item in names">{{item}}</li>
</ul>
<ul>
<!-- 在遍历过程中使用下标值index-->
<li v-for="(item,index) in names">{{index+1}}.{{item}}</li>
</ul>
</div>
<script src="../js/vue.js"></script>
<script>
const app=new Vue({
el:'#app',
data:{
names:["kobe","james","why","jetty"]
}
})
</script>
</body>
</html>
4.2遍历对象
-
value
-
value,key
-
value,key,index
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<ul>
<!-- <li>{{info.name}}</li>-->
<!-- <li>{{info.age}}</li>-->
<!-- <li>{{info.height}}</li>-->
<!-- 1、在遍历时,如果只是获取一个值,那么获取到的就是value-->
<li v-for="item in info">{{item}}</li>
</ul>
<!-- 2、在获取key和value时,格式是:(value,key)-->
<ul>
<li v-for="(value,key) in info">{{value}}-{{key}}</li>
</ul>
<!-- 3、在获取key和value和index时,格式是:(value,key,index)-->
<ul>
<li v-for="(value,key,index) in info">{{index+1}}-{{value}}-{{key}}</li>
</ul>
</div>
<script src="../js/vue.js"></script>
<script>
const app=new Vue({
el:'#app',
data:{
info:{
name:'james',
age:18,
height:188
}
}
})
</script>
</body>
</html>
4.3数组中哪些方式是响应式的
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<ul>
<li v-for="item in letters" >{{item}}</li>
</ul>
<button @click="btnClick">点击一下</button>
</div>
<script src="../js/vue.js"></script>
<script>
const app=new Vue({
el:'#app',
data:{
letters:['a','b','c','d','e']
},
methods:{
btnClick(){
// 1、push方法 在数组的最后面添加元素
// app.letters.push('aaa');
// this.letters.push('aaa','bbb','ccc');
// pop 将会从后面往前删除元素
// this.letters.pop();
// shift 将元素从前往后删除
// this.letters.shift();
// unshift 在数组最前面添加元素
// this.letters.unshift('h');
// this.letters.unshift('aaa','bbb','ccc');
// reverse 将顺序颠倒
// this.letters.reverse();
// splice 删除元素、替换元素、插入元素 splice(1,3,'l','i','j')表示在1到3的元素用后面的元素替代
// this.letters.splice(1,3,'l','i','j');
// sort
// this.letters.sort();
// 2、通过索引值修改元素
// this.letters.splice(2,0,'bbb');
// this.letters[0]='bbb'
}
}
});
// function sum(num1,num2) {
// return num1+num2;
// };
// function sum(num1,num2,num3) {
// return num1+num2+num3;
// };
// function sum(...num){
// console.log(num);
// }
// sum(10,20);
</script>
</body>
</html>
4.4作业案例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<ul>
<li v-for="item in letters" >{{item}}</li>
</ul>
<button @click="btnClick">点击一下</button>
</div>
<script src="../js/vue.js"></script>
<script>
const app=new Vue({
el:'#app',
data:{
letters:['a','b','c','d','e']
},
methods:{
btnClick(){
// 1、push方法 在数组的最后面添加元素
// app.letters.push('aaa');
// this.letters.push('aaa','bbb','ccc');
// pop 将会从后面往前删除元素
// this.letters.pop();
// shift 将元素从前往后删除
// this.letters.shift();
// unshift 在数组最前面添加元素
// this.letters.unshift('h');
// this.letters.unshift('aaa','bbb','ccc');
// reverse 将顺序颠倒
// this.letters.reverse();
// splice 删除元素、替换元素、插入元素 splice(1,3,'l','i','j')表示在1到3的元素用后面的元素替代
// this.letters.splice(1,3,'l','i','j');
// sort
// this.letters.sort();
// 2、通过索引值修改元素
// this.letters.splice(2,0,'bbb');
// this.letters[0]='bbb'
}
}
});
// function sum(num1,num2) {
// return num1+num2;
// };
// function sum(num1,num2,num3) {
// return num1+num2+num3;
// };
// function sum(...num){
// console.log(num);
// }
// sum(10,20);
</script>
</body>
</html>
五、书籍案例
六、v-model的使用
6.1 v-model的基本使用
-
v-model => v-bind: value v-on: input
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<!-- <input type="text" :value="message" @input="valueChange"/>-->
<input type="text" :value="message" @input="message=$event.target.value"/>
<h2>{{message}}</h2>
</div>
<!--v-model和message双向绑定-->
<script src="../js/vue.js"></script>
<script>
const app=new Vue({
el:'#app',
data:{
message:"hello"
},
methods:{
// 事件
valueChange(event){
this.message=event.target.value;
}
}
})
</script>
</body>
</html>
6.2 v-model和radio/checkbox/select
v-model结合radio
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<label for="male">
<input type="radio" id="male" name="sex" value="男" v-model="sex"/>男
</label>
<label for="female">
<input type="radio" id="female" name="sex" value="女" v-model="sex"/>女
</label>
<h2>你选择的性别是:{{sex}}</h2>
</div>
<script src="../js/vue.js"></script>
<script>
const app=new Vue({
el:'#app',
data:{
//显示默认值
sex:'男'
}
})
</script>
</body>
</html>
v-model结合checkbox
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<!-- 1、checkbox单选框-->
<!-- <label for="protocol">-->
<!-- <input type="checkbox" id="protocol" v-model="isProtocol"/>同意协议-->
<!-- </label>-->
<!-- <h2>你选择的是:{{isProtocol}}</h2>-->
<!-- 2、checkbox多选框-->
<label for="">
<input type="checkbox" value="篮球" v-model="hobbies"/>篮球
<input type="checkbox" value="足球" v-model="hobbies"/>足球
<input type="checkbox" value="乒乓球" v-model="hobbies"/>乒乓球
<input type="checkbox" value="羽毛球" v-model="hobbies"/>羽毛球
</label>
<h2>你的爱好是:{{hobbies}}</h2>
</div>
<script src="../js/vue.js"></script>
<script>
const app=new Vue({
el:'#app',
data:{
message:"hello",
isProtocol:false,//单选框
hobbies:[]//多选框,用数组存储
}
})
</script>
</body>
</html>
v-model结合select
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<!-- 1、选择一个-->
<!-- <select name="abc" v-model="fruit">-->
<!-- <option value="苹果" >苹果</option>-->
<!-- <option value="香蕉">香蕉</option>-->
<!-- <option value="橘子" >橘子</option>-->
<!-- <option value="橙子" >橙子</option>-->
<!-- <option value="车厘子" >车厘子</option>-->
<!-- </select>-->
<!-- <h2>你选择的水果是:{{fruit}}</h2>-->
<!-- 2、选择多个 multiple的属性作用-->
<select name="abc" v-model="fruits" multiple>
<option value="苹果" >苹果</option>
<option value="香蕉">香蕉</option>
<option value="橘子" >橘子</option>
<option value="橙子" >橙子</option>
<option value="车厘子" >车厘子</option>
</select>
<h2>你选择的水果是:{{fruits}}</h2>
</div>
<script src="../js/vue.js"></script>
<script>
const app=new Vue({
el:'#app',
data:{
fruit:'香蕉',
fruits:[]
}
})
</script>
</body>
</html>
6.3修饰符
-
lazy
-
number
-
trim
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<!-- 1、修饰符:lazy-->
<!-- 只有v-model每次都要随时更新,但是加了lazy属性就可以等你输完,按enter键就完成了-->
<input type="text" v-model.lazy="message"/>
<h2>{{message}}</h2>
<!-- 2、修饰符:number-->
<!-- number可以将其类型转换为number类型-->
<input type="text" v-model.number="age"/>
<h2>{{age}}--{{typeof age}}</h2>
<!-- 3、修饰符:trim-->
<input type="text" v-model="name"/>
<h2>您输入的名字是:{{name}}</h2>
</div>
<script src="../js/vue.js"></script>
<script>
const app=new Vue({
el:'#app',
data:{
message:"hello",
age:0,
name:'小花'
}
})
</script>
</body>
</html>
七、组件化开发
7.1认识组件化
组件化就是将一个页面拆分成一个个小的功能模块,每个功能模块完成属于自己这部分独立的功能,使得整个页面的管理和维护变得非常容易。
7.2组件的基本使用
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<my-cpn>
<h2>我是标题</h2>
<p>我是内容,哈哈哈哈</p>
<p>我是内容,嘿嘿嘿嘿</p>
</my-cpn>
<div id="app">
<my-cpn></my-cpn>
<my-cpn></my-cpn>
<div>
<div>
<my-cpn></my-cpn>
</div>
</div>
</div>
<script src="../js/vue.js"></script>
<script>
//ES6
// const str='abc'+
// 'cde';
// getComputedStyle()
// 1、创建组建构造器对象
const cpnC=Vue.extend({
template:
<div>
<h2>我是标题</h2>
<p>我是内容,哈哈哈哈</p>
<p>我是内容,嘿嘿嘿嘿</p>
</div>
});
//2、注册组件
Vue.component('my-cpn',cpnC);
//3、使用组件
const app=new Vue({
el:'#app',
data:{
message:"hello"
}
})
</script>
</body>
</html>
7.3全局组件和局部组件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<cpn></cpn>
<cpn></cpn>
<cpn></cpn>
<cpn></cpn>
</div>
<div id="app2">
<cpn></cpn>
</div>
<script src="../js/vue.js"></script>
<script>
//1、创建组建构造器
const cpnC=Vue.extend({
template:
<div>
<h2>这是第一次使用</h2>
<p>请多多指教</p>
<p>我喜欢日漫</p>
</div>
});
//2、注册组件(全局组件)
Vue.component('cpn',cpnC);
//疑问:怎么注册的组件才是局部组件
//3、
const app=new Vue({
el:'#app',
data:{
message:"hello"
},
components:{
//cpn使用组件时的标签名
cpn:cpnC
}
});
const app2=new Vue({
el:'#app2',
data:{
}
})
</script>
</body>
</html>
7.4父组件和子组件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<cpn1></cpn1>
</div>
<script src="../js/vue.js"></script>
<script>
//1、创建组件构造器(第一个组件)
const cpnC1=Vue.extend({
template:
<div>
<h2>组件一</h2>
<p>嘿嘿</p>
</div>,
});
const cpnC2=Vue.extend({
template:
<div>
<h2>组件二</h2>
<p>哈哈</p>
</div>,
});
const app=new Vue({
el:'#app',
data:{
message:"hello"
},
components:{
cpn1:cpnC1,
cpn2:cpnC2,
}
})
</script>
</body>
</html>
7.5注册的语法糖
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
{{message}}
<cpn1></cpn1>
</div>
<script src="../js/vue.js"></script>
<script>
//全局组件注册的语法糖
//1、创建组件构造器
// const cpnC1=Vue.extend();
//2、注册组件
Vue.component('cpn1',{
template:
<div>
<p>父组件</p>
</div>
});
const app=new Vue({
el:'#app',
data:{
message:"hello"
},
components:{
cpn2:{
template:
<div>
<p>组件二</p>
</div>
}
}
})
</script>
</body>
</html>
7.6模板的分类写法
-
script
-
template
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<cpn></cpn>
</div>
<!--script标签,类型必须是text/x-template-->
<!--<script type="text/x-template" id="cpn">-->
<!-- <div>-->
<!-- <h2>我是标题</h2>-->
<!-- <p>这是内容,哈哈哈哈哈</p>-->
<!-- </div>-->
<!--</script>-->
<!--template标签-->
<template id="cpn">
<div>
<h2>我是标题</h2>
<p>这是内容,哈哈哈哈哈</p>
</div>
</template>
<script src="../js/vue.js"></script>
<script>
//1、注册一个全局组件
Vue.component('cpn',
{
template:'#cpn',
}
);
const app=new Vue({
el:'#app',
data:{
message:"hello"
}
})
</script>
</body>
</html>
7.7数据的存放
-
子组件不能直接访问父组件
-
子组件中有自己的data,而且必须是一个函数
-
为什么必须是一个函数
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<cpn></cpn>
<cpn></cpn>
<cpn></cpn>
</div>
<template id="cpn">
<div>
<h2>当前计数:{{counter}}</h2>
<button @click="increment">+</button>
<button @click="decrement">-</button>
</div>
</template>
<script src="../js/vue.js"></script>
<script>
//1、注册组件
const obj={
counter:0
};
Vue.component('cpn',{
template:'#cpn',
data(){
return obj;
},
methods:{
increment(){
this.counter++;
},
decrement(){
this.counter--;
}
}
});
const app=new Vue({
el:'#app',
data:{
message:"hello"
}
})
</script>
<script>
const obj={
name:'why',
age:18
};
function abc(){
return obj;
}
let obj1=abc();
let obj2=abc();
let obj3=abc();
obj1.name='kobe';
console.log(obj2);
console.log(obj3);
</script>
</body>
</html>
7.8父子组件的通信
-
父传子:props
-
子传父:$emit
父传子
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<cpn :cinfo="info"></cpn>
</div>
<template id="cpn">
<h2>{{cinfo}}</h2>
</template>
<script src="../js/vue.js"></script>
<script>
const cpn={
template:'#cpn',
props:{
cinfo:{
type:Object,
default() {
return {};
}
}
}
};
const app=new Vue({
el:'#app',
data:{
info:{
name:'why',
age:18,
height:188
}
},
components:{
cpn
}
})
</script>
</body>
</html>
子传父
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<cpn @item-click="cpnClick"></cpn>
</div>
<!--子组件模块-->
<template id="cpn">
<div>
<button v-for="item in categories" @click="btnClick(item)">{{item.name}}</button>
</div>
</template>
<script src="../js/vue.js"></script>
<script>
//1、子组件
const cpn={
template:'#cpn',
data(){
return {
categories:[
{id:1,name:'热门推荐'},
{id:2,name:'手机数码'},
{id:3,name:'家用家电'},
{id:4,name:'电脑办公'},
]
}
},
methods:{
btnClick(item){
//发射事件
this.$emit('item-click',item);
}
}
};
//2、父组件
const app=new Vue({
el:'#app',
data:{
message:"hello"
},
components:{
cpn
},
methods:{
cpnClick(){
console.log('cpnClick')
}
}
})
</script>
</body>
</html>