zsydgithub 1 year ago
parent
commit
5cee0adbff

+ 59 - 21
v3_project/src/App.vue

@@ -1,30 +1,68 @@
 <template>
 <template>
-  <h2>响应式数据的判断</h2>
+  <div class="todo-container">
+    <div class="todo-wrap">
+      <Header :addTodo="addTodo"></Header>
+      <List :todos="todos"></List>
+      <Footer></Footer>
+    </div>
+  </div>
 </template>
 </template>
 
 
 <script lang="ts">
 <script lang="ts">
-import { defineComponent ,ref,isRef, isReactive, reactive, isReadonly, readonly, isProxy} from 'vue'
-
+import { defineComponent, reactive, toRefs } from "vue";
+//引入子级组件
+import Header from "./components/Header.vue";
+import List from "./components/List.vue";
+import Footer from "./components/Footer.vue";
+import { Todo } from "./types/todo";
 export default defineComponent({
 export default defineComponent({
-  //isRef
-  //isReactive
-  //isReadonly
-  //isProxy
-  setup () {
-    //isRef: 检查一个值是否为ref对象
-    console.log(isRef(ref({})))
-    //isReactive检查一个对象是否是reactive创建的响应式代理
-    console.log(isReactive(reactive({})))
-    //isReadonly 检查一个对象是否是由readonly创建的只读代理
-    console.log(isReadonly(readonly({})))
-    //isProxy 检查一个对象是否是由reactive或者readonly方法创建的代理
-    console.log(isProxy(readonly({})))
-    console.log(isProxy(reactive({})))
-    return {}
-  }
-})
+  setup() {
+    //定义一个数组数据  存放每一个对象  对象下面{id,title,isCompleted}
+    const state = reactive<{ todos: Todo[] }>({
+      todos: [
+        {
+          id: 1,
+          title: "奔驰",
+          isCompleted: false,
+        },
+        {
+          id: 2,
+          title: "宝马",
+          isCompleted: false,
+        },
+        {
+          id: 3,
+          title: "奥迪",
+          isCompleted: false,
+        },
+      ],
+    });
+
+    //添加数据的方法
+    const addTodo = (todo: Todo) => {
+      state.todos.unshift(todo);
+    };
+    return {
+      ...toRefs(state),
+      addTodo,
+    };
+  },
+  components: {
+    Header,
+    List,
+    Footer,
+  },
+});
 </script>
 </script>
 
 
 <style scoped>
 <style scoped>
-
+.todo-container {
+  width: 600px;
+  margin: 0 auto;
+}
+.todo-container .todo-wrap {
+  padding: 10px;
+  border: 1px solid #ddd;
+  border-radius: 5px;
+}
 </style>
 </style>

+ 50 - 0
v3_project/src/components/Footer.vue

@@ -0,0 +1,50 @@
+<template>
+  <div>
+    <div class="todo-footer">
+      <label>
+        <input type="checkbox" />
+      </label>
+      <span> <span>已完成0</span> / 全部2 </span>
+      <button class="btn btn-danger">清除已完成任务</button>
+    </div>
+  </div>
+</template>
+
+<script lang="ts">
+import { defineComponent } from "vue";
+
+export default defineComponent({
+  name: "Footer",
+  setup() {
+    return {};
+  },
+});
+</script>
+
+<style scoped>
+.todo-footer {
+  height: 40px;
+  line-height: 40px;
+  padding-left: 6px;
+  margin-top: 5px;
+}
+
+.todo-footer label {
+  display: inline-block;
+  margin-right: 20px;
+  cursor: pointer;
+}
+
+.todo-footer label input {
+  position: relative;
+  top: -1px;
+  vertical-align: middle;
+  margin-right: 5px;
+}
+
+.todo-footer button {
+  float: right;
+  margin-top: 5px;
+}
+
+</style>

+ 69 - 0
v3_project/src/components/Header.vue

@@ -0,0 +1,69 @@
+<template>
+  <div>
+    <div class="todo-header">
+      <input
+        type="text"
+        placeholder="请输入你的任务名称,按回车键确认"
+        v-model="title"
+        @keyup.enter="add"
+      />
+    </div>
+  </div>
+</template>
+
+<script lang="ts">
+import { defineComponent,ref } from "vue";
+
+export default defineComponent({
+  name: "Header",
+  props: {
+    addTodo: {
+      type: Function,
+      required: true,
+    },
+  },
+  setup(props) {
+    //定义一个ref类型的数据
+    const title = ref('')
+    //回车的事件的回调函数,用来添加数据
+    const add = () => {
+      //获取文本框中输入的数据,判断不为空
+      const text = title.value
+      if(!text.trim()) return
+      //此时有数据,创建一个todo对象
+      const todo = {
+        id: Date.now(),
+        title: text,
+        isCompleted: false
+      }
+
+      //调用方法addTodo的方法
+      props.addTodo(todo)
+      //清空文本框
+      title.value = ''
+    };
+    return {
+      add,
+      title
+    };
+  },
+});
+</script>
+
+<style scoped>
+.todo-header input {
+  width: 560px;
+  height: 28px;
+  font-size: 14px;
+  border: 1px solid #ccc;
+  border-radius: 4px;
+  padding: 4px 7px;
+}
+
+.todo-header input:focus {
+  outline: none;
+  border-color: rgba(82, 168, 236, 0.8);
+  box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075),
+    0 0 8px rgba(82, 168, 236, 0.6);
+}
+</style>

+ 64 - 0
v3_project/src/components/Item.vue

@@ -0,0 +1,64 @@
+<template>
+  <div>
+    <li>
+      <label>
+        <input type="checkbox" />
+        <span>{{todo.title}}</span>
+      </label>
+      <button class="btn btn-danger" style="display: none">删除</button>
+    </li>
+  </div>
+</template>
+
+<script lang="ts">
+import { defineComponent } from "vue";
+import {Todo} from "../types/todo"
+export default defineComponent({
+  name: "Item",
+  props: {
+    todo: {
+      type: Object as () => Todo, //函数返回的是一个Todo类型
+      required: true
+    },
+  },
+  setup() {
+    return {};
+  },
+});
+</script>
+
+<style scoped>
+li {
+  list-style: none;
+  height: 36px;
+  line-height: 36px;
+  padding: 0 5px;
+  border-bottom: 1px solid #ddd;
+}
+
+li label {
+  float: left;
+  cursor: pointer;
+}
+
+li label li input {
+  vertical-align: middle;
+  margin-right: 6px;
+  position: relative;
+  top: -1px;
+}
+
+li button {
+  float: right;
+  display: none;
+  margin-top: 3px;
+}
+
+li:before {
+  content: initial;
+}
+
+li:last-child {
+  border-bottom: none;
+}
+</style>

+ 40 - 0
v3_project/src/components/List.vue

@@ -0,0 +1,40 @@
+<template>
+  <div>
+    <ul class="todo-main">
+      <Item v-for="(todo,index) in todos" :key="todo.id" :todo="todo"></Item>
+    </ul>
+  </div>
+</template>
+
+<script lang="ts">
+import { defineComponent } from "vue";
+import Item from "./Item.vue";
+export default defineComponent({
+  name: "List",
+  props: ['todos'],
+  setup() {
+    return {};
+  },
+  components: {
+    Item
+  }
+});
+</script>
+
+<style scoped>
+.todo-main {
+  margin-left: 0px;
+  border: 1px solid #ddd;
+  border-radius: 2px;
+  padding: 0px;
+}
+
+.todo-empty {
+  height: 40px;
+  line-height: 40px;
+  border: 1px solid #ddd;
+  border-radius: 2px;
+  padding-left: 5px;
+  margin-top: 10px;
+}
+</style>

+ 6 - 0
v3_project/src/types/todo.ts

@@ -0,0 +1,6 @@
+//定义一个接口,约束state的数据类型
+export interface Todo{
+  id: number,
+  title: string,
+  isCompleted: boolean
+}

+ 137 - 0
v3_project/todos_page/index.css

@@ -0,0 +1,137 @@
+/*base*/
+body {
+  background: #fff;
+}
+
+.btn {
+  display: inline-block;
+  padding: 4px 12px;
+  margin-bottom: 0;
+  font-size: 14px;
+  line-height: 20px;
+  text-align: center;
+  vertical-align: middle;
+  cursor: pointer;
+  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);
+  border-radius: 4px;
+}
+
+.btn-danger {
+  color: #fff;
+  background-color: #da4f49;
+  border: 1px solid #bd362f;
+}
+
+.btn-danger:hover {
+  color: #fff;
+  background-color: #bd362f;
+}
+
+.btn:focus {
+  outline: none;
+}
+
+
+/*app*/
+.todo-container {
+  width: 600px;
+  margin: 0 auto;
+}
+.todo-container .todo-wrap {
+  padding: 10px;
+  border: 1px solid #ddd;
+  border-radius: 5px;
+}
+
+/*header*/
+.todo-header input {
+  width: 560px;
+  height: 28px;
+  font-size: 14px;
+  border: 1px solid #ccc;
+  border-radius: 4px;
+  padding: 4px 7px;
+}
+
+.todo-header input:focus {
+  outline: none;
+  border-color: rgba(82, 168, 236, 0.8);
+  box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);
+}
+
+/*main*/
+.todo-main {
+  margin-left: 0px;
+  border: 1px solid #ddd;
+  border-radius: 2px;
+  padding: 0px;
+}
+
+.todo-empty {
+  height: 40px;
+  line-height: 40px;
+  border: 1px solid #ddd;
+  border-radius: 2px;
+  padding-left: 5px;
+  margin-top: 10px;
+}
+/*item*/
+li {
+  list-style: none;
+  height: 36px;
+  line-height: 36px;
+  padding: 0 5px;
+  border-bottom: 1px solid #ddd;
+}
+
+li label {
+  float: left;
+  cursor: pointer;
+}
+
+li label li input {
+  vertical-align: middle;
+  margin-right: 6px;
+  position: relative;
+  top: -1px;
+}
+
+li button {
+  float: right;
+  display: none;
+  margin-top: 3px;
+}
+
+li:before {
+  content: initial;
+}
+
+li:last-child {
+  border-bottom: none;
+}
+
+/*footer*/
+.todo-footer {
+  height: 40px;
+  line-height: 40px;
+  padding-left: 6px;
+  margin-top: 5px;
+}
+
+.todo-footer label {
+  display: inline-block;
+  margin-right: 20px;
+  cursor: pointer;
+}
+
+.todo-footer label input {
+  position: relative;
+  top: -1px;
+  vertical-align: middle;
+  margin-right: 5px;
+}
+
+.todo-footer button {
+  float: right;
+  margin-top: 5px;
+}

+ 46 - 0
v3_project/todos_page/index.html

@@ -0,0 +1,46 @@
+<!doctype html>
+<html lang="en">
+<head>
+  <meta charset="utf-8">
+  <title>React App</title>
+
+  <link rel="stylesheet" href="index.css">
+</head>
+<body>
+<div id="root">
+  <div class="todo-container">
+    <div class="todo-wrap">
+      <div class="todo-header">
+        <input type="text" placeholder="请输入你的任务名称,按回车键确认"/>
+      </div>
+      <ul class="todo-main">
+        <li>
+          <label>
+            <input type="checkbox"/>
+            <span>xxxxx</span>
+          </label>
+          <button class="btn btn-danger" style="display:none">删除</button>
+        </li>
+        <li>
+          <label>
+            <input type="checkbox"/>
+            <span>yyyy</span>
+          </label>
+          <button class="btn btn-danger" style="display:none">删除</button>
+        </li>
+      </ul>
+      <div class="todo-footer">
+        <label>
+          <input type="checkbox"/>
+        </label>
+        <span>
+          <span>已完成0</span> / 全部2
+        </span>
+        <button class="btn btn-danger">清除已完成任务</button>
+      </div>
+    </div>
+  </div>
+</div>
+
+</body>
+</html>