赞
踩
- //引入vue
- import Vue from "vue";
- //引入组件App
- import App from "./App.vue";
-
- //关闭vue的生产提示
- Vue.config.productionTip = false;
-
- //创建vm
- new Vue({
- el: "#app",
- render: (h) => h(App),
- });
- <template>
- <div id="root">
- <div class="todo-container">
- <div class="todo-wrap">
- <todo-head :addTodo="addTodo" />
- <todo-list
- :todoList="todoList"
- :deleteTodo="deleteTodo"
- :updateFlag="updateFlag"
- />
- <todo-fotter
- :todoList="todoList"
- :updateFlagAll="updateFlagAll"
- :deleteFlagAll="deleteFlagAll"
- />
- </div>
- </div>
- </div>
- </template>
-
- <script>
- import TodoList from "./components/todo-list.vue";
- import TodoHead from "./components/todo-head.vue";
- import TodoFotter from "./components/todo-fotter.vue";
- //引入组件
-
- export default {
- components: { TodoHead, TodoList, TodoFotter },
- name: "App",
- data() {
- return {
- todoList: [
- { id: "001", name: "yb", flag: true },
- { id: "002", name: "yg", flag: false },
- { id: "003", name: "yf", flag: true },
- ],
- };
- },
- methods: {
- //添加
- addTodo(todo) {
- this.todoList.unshift(todo); //在数组最前方添加
- },
- //删除
- deleteTodo(id) {
- //过滤出 不是要删除id的 所有值
- this.todoList = this.todoList.filter((todo) => todo.id != id);
- },
- //删除全部已选的
- deleteFlagAll() {
- this.todoList = this.todoList.filter((todo) => todo.flag === false);
- },
- //修改指定事 是否完成
- updateFlag(id) {
- this.todoList.forEach((todo) => {
- if (todo.id === id) todo.flag = !todo.flag;
- });
- },
- //修改全部的 是否完成
- updateFlagAll(flag) {
- this.todoList.forEach((todo) => {
- todo.flag = flag;
- });
- },
- //删除指定的
- },
- };
- </script>
-
- <style>
- /*base*/
- body {
- background: plum;
- }
- .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;
- }
-
- .todo-container {
- width: 600px;
- margin: 0 auto;
- }
- .todo-container .todo-wrap {
- padding: 10px;
- border: 1px solid #ddd;
- border-radius: 5px;
- }
- </style>
- <template>
- <div class="todo-header">
- <input
- type="text"
- placeholder="请输入你的任务名称,按回车键确认"
- @keyup.enter="add"
- v-model="todoName"
- />
- </div>
- </template>
-
- <script scoped>
- //引入nanoid
- import { nanoid } from "nanoid";
- export default {
- props: ["addTodo"],
- data() {
- return {
- todoName: "",
- };
- },
- methods: {
- add() {
- //去除前后空格判断不为空 进行添加
- if (this.todoName.trim() != "" && this.todoName.trim() != null) {
- const todo = { id: nanoid(), name: this.todoName, flag: false };
- this.addTodo(todo);
- this.todoName = "";
- }
- },
- },
- };
- </script>
-
- <style>
- /*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);
- }
- </style>
- <template>
- <ul class="todo-main">
- <todo-item
- v-for="todo in todoList"
- :key="todo.id"
- :todo="todo"
- :deleteTodo="deleteTodo"
- :updateFlag="updateFlag"
- />
- </ul>
- </template>
-
- <script>
- import todoItem from "./todo-item.vue";
- export default {
- components: { todoItem },
- props: ["todoList", "deleteTodo", "updateFlag"],
- };
- </script>
-
- <style scoped>
- /*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;
- }
- </style>
- <template>
- <li>
- <label>
- <!-- change:元素发生修改时调用 -->
- <input type="checkbox" :checked="todo.flag" @change="upd(todo.id)" />
- <span>{{ todo.name }}</span>
- </label>
- <button class="btn btn-danger" @click="del(todo.id)">删除</button>
- </li>
- </template>
-
- <script>
- export default {
- props: ["todo", "deleteTodo", "updateFlag"],
- methods: {
- del(id) {
- this.deleteTodo(id);
- },
- upd(id) {
- this.updateFlag(id);
- },
- },
- };
- </script>
-
- <style scoped>
- /*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;
- }
- li:hover {
- background-color: pink;
- }
- li:hover button {
- display: block;
- }
- </style>
- <template>
- <div class="todo-footer" v-show="allNUm">
- <label>
- <input type="checkbox" v-model="flag" />
- </label>
- <span>
- <span>已完成{{ trueNum }}</span> / 全部{{ allNUm }}
- </span>
- <button class="btn btn-danger" @click="delFlagAll">清除已完成任务</button>
- </div>
- </template>
-
- <script>
- export default {
- props: ["todoList", "updateFlagAll", "deleteFlagAll"],
- methods: {
- delFlagAll() {
- this.deleteFlagAll();
- },
- },
- computed: {
- allNUm() {
- return this.todoList.length;
- },
- trueNum() {
- /* reduce 根据数组的长度 执行几次
- returnValue 每次的返回值
- todo 每次的实例
- 0 初始值 */
- return this.todoList.reduce(
- (returnValue, todo) => returnValue + (todo.flag ? 1 : 0),
- 0
- );
- },
- flag: {
- get() {
- //如果 已完成的数量 === 全部数量 默认全选
- return this.trueNum === this.allNUm && this.trueNum > 0;
- },
- set(value) {
- //value获取当前多选框的状态 勾选 true 不勾选 false
- this.updateFlagAll(value);
- },
- },
- },
- };
- </script>
-
- <style scoped>
- /*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;
- }
- </style>
- 1、组件化编码流程:
- (1)、拆分静态组件:组件要按照功能点拆分,命名不要与html元素冲突
- (2)、实现动态组件:考虑好数据的存放位置,数据是一个在用,还是一堆组件再用
- 1)、一个组件在用:放在组件自身即可。
- 2)、一些组件在用:放在他们共同的父组件上(状态提升)
- (3)、实现交互:从绑定事件开始。
- 2、props适用于:
- (1)、父组件 ===> 子组件 通信 (父组件创建一个函数 写点方法 让子组件传入参数调用实现功能)
- (2)、子组件 ===> 父组件 通信 (要求父组件传过来一个函数 再通过上方的说明实现)
-
- 3、使用v-model 时要切记:v-model 绑定的值不能是 props传过来的值,因为props是 不可以修改的!
- 4、props传过来的若是对象类型的值,修改对象的属性时Vue不会报错 会提示破浪线 可以运行,但不推荐使用
- data() {
- return {
- //获取存储
- todoList: localStorage.getItem("todos") || [],
- };
- },
-
-
- watch: {
- todoList: {
- deep: true, //开启深度监视
- handler(value) {
- //这里获取的 value 是todoList 被修改后的值
- localStorage.setItem("todos", JSON.stringify(value)); //把值转为json格式字符串
- },
- },
- },
- <template>
- <div id="root">
- <div class="todo-container">
- <div class="todo-wrap">
- <todo-head @addTodo="addTodo" />
- <todo-list
- :todoList="todoList"
- :deleteTodo="deleteTodo"
- :updateFlag="updateFlag"
- />
- <todo-fotter
- :todoList="todoList"
- @updateFlagAll="updateFlagAll"
- @deleteFlagAll="deleteFlagAll"
- />
- </div>
- </div>
- </div>
- </template>
-
- //给底部组件标签绑定两个自定义事件 @updateFlagAll @deleteFlagAll
- <template>
- <div class="todo-footer" v-show="allNUm">
- <label>
- <input type="checkbox" v-model="flag" />
- </label>
- <span>
- <span>已完成{{ trueNum }}</span> / 全部{{ allNUm }}
- </span>
- <button class="btn btn-danger" @click="delFlagAll">清除已完成任务</button>
- </div>
- </template>
-
- <script>
- export default {
- props: ["todoList"],
- methods: {
- delFlagAll() {
- //this.deleteFlagAll();
- this.$emit("deleteFlagAll");
- },
- },
- computed: {
- allNUm() {
- return this.todoList.length;
- },
- trueNum() {
- /* reduce 根据数组的长度 执行几次
- returnValue 每次的返回值
- todo 每次的实例
- 0 初始值 */
- return this.todoList.reduce(
- (returnValue, todo) => returnValue + (todo.flag ? 1 : 0),
- 0
- );
- },
- flag: {
- get() {
- //如果 已完成的数量 === 全部数量 默认全选
- return this.trueNum === this.allNUm && this.trueNum > 0;
- },
- set(value) {
- //value获取当前多选框的状态 勾选 true 不勾选 false
- //this.updateFlagAll(value);
- this.$emit("updateFlagAll", value);
- },
- },
- },
- };
- </script>
-
- <style scoped>
- /*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;
- }
- </style>
- //引入vue
- import Vue from "vue";
- //引入组件App
- import App from "./App.vue";
-
- //关闭vue的生产提示
- Vue.config.productionTip = false;
-
- //创建vm
- new Vue({
- el: "#app",
- render: (h) => h(App),
- beforeCreate() {
- Vue.prototype.$bus = this; //设置全局事件总线
- },
- });
- <template>
- <div id="root">
- <div class="todo-container">
- <div class="todo-wrap">
- <todo-head @addTodo="addTodo" />
- <todo-list :todoList="todoList" />
- <todo-fotter
- :todoList="todoList"
- @updateFlagAll="updateFlagAll"
- @deleteFlagAll="deleteFlagAll"
- />
- </div>
- </div>
- </div>
- </template>
-
- <script>
- import TodoList from "./components/todo-list.vue";
- import TodoHead from "./components/todo-head.vue";
- import TodoFotter from "./components/todo-fotter.vue";
- //引入组件
-
- export default {
- components: { TodoHead, TodoList, TodoFotter },
- name: "App",
- data() {
- return {
- //获取存储 使用JSON把字符解析成对象
- todoList: JSON.parse(localStorage.getItem("todos")) || [],
- };
- },
- methods: {
- //添加
- addTodo(todo) {
- this.todoList.unshift(todo); //在数组最前方添加u
- },
- //删除
- deleteTodo(id) {
- //过滤出 不是要删除id的 所有值
- this.todoList = this.todoList.filter((todo) => todo.id != id);
- },
- //删除全部已选的
- deleteFlagAll() {
- this.todoList = this.todoList.filter((todo) => todo.flag === false);
- },
- //修改指定事 是否完成
- updateFlag(id) {
- this.todoList.forEach((todo) => {
- if (todo.id === id) todo.flag = !todo.flag;
- });
- },
- //修改全部的 是否完成
- updateFlagAll(flag) {
- this.todoList.forEach((todo) => {
- todo.flag = flag;
- });
- },
- //删除指定的g
- },
- mounted() {
- this.$bus.$on("deleteTodo", this.deleteTodo); //gei$bus设置自定义事件
- this.$bus.$on("updateFlag", this.updateFlag);
- },
- beforeDestroy() {
- this.$bus.$off("deleteTodo", "updateFlag");
- },
- watch: {
- todoList: {
- deep: true, //开启深度监视
- handler(value) {
- //这里获取的 value 是todoList 被修改后的值
- localStorage.setItem("todos", JSON.stringify(value)); //把值转为json格式字符串
- },
- },
- },
- };
- </script>
-
- <style>
- /*base*/
- body {
- background: plum;
- }
- .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;
- }
-
- .todo-container {
- width: 600px;
- margin: 0 auto;
- }
- .todo-container .todo-wrap {
- padding: 10px;
- border: 1px solid #ddd;
- border-radius: 5px;
- }
- </style>
- <template>
- <ul class="todo-main">
- <todo-item v-for="todo in todoList" :key="todo.id" :todo="todo" />
- </ul>
- </template>
-
- props: ["todoList"],
- <template>
- <li>
- <label>
- <!-- change:元素发生修改时调用 -->
- <input type="checkbox" :checked="todo.flag" @change="upd(todo.id)" />
- <span>{{ todo.name }}</span>
- </label>
- <button class="btn btn-danger" @click="del(todo.id)">删除</button>
- </li>
- </template>
-
- <script>
- export default {
- props: ["todo"],
- methods: {
- del(id) {
- //this.deleteTodo(id);
- if (confirm("确认删除")) {
- this.$bus.$emit("deleteTodo", id);
- }
- },
- upd(id) {
- //this.updateFlag(id);
- this.$bus.$emit("updateFlag", id);
- },
- },
- };
- </script>
-
- <style scoped>
- /*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;
- }
- li:hover {
- background-color: pink;
- }
- li:hover button {
- display: block;
- }
- </style>
全装 pubsub.js(消息发布与订阅库)
npm i pubsub-js
- //引入订阅消息与发布库
- import pubsub from "pubsub-js";
- mounted() {
- this.pubId = pubsub.subscribe("deleteTodo", this.deleteTodo); //设置消息订阅
- this.$bus.$on("updateFlag", this.updateFlag);
- },
- del(id) {
- if (confirm("确认删除")) {
- //this.deleteTodo(id);
- //this.$bus.$emit("deleteTodo", id);
- pubsub.publish("deleteTodo", id); //发送消息
- }
- },
- <template>
- <li>
- <label>
- <!-- change:元素发生修改时调用 -->
- <input type="checkbox" :checked="todo.flag" @change="upd(todo.id)" />
- <span v-show="!todo.isEdit">{{ todo.name }}</span>
- <input
- type="text"
- :value="todo.name"
- v-show="todo.isEdit"
- @blur="nameBlur($event, todo)"
- ref="inputFocus"
- />
- </label>
- <button class="btn btn-danger" @click="del(todo.id)">删除</button>
- <button v-show="!todo.isEdit" class="btn btn-edit" @click="updName(todo)">
- 编辑
- </button>
- </li>
- </template>
-
- <script>
- //引入订阅消息与发布库
- import pubsub from "pubsub-js";
- export default {
- props: ["todo"],
- methods: {
- del(id) {
- //this.deleteTodo(id);
- if (confirm("确认删除")) {
- //this.$bus.$emit("deleteTodo", id);
- pubsub.publish("deleteTodo", id);
- }
- },
- upd(id) {
- //this.updateFlag(id);
- this.$bus.$emit("updateFlag", id);
- },
- updName(todo) {
- if ("isEdit" in todo) {
- //判断该对象 有没有 isEdit属性
- todo.isEdit = true;
- } else {
- console.log("@");
- this.$set(todo, "isEdit", true);
- }
- // $nextTick() 会在模板解析下一次执行里面的函数
- this.$nextTick(() => this.$refs.inputFocus.focus());
- },
- nameBlur(event, todo) {
- todo.isEdit = false;
- if (!event.target.value.trim()) return alert("不能为空");
- //字符 有值的时候 返回的是 true 没有返回 false
- this.$bus.$emit("updateName", todo.id, event.target.value);
- },
- },
- };
- </script>
-
- <style scoped>
- /*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;
- }
- li:hover {
- background-color: pink;
- }
- li:hover button {
- display: block;
- }
- </style>
- <template>
- <!-- 普通的动画 -->
- <!-- <ul class="todo-main">
- <transition-group name="todo" appear>
- <todo-item v-for="todo in todoList" :key="todo.id" :todo="todo" />
- </transition-group>
- </ul> -->
- <!-- 第三方库动画 -->
- <ul class="todo-main">
- <transition-group
- name="animate__animated animate__bounce"
- appear
- enter-active-class="animate__bounce"
- leave-active-class="animate__backOutDown"
- >
- <todo-item v-for="todo in todoList" :key="todo.id" :todo="todo" />
- </transition-group>
- </ul>
- </template>
-
- <script>
- //引入
- import "animate.css";
- import todoItem from "./todo-item.vue";
- export default {
- components: { todoItem },
- props: ["todoList"],
- };
- </script>
-
- <style scoped>
- /*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;
- }
-
- /* 普通的动画 */
- /* .todo-enter-active {
- animation: goto 1s linear;
- }
- .todo-leave-active {
- animation: goto 1s linear reverse;
- }
- @keyframes goto {
- from {
- transform: translateX(-100%);
- }
- to {
- transform: translateX(0%);
- }
- } */
- </style>
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。