Vue3实现简单的水果购物车
hello world
<!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>
</head>
<body>
<div id="app"><!--Vue的容器-->
<h1>{{msg}}</h1>
</div>
<script src="https://unpkg.com/vue@next"></script><!--用js的方式引入Vue-->
<script>
//Vue.createApp({})创建vue3的实例 vue2是new Vue({})
Vue.createApp({
data(){
return {
msg:"hello world"
}
}
}).mount("#app")//mount挂载dom节点
</script>
</body>
</html>
1.如何操作文本:v-text
<!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>
</head>
<body>
<div id="app">
<!--指令:vue提供的一些特殊的属性v-开头-->
<h1 v-text="msg"></h1><!--跟<h1>{{msg}}</h1>效果一样-->
<!--v-text这个指令让h1标签绑定msg这个变量的文本-->
</div>
<script src="https://unpkg.com/vue@next"></script>
<script>
Vue.createApp({
//选项api(option api)
data(){
return {
msg:"hello world"
}
}
}).mount("#app")
</script>
</body>
</html>
2.如何操作属性:v-bind
将鼠标悬浮在hello world上就显示hello vue3的小框
现在要让title显示Vue里面的数据
<!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>
</head>
<body>
<div id="app">
<!--v-bind是绑定属性的意思,:后面是属性-->
<h1 v-bind:title="tit" v-text="msg"></h1><!--将tit这个变量通过v-bind绑定到h1标签的title属性上-->
</div>
<script src="https://unpkg.com/vue@next"></script>
<script>
Vue.createApp({
data(){
return {
msg:"hello world",
tit:"hello vue"
}
}
}).mount("#app")
</script>
</body>
</html>
3.如何绑定事件:v-on
<!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>
</head>
<body>
<div id="app">
<h1
v-bind:title="tit"
v-text="msg"
v-on:click="showData"
><!--v-on绑定事件,showData是个函数-->
</h1>
</div>
<script src="https://unpkg.com/vue@next"></script>
<script>
Vue.createApp({
data(){
return {
msg:"hello world",
tit:"hello vue"
}
},
methods:{//click事件的函数
showData(){
alert("hello vue3");
}
}
}).mount("#app")
</script>
</body>
</html>
实现计数器功能
<!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>
</head>
<body>
<div id="app">
<button @click="decrease">-</button><!--v-on:click简写成@click-->
<span>{{number}}</span>
<button @click="increase">+</button>
</div>
<script src="https://unpkg.com/vue@next"></script>
<script>
Vue.createApp({
data(){
return {
number:0
}
},
methods:{
decrease(){
if(this.number > 0){
this.number--;
}
},
increase(){
this.number++;
}
}
}).mount("#app")
</script>
</body>
</html>
图片切换功能
<!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>
<style>
img{
height: 300px;
}
</style>
</head>
<body>
<div id="app">
<img :src="src" alt=""><!--v-bind:src简写成:src-->
<button @click="changePic(0)">1</button>
<button @click="changePic(1)">2</button>
<button @click="changePic(2)">3</button>
</div>
<script src="https://unpkg.com/vue@next"></script>
<script>
Vue.createApp({
data(){
return {
src:"images/1.jpg",
list:[
"images/1.jpg",
"images/2.jpg",
"images/3.jpg"
]
}
},
methods:{
changePic(i){
this.src = this.list[i];
}
}
}).mount("#app")
</script>
</body>
</html>
渲染列表
优化下上述的图片切换
<!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>
<style>
img{
height: 300px;
}
</style>
</head>
<body>
<div id="app">
<img :src="src" alt=""><!--v-bind:src简写成:src-->
<button
v-for="item,index in list"
@click="changePic(index)">
{{index+1}}
</button>
<!--item是元素 index是索引
item in list表示数组中的元素,即list中的3张图片路径,item会使每个数组的元素都拥有一个按钮,即页面会出现3个按钮
而index负责给按钮命名{{index+1}},123,以及给点击对应的按钮设置参数changePic(index)
-->
</div>
<script src="https://unpkg.com/vue@next"></script>
<script>
Vue.createApp({
data(){
return {
src:"images/1.jpg",
list:[
"images/1.jpg",
"images/2.jpg",
"images/3.jpg"
]
}
},
methods:{
changePic(i){
this.src = this.list[i];
}
}
}).mount("#app")
</script>
</body>
</html>
好处在于如果给数组添加图片路径,button那里会自动添加按钮,不用额外去写button
表单提交时阻止默认行为
一般的提交表单会刷新页面
<!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>
</head>
<body>
<div id="app">
<!--绑定表单提交的事件是@submit-->
<form @submit="post">
<input type="text">
<button>提交表单</button>
</form>
</div>
<script src="https://unpkg.com/vue@next"></script>
<script>
Vue.createApp({
methods:{
post(){
console.log("hello")
}
}
}).mount("#app")
</script>
</body>
</html>
点击提交表单,hello会一闪而逝,因为提交表单后会刷新页面
要阻止提交表单会刷新页面的默认行为
<div id="app">
<form @submit.prevent="post"><!--submit后面加个事件修饰符prevent-->
<input type="text">
<button>提交表单</button>
</form>
</div>
<script src="https://unpkg.com/vue@next"></script>
<script>
Vue.createApp({
methods:{
post(){
console.log("hello")
}
}
}).mount("#app")
</script>
现在不会刷新了
数据的双向绑定
要使表单里输入什么就提交什么,就要用到数据的双向绑定
<!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>
</head>
<body>
<div id="app">
<h1>{{msg}}</h1><!--只要有一个地方的msg发生改变,其他的msg也会发生改变,这就是双向绑定的特点-->
<form @submit.prevent="post">
<input type="text" v-model="msg"><!--用v-model绑定msg这个变量-->
<button>提交表单</button>
</form>
</div>
<script src="https://unpkg.com/vue@next"></script>
<script>
Vue.createApp({
data(){
return{
msg:"hello"
}
},
methods:{
post(){
console.log("hello")
}
}
}).mount("#app")
</script>
</body>
</html>
往文本框中输入字符,h1标签也会跟着变
把post方法改下就能打印文本框的数据了
<div id="app">
<h1>{{msg}}</h1>
<form @submit.prevent="post">
<input type="text" v-model="msg">
<button>提交表单</button>
</form>
</div>
<script src="https://unpkg.com/vue@next"></script>
<script>
Vue.createApp({
data(){
return{
msg:"hello"
}
},
methods:{
post(){
console.log(this.msg)
}
}
}).mount("#app")
</script>
把数据转换成数值类型,控制台中的信息是蓝色的。上面那种字符串是黑色的
<div id="app">
<h1>{{msg}}</h1>
<form @submit.prevent="post">
<input type="text" v-model.number="msg"><!--.number使数据转换成数值类型-->
<button>提交表单</button>
</form>
</div>
<script src="https://unpkg.com/vue@next"></script>
<script>
Vue.createApp({
data(){
return{
msg:""
}
},
methods:{
post(){
console.log(this.msg)
}
}
}).mount("#app")
</script>
如果想要文本框失去焦点时h1标签才变化,就用.lazy
<div id="app">
<h1>{{msg}}</h1>
<form @submit.prevent="post">
<input type="text" v-model.lazy="msg">
<button>提交表单</button>
</form>
</div>
<script src="https://unpkg.com/vue@next"></script>
<script>
Vue.createApp({
data(){
return{
msg:""
}
},
methods:{
post(){
console.log(this.msg)
}
}
}).mount("#app")
</script>
没有失去焦点时h1不会变化
.trim可以去掉文本前后的空格,防止输入用户名的时候多打了空格而没察觉
<div id="app">
<h1>{{msg}}</h1>
<form @submit.prevent="post">
<input type="text" v-model.trim="msg">
<button>提交表单</button>
</form>
</div>
h1不受空格影响,点击提交后文本框中的空格就会消失
一个简单的水果购物车功能
<!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>
</head>
<body>
<div id="app">
<h1>水果列表</h1>
<form @submit.prevent="insert"><!--通过insert方法添加数组-->
<input type="text" v-model="name">
<input type="text" v-model.number="price">
<button>添加</button>
</form>
<ul>
<li v-for="item,index in list">
名称:{{item.name}}
单价:{{item.price}}
数量:<!--数量是个计数器-->
<button @click="decrease(index)">-</button><!--通过index定位到数组的第几个元素-->
<span>{{item.count}}</span>
<button @click="increase(index)">+</button>
</li>
</ul>
<h3>总价:{{totalPrice}}</h3>
</div>
<script src="https://unpkg.com/vue@next"></script>
<script>
Vue.createApp({
data(){
return{
name:"",
price:0,
list:[]
}
},
computed:{//计算属性
totalPrice(){
let sum = 0;
this.list.forEach(v => {//forEach遍历数组
sum += (v.price * v.count);
})
return sum;
}
},
methods:{
insert(){//添加数组
this.list.push({
name:this.name,
price:this.price,
count:1
})
},
increase(i){
this.list[i].count++
},
decrease(i){
if(this.list[i].count > 0){
this.list[i].count--
}else if(this.list[i].count <=0 && confirm("是否删除")){//数量小于等于0就弹出窗口,如果点确定就删了
this.list.splice(i,1);//删掉那一项
}
}
}
}).mount("#app")
</script>
</body>
</html>