1.数据绑定
单向数据绑定(数据只能从data流向页面)
v-bind 把运行结果绑定
<div id="root">
<a v-bind:href="url">点击去{{name}}</a>
</div>
<script>
Vue.config.productionTip = false //关闭vue启动时是生产提示
new Vue({
el:'#root',
data:{
name:"留言板",
url:"http://api.hh2022.cn"
}
})
</script>
双向数据绑定 (数据不仅可以从data流向页面,还可以从页面流向data)
v-model 注意(和v-bind效果差不多但是只能用于输入类元素)
<div id="root">
单向数据绑定:<input type="text" v-bind:value="name"><br>
双向数据绑定:<input type="text" v-model="name"><br>
<!-- 以下代码是错误的,v-model只能用于表单元素(输入类元素)上 -->
<h2 v-model:x="name">你好啊</h2>
</div>
<script>
Vue.config.productionTip = false //关闭vue启动时是生产提示
new Vue({
el:'#root',
data:{
name:"留言板",
url:"http://api.hh2022.cn"
}
})
</script>
2.其他写法
Vue的el挂载方式(第二种)
<script>
Vue.config.productionTip = false //关闭vue启动时是生产提示
const v = new Vue({
// el:'#root',
data:{
name:"留言板",
url:"http://api.hh2022.cn"
}
})
console.log(v)
//第二种挂载方式
v.$mount("#root")
</script>
Vue的data挂载方式(函数式)
<script>
const v = new Vue({
// el:'#root',
// data:{
// name:"留言板",
// url:"http://api.hh2022.cn"
// }
data:function(){
return{
name:"留言板"
}
}
})
console.log(v)
//第二种挂载方式
v.$mount("#root")
</script>
3.认识MVVM
回顾 Object.defineProperty
<script>
let person = {
name:"张三",
sex:"男",
}
Object.defineProperty(person,"age",{
value:18
enumerable:true //控制属性是否可以被枚举,默认值为false
writable:true, //控制属性是否可以被修改,默认值为false
configurable:true, //控制属性是否可以被删除,默认值为false
})
console.log(person)
</script>
如果 enumerable为false 那么 age属性是不可枚举的(不可以被遍历)
4.数据代理
数据代理就是提供一个对象对另外一个对象中的属性的操作(读/写)
<script>
let obj = {x:100}
let obj2 = {y:200}
Object.defineProperty(obj2,"x",{
//getter 读取数据时触发,给obj2的x赋值为obj的x
get:function(){
return obj.x
},
//setter 如果set调用了,代表有人想更改obj2的x
set(value){
obj.x = value;
}
})
</script>
vue中的数据代理
5.事件绑定
<div id="root">
<h2>{{name}}</h2>
<button @click="showInfo1">点击1</button>
<button @click="showInfo2($event,666)">点击2</button>
</div>
<script>
Vue.config.productionTip = false //关闭vue启动时是生产提示
const vm = new Vue({
el:"#root",
data:{
name:"SuperChen"
},
methods:{
showInfo1(event){
alert("你好!")
},
showInfo2(event,number){
alert(number)
}
}
})
</script>
阻止默认事件
<div id="root">
<h2>{{name}}</h2>
<a href="http://api.hh2022.cn" @click.prevent="showInfo"></a>
</div>
<script>
Vue.config.productionTip = false //关闭vue启动时是生产提示
const vm = new Vue({
el:"#root",
data:{
name:"SuperChen"
},
methods:{
showInfo(event){
alert("你好!")
},
}
})
</script>
.stop:防止事件冒泡,等同于JavaScript中的event.stopPropagation()
.prevent:防止执行预设的行为,等同于JavaScript中的event.preventDefault()
.capture:捕获冒泡
.self:将事件绑定到自身,只有自身才能触发
.once:只触发一次
.passive:不阻止事件的默认行为
键盘事件(回车触发)
<div id="root">
<h2>{{name}}</h2>
<input type="text" placeholder="按下回车提示输入" @keyup.enter="showInfo">
</div>
<script>
Vue.config.productionTip = false //关闭vue启动时是生产提示
const vm = new Vue({
el:"#root",
data:{
name:"SuperChen"
},
methods:{
showInfo(event){
console.log(event.target.value)
},
}
})
</script>
回车 => enter
删除 => delete(捕获“删除”和“退格”键)
退出 => esc
空格 => space
换行 => tab(必须配合keydown使用)
上 => up
下 => down
左 => left
右 => right
返回值,和事件调用注意事项
<div id="root">
姓:<input type="text" v-model="firstName"> <br><br>
名:<input type="text" v-model="lastName"><br><br>
姓名:<span>{{fullName}}</span>
</div>
<script>
Vue.config.productionTip = false //关闭vue启动时是生产提示
const vm = new Vue({
el:"#root",
data:{
firstName:"张",
lastName:"三"
},
methods:{
fullName(){
return "小猪佩奇"
},
}
})
</script>
运行结果:
直接显示了函数,这显然不是我们想要的(我们想要的是返回值)
<div id="root">
姓:<input type="text" v-model="firstName"> <br><br>
名:<input type="text" v-model="lastName"><br><br>
姓名:<span>{{fullName()}}</span>
</div>
<script>
Vue.config.productionTip = false //关闭vue启动时是生产提示
const vm = new Vue({
el:"#root",
data:{
firstName:"张",
lastName:"三"
},
methods:{
fullName(){
return "小猪佩奇"
},
}
})
</script>
现在就显示了返回值
6.计算属性
<div id="root">
姓:<input type="text" v-model="firstName"> <br><br>
名:<input type="text" v-model="lastName"><br><br>
姓名:<span>{{fullName}}</span>
</div>
<script>
Vue.config.productionTip = false //关闭vue启动时是生产提示
const vm = new Vue({
el:"#root",
data:{
firstName:"张",
lastName:"三"
},
//与methods相比
//computed内部有缓存机制(高效)调试方便
computed:{
fullName:{
//初次读取时set只会调用一次
get(){
console.log("get被调用了")
return this.firstName+"-"+this.lastName
},
set(value){
const arr = value.split("-")
this.firstName = arr[0]
this.lastName = arr[1]
}
},
}
})
</script>
get和set都是被vue管理的函数
简写形式(确定只读不改,才可以使用简写)
<div id="root">
姓:<input type="text" v-model="firstName"> <br><br>
名:<input type="text" v-model="lastName"><br><br>
姓名:<span>{{fullName}}</span>
</div>
<script>
Vue.config.productionTip = false //关闭vue启动时是生产提示
const vm = new Vue({
el:"#root",
data:{
firstName:"张",
lastName:"三"
},
//与methods相比
//computed内部有缓存机制(高效)调试方便
//简写
computed:{
fullName(){
return this.firstName+"-"+this.lastName
}
}
})
</script>
与上面效果相同
7.三元表达式
<div id="root">
<h2>今天天气很{{info}}</h2>
<button @click="changeWeater">切换天气</button>
</div>
<script>
Vue.config.productionTip = false //关闭vue启动时是生产提示
const vm = new Vue({
el:"#root",
data:{
isHost:true
},
computed:{
info(){
return this.isHost ? "炎热":"凉爽"
}
},
methods:{
changeWeater(){
this.isHost = !this.isHost
}
}
})
</script>
8.监视属性
<div id="root">
<h2>今天天气很{{info}}</h2>
<button @click="changeWeater">切换天气</button>
</div>
<script>
Vue.config.productionTip = false //关闭vue启动时是生产提示
const vm = new Vue({
el:"#root",
data:{
isHot:true
},
computed:{
info(){
return this.isHot ? "炎热":"凉爽"
}
},
methods:{
changeWeater(){
this.isHot = !this.isHot
},
//监视属性
watch:{
isHot:{
deep:true, //深度监视
//handler在isHost发送变化时调用
handler(newValue,oldValue){
console.log("新值"+newValue+"-"+"旧值:"+oldValue)
}
}
}
}
})
</script>
简写
<div id="root">
<h2>今天天气很{{info}}</h2>
<button @click="changeWeater">切换天气</button>
</div>
<script>
Vue.config.productionTip = false //关闭vue启动时是生产提示
const vm = new Vue({
el:"#root",
data:{
isHot:true
},
computed:{
info(){
return this.isHot ? "炎热":"凉爽"
}
},
methods:{
changeWeater(){
this.isHot = !this.isHot
},
// //监视属性
// watch:{
// isHot:{
// deep:true,
// //handler在isHost发送变化时调用
// handler(newValue,oldValue){
// console.log("新值"+newValue+"-"+"旧值:"+oldValue)
// }
// }
// }
}
})
//监视属性简写
vm.$watch("isHot",(newValue,oldValue) => {
console.log("isHot被修改了",newValue,oldValue,this)
})
</script>
8.绑定style样式
<div id="root">
<div class="basic" :style="styleObj">{{name}}</div>
</div>
<script>
Vue.config.productionTip = false //关闭vue启动时是生产提示
const vm = new Vue({
el:"#root",
data:{
name:'sueprchen',
styleObj:{
fontSize:'40px',
color:'red'
}
},
})
</script>
9.条件渲染
<div id="root">
<h1 v-show="n === 1">你好</h1>
</div>
<script>
Vue.config.productionTip = false //关闭vue启动时是生产提示
const vm = new Vue({
el:"#root",
data:{
name:'sueprchen',
n:1
},
})
</script>
当 n === 1成立时 h1标签显示
小案例
当n的值是1 显示vue 当n的值是2是显示React
<div id="root">
<h2>当前n的值是:{{n}}</h2>
<button @click="n++">点我n+1</button>
<div v-if="n === 1">Vue</div>
<div v-else-if="n === 1">React</div>
<div v-else-if="n === 2">嘿嘿没了</div>
</div>
<script>
Vue.config.productionTip = false //关闭vue启动时是生产提示
const vm = new Vue({
el:"#root",
data:{
name:'sueprchen',
n:1
},
})
</script>
分析:如果两个条件都成立会显示哪个? 答案:显示 嘿嘿没了
那想要显示成立条件的应该如何写
<div id="root">
<h2>当前n的值是:{{n}}</h2>
<button @click="n++">点我n+1</button>
<div v-if="n === 1">Vue</div>
<div v-if="n === 1">React</div>
<div v-if="n === 2">嘿嘿没了</div>
</div>
<script>
Vue.config.productionTip = false //关闭vue启动时是生产提示
const vm = new Vue({
el:"#root",
data:{
name:'sueprchen',
n:1
},
})
</script>
10.列表渲染遍历
<div id="root">
<!-- 遍历数组 -->
<h2>{{name}}</h2>
<ul>
<!-- index是索引 -->
<li v-for="(p,index) in persons" :key="index">
{{p.name}}-{{p.age}}-{{index}}
</li>
<!-- 遍历对象 -->
<h2>汽车信息</h2>
<li v-for="(value,k) of car" :key="k">
{{value}}-{{k}}
</li>
</ul>
</div>
<script>
Vue.config.productionTip = false //关闭vue启动时是生产提示
const vm = new Vue({
el:"#root",
data:{
name:'人员列表',
persons:[
{id:'001',name:'张三',age:18},
{id:'002',name:'李四',age:19},
{id:'001',name:'王五',age:20}
],
car:{
name:'奥迪A8',
price:'70万',
color:'黑色'
}
},
})
</script>
列表添加元素
<div id="root">
<!-- 遍历数组 -->
<h2>{{name}}</h2>
<!-- click.once 设置按钮只能按一次 -->
<button @click.once="add">添加一个老刘</button>
<ul>
<!-- index是索引 -->
<li v-for="(p,index) in persons" :key="index">
{{p.name}}-{{p.age}}-{{index}}
</li>
</ul>
</div>
<script>
Vue.config.productionTip = false //关闭vue启动时是生产提示
const vm = new Vue({
el:"#root",
data:{
name:'人员列表',
persons:[
{id:'001',name:'张三',age:18},
{id:'002',name:'李四',age:19},
{id:'003',name:'王五',age:20}
],
},
methods:{
add(){
const p = {id:'004',name:"老刘",age:40}
//向列表头部添加元素
this.persons.unshift(p)
}
}
})
</script>
11.列表过滤
使用watch
<div id="root">
<!-- 遍历数组 -->
<h2>{{name}}</h2>
<input type="text" placeholder="请输入名字" v-model="keyWord">
<ul>
<!-- index是索引 -->
<li v-for="(p,index) in filPerons" :key="index">
{{p.name}}-{{p.age}}-{{index}}
</li>
</ul>
</div>
<script>
Vue.config.productionTip = false //关闭vue启动时是生产提示
const vm = new Vue({
el:"#root",
data:{
keyWord:'',
name:'人员列表',
persons:[
{id:'001',name:'张三',age:18,sex:'女'},
{id:'002',name:'李四',age:19,sex:'男'},
{id:'003',name:'王五',age:20,sex:'男'}
],
filPerons:[],
},
watch:{
keyWord:{
//先调用一次
immediate:true,
handler(val){
//列表过滤
this.filPerons = this.persons.filter((p) =>{
return p.name.indexOf(val) !== -1
})
}
}
}
})
</script>
使用computed
<div id="root">
<!-- 遍历数组 -->
<h2>{{name}}</h2>
<input type="text" placeholder="请输入名字" v-model="keyWord">
<!-- click.once 设置按钮只能按一次 -->
<!-- <button @click.once="add">添加一个老刘</button> -->
<ul>
<!-- index是索引 -->
<li v-for="(p,index) in filPerons" :key="index">
{{p.name}}-{{p.age}}-{{index}}
</li>
</ul>
</div>
<script>
Vue.config.productionTip = false //关闭vue启动时是生产提示
const vm = new Vue({
el:"#root",
data:{
keyWord:'',
name:'人员列表',
persons:[
{id:'001',name:'张三',age:18,sex:'女'},
{id:'002',name:'李四',age:19,sex:'男'},
{id:'003',name:'王五',age:20,sex:'男'}
],
},
computed:{
filPerons(){
return this.persons.filter((p) => {
return p.name.indexOf(this.keyWord) !== -1
})
}
}
})
</script>
当watch和computed都可以实现的时候,优先选择computed
列表排序
<div id="root">
<!-- 遍历数组 -->
<h2>{{name}}</h2>
<input type="text" placeholder="请输入名字" v-model="keyWord">
<button @click="sortType = 2">年龄升序</button>
<button @click="sortType = 1">年龄降序</button>
<button @click="sortType = 0">原顺序</button>
<ul>
<!-- index是索引 -->
<li v-for="(p,index) in filPerons" :key="index">
{{p.name}}-{{p.age}}-{{index}}
</li>
</ul>
</div>
<script>
Vue.config.productionTip = false //关闭vue启动时是生产提示
const vm = new Vue({
el:"#root",
data:{
keyWord:'',
sortType:0, //0代表原顺序 1代表降序 2代表升序
name:'人员列表',
persons:[
{id:'001',name:'张三',age:20,sex:'女'},
{id:'002',name:'李四',age:11,sex:'男'},
{id:'003',name:'王五',age:12,sex:'男'},
{id:'004',name:'老六',age:12,sex:'男'},
{id:'005',name:'老八',age:19,sex:'男'},
{id:'006',name:'刀哥',age:51,sex:'男'},
{id:'007',name:'虎哥',age:30,sex:'男'},
{id:'008',name:'坤坤',age:22,sex:'男'}
],
},
computed:{
filPerons(){
const arr = this.persons.filter((p) => {
return p.name.indexOf(this.keyWord) !== -1
})
//判断是否需要排序
if(this.sortType){
//会收到前后两个数据
arr.sort((p1,p2) =>{
return this.sortType === 1 ? p2.age-p1.age : p1.age-p2.age
})
}
//返回
return arr;
}
}
})
</script>
降序就是 p2-p1 升序就是p1-p2