前言
实现效果:
正文
准备工作:
- 在终端输入
npm create vue@latest创建vue项目文件; - 安装包,在终端输入
npm i。
文件布局:
新建的vue文件:
(因为样式我是用css写的,所以记得把style里的lang属性的值改为css)
- 新建一个文件夹
components用于存放vue文件;
- Shopping.vue
js
- 引入文件
import { reactive, computed } from 'vue';
- 引入书籍数组,用
reactive来使其变成响应式的变量,因为需要改变书籍购买的数量
const books = reactive([
{
id: 1,
name: '《算法导论》',
date: '2006-9',
price: 85.00,
count: 1
},
{
id: 2,
name: '《UNIX编程艺术》',
date: '2006-2',
price: 59.00,
count: 1
},
{
id: 3,
name: '《编程珠玑》',
date: '2008-10',
price: 39.00,
count: 1
},
{
id: 4,
name: '《代码大全》',
date: '2006-3',
price: 128.00,
count: 1
},
]);
- 定义一个计算属性
computed来计算书籍的总价格,当数量发生变化时会触发该函数
const totalPrice = computed(() => {
let total = 0;
books.forEach(book => {
total += book.price * book.count;
});
return total;
});
- 定义两个函数
add和minus用户实现书籍数量的变化
const add = (index) => {
// console.log(index);
books[index].count++;
};
const minus = (index) => {
// console.log(index);
books[index].count--;
};
css
<style lang="css" scoped>
table{
margin: 0 auto;
border: 1px solid #e9e9e9;
border-collapse: collapse;
border-spacing: 0;
}
th, td{
padding: 8px 16px;
border: 1px solid #e9e9e9;
}
.counter{
margin: 0 5px;
}
</style>
template
- 通过
table标签来渲染书籍的数据 - 通过
v-for来实现遍历渲染 - 通过
@click来绑定add和minus :disabled="book.count <= 0表示当数量减到小于或者等于0时,按钮失效
<template>
<div>
<table>
<thead>
<th>序号</th>
<th>书籍名称</th>
<th>出版日期</th>
<th>价格</th>
<th>购买数量</th>
<th>操作</th>
</thead>
<tbody>
<tr v-for="(book, index) in books" :key="index">
<td>{{index + 1}}</td>
<td>{{book.name}}</td>
<td>{{book.date}}</td>
<td>{{book.price}}</td>
<td>{{book.count}}</td>
<td>
<button :disabled="book.count <= 0" @click="minus(index)">-</button>
<span class="counter">{{book.count}}</span>
<button @click="add(index)">+</button>
</td>
</tr>
</tbody>
</table>
<h3>总价格:{{totalPrice}}</h3>
</div>
</template>
- Todos.vue
js
- 引入文件
import { reactive, ref } from 'vue';
- 定义一个
newTodo,初始值为null,用来获取input输入框的内容,来实现添加功能
const newTodo = ref(null);
- 定义一个清单数组
todos,通过reactive来使其变成响应式的,因为后面点击勾选需要改变里面的completed属性
const state = reactive({
todos: [
{
id: 1,
title: '学习',
completed: false
},
{
id: 2,
title: '吃饭',
completed: true
},
{
id: 3,
title: '睡觉',
completed: false
}
],
});
- 定义一个
addTodo函数用来增加列表
// 1. 输入newTodo 增加列表
const addTodo = () => {
state.todos.push({
id: state.todos.length + 1,
title: newTodo.value,
completed: false
});
}
- 定义一个函数
com用于勾选和取消
// 2.勾选和取消某件事项
const com = () => {
state.todos.completed = !state.todos.completed;
};
css
在main.js引入一个todomvc-app-css里的css文件里包装好的类来实现
import "todomvc-app-css/index.css";
template
- 通过
v-for来实现列表渲染 @click来绑定函数v-model来实现数据的双向绑定
<template>
<section class="todoapp">
<header class="header">
<h1>todos</h1>
<input type="text" class="new-todo" placeholder="想干的事" @keyup.enter="addTodo" v-model="newTodo">
</header>
<section class="main">
<input type="checkbox" class="toggle-all" id="toggle-all">
<label for="toggle-all">Mark all as complete</label>
<ul class="todo-list">
<li class="todo" v-for="(item, index) in state.todos" :key="index">
<div class="view">
<input type="checkbox" class="toggle" v-model="item.completed" @click="com">
<label>{{item.title}}</label>
<button class="destroy"></button>
</div>
</li>
</ul>
</section>
</section>
</template>
App.vue文件:
js
- 引入文件
import { ref } from 'vue';
import Shopping from './components/Shopping.vue'
import Todos from './components/Todos.vue';
- 定义一个变量
tabIndex来实现按购物车和计划清单页面的切换的判断,通过ref使其变成响应式的
let tabIndex = ref(1);
- 定义一个
changeTab函数来实现切换
const changeTab = (index) => {
console.log(index);
tabIndex.value = index;
}
css
<style lang="css" scoped>
.app{
text-align: center;
}
.btn{
font-size: 20px;
width: 100px;
height: 40px;
margin: 20px;
}
</style>
template
- 通过
@click绑定函数 - 通过
v-if来实现两个页面的切换,如果变量tabIndex为1展示购物车页面 - 反之为计划清单页面
<template>
<div class="app">
<button class="btn" @click="changeTab(1)">购物车</button>
<button class="btn" @click="changeTab(2)">todos</button>
<!-- shopping -->
<Shopping v-if="tabIndex === 1"></Shopping>
<!-- todos -->
<Todos v-else></Todos>
</div>
</template>