当前位置:   article > 正文

(Vue案例)TodoList_vue todolist案例

vue todolist案例

实现效果

 代码展示

main.js

  1. //引入vue
  2. import Vue from "vue";
  3. //引入组件App
  4. import App from "./App.vue";
  5. //关闭vue的生产提示
  6. Vue.config.productionTip = false;
  7. //创建vm
  8. new Vue({
  9. el: "#app",
  10. render: (h) => h(App),
  11. });

App.vue

  1. <template>
  2. <div id="root">
  3. <div class="todo-container">
  4. <div class="todo-wrap">
  5. <todo-head :addTodo="addTodo" />
  6. <todo-list
  7. :todoList="todoList"
  8. :deleteTodo="deleteTodo"
  9. :updateFlag="updateFlag"
  10. />
  11. <todo-fotter
  12. :todoList="todoList"
  13. :updateFlagAll="updateFlagAll"
  14. :deleteFlagAll="deleteFlagAll"
  15. />
  16. </div>
  17. </div>
  18. </div>
  19. </template>
  20. <script>
  21. import TodoList from "./components/todo-list.vue";
  22. import TodoHead from "./components/todo-head.vue";
  23. import TodoFotter from "./components/todo-fotter.vue";
  24. //引入组件
  25. export default {
  26. components: { TodoHead, TodoList, TodoFotter },
  27. name: "App",
  28. data() {
  29. return {
  30. todoList: [
  31. { id: "001", name: "yb", flag: true },
  32. { id: "002", name: "yg", flag: false },
  33. { id: "003", name: "yf", flag: true },
  34. ],
  35. };
  36. },
  37. methods: {
  38. //添加
  39. addTodo(todo) {
  40. this.todoList.unshift(todo); //在数组最前方添加
  41. },
  42. //删除
  43. deleteTodo(id) {
  44. //过滤出 不是要删除id的 所有值
  45. this.todoList = this.todoList.filter((todo) => todo.id != id);
  46. },
  47. //删除全部已选的
  48. deleteFlagAll() {
  49. this.todoList = this.todoList.filter((todo) => todo.flag === false);
  50. },
  51. //修改指定事 是否完成
  52. updateFlag(id) {
  53. this.todoList.forEach((todo) => {
  54. if (todo.id === id) todo.flag = !todo.flag;
  55. });
  56. },
  57. //修改全部的 是否完成
  58. updateFlagAll(flag) {
  59. this.todoList.forEach((todo) => {
  60. todo.flag = flag;
  61. });
  62. },
  63. //删除指定的
  64. },
  65. };
  66. </script>
  67. <style>
  68. /*base*/
  69. body {
  70. background: plum;
  71. }
  72. .btn {
  73. display: inline-block;
  74. padding: 4px 12px;
  75. margin-bottom: 0;
  76. font-size: 14px;
  77. line-height: 20px;
  78. text-align: center;
  79. vertical-align: middle;
  80. cursor: pointer;
  81. box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2),
  82. 0 1px 2px rgba(0, 0, 0, 0.05);
  83. border-radius: 4px;
  84. }
  85. .btn-danger {
  86. color: #fff;
  87. background-color: #da4f49;
  88. border: 1px solid #bd362f;
  89. }
  90. .btn-danger:hover {
  91. color: #fff;
  92. background-color: #bd362f;
  93. }
  94. .btn:focus {
  95. outline: none;
  96. }
  97. .todo-container {
  98. width: 600px;
  99. margin: 0 auto;
  100. }
  101. .todo-container .todo-wrap {
  102. padding: 10px;
  103. border: 1px solid #ddd;
  104. border-radius: 5px;
  105. }
  106. </style>

components里的 todo-head.vue

  1. <template>
  2. <div class="todo-header">
  3. <input
  4. type="text"
  5. placeholder="请输入你的任务名称,按回车键确认"
  6. @keyup.enter="add"
  7. v-model="todoName"
  8. />
  9. </div>
  10. </template>
  11. <script scoped>
  12. //引入nanoid
  13. import { nanoid } from "nanoid";
  14. export default {
  15. props: ["addTodo"],
  16. data() {
  17. return {
  18. todoName: "",
  19. };
  20. },
  21. methods: {
  22. add() {
  23. //去除前后空格判断不为空 进行添加
  24. if (this.todoName.trim() != "" && this.todoName.trim() != null) {
  25. const todo = { id: nanoid(), name: this.todoName, flag: false };
  26. this.addTodo(todo);
  27. this.todoName = "";
  28. }
  29. },
  30. },
  31. };
  32. </script>
  33. <style>
  34. /*header*/
  35. .todo-header input {
  36. width: 560px;
  37. height: 28px;
  38. font-size: 14px;
  39. border: 1px solid #ccc;
  40. border-radius: 4px;
  41. padding: 4px 7px;
  42. }
  43. .todo-header input:focus {
  44. outline: none;
  45. border-color: rgba(82, 168, 236, 0.8);
  46. box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075),
  47. 0 0 8px rgba(82, 168, 236, 0.6);
  48. }
  49. </style>

components里的todo-list.vue

  1. <template>
  2. <ul class="todo-main">
  3. <todo-item
  4. v-for="todo in todoList"
  5. :key="todo.id"
  6. :todo="todo"
  7. :deleteTodo="deleteTodo"
  8. :updateFlag="updateFlag"
  9. />
  10. </ul>
  11. </template>
  12. <script>
  13. import todoItem from "./todo-item.vue";
  14. export default {
  15. components: { todoItem },
  16. props: ["todoList", "deleteTodo", "updateFlag"],
  17. };
  18. </script>
  19. <style scoped>
  20. /*main*/
  21. .todo-main {
  22. margin-left: 0px;
  23. border: 1px solid #ddd;
  24. border-radius: 2px;
  25. padding: 0px;
  26. }
  27. .todo-empty {
  28. height: 40px;
  29. line-height: 40px;
  30. border: 1px solid #ddd;
  31. border-radius: 2px;
  32. padding-left: 5px;
  33. margin-top: 10px;
  34. }
  35. </style>

components里的 todo-Item.vue

  1. <template>
  2. <li>
  3. <label>
  4. <!-- change:元素发生修改时调用 -->
  5. <input type="checkbox" :checked="todo.flag" @change="upd(todo.id)" />
  6. <span>{{ todo.name }}</span>
  7. </label>
  8. <button class="btn btn-danger" @click="del(todo.id)">删除</button>
  9. </li>
  10. </template>
  11. <script>
  12. export default {
  13. props: ["todo", "deleteTodo", "updateFlag"],
  14. methods: {
  15. del(id) {
  16. this.deleteTodo(id);
  17. },
  18. upd(id) {
  19. this.updateFlag(id);
  20. },
  21. },
  22. };
  23. </script>
  24. <style scoped>
  25. /*item*/
  26. li {
  27. list-style: none;
  28. height: 36px;
  29. line-height: 36px;
  30. padding: 0 5px;
  31. border-bottom: 1px solid #ddd;
  32. }
  33. li label {
  34. float: left;
  35. cursor: pointer;
  36. }
  37. li label li input {
  38. vertical-align: middle;
  39. margin-right: 6px;
  40. position: relative;
  41. top: -1px;
  42. }
  43. li button {
  44. float: right;
  45. display: none;
  46. margin-top: 3px;
  47. }
  48. li:before {
  49. content: initial;
  50. }
  51. li:last-child {
  52. border-bottom: none;
  53. }
  54. li:hover {
  55. background-color: pink;
  56. }
  57. li:hover button {
  58. display: block;
  59. }
  60. </style>

components 里的 todo-fotter.vue

  1. <template>
  2. <div class="todo-footer" v-show="allNUm">
  3. <label>
  4. <input type="checkbox" v-model="flag" />
  5. </label>
  6. <span>
  7. <span>已完成{{ trueNum }}</span> / 全部{{ allNUm }}
  8. </span>
  9. <button class="btn btn-danger" @click="delFlagAll">清除已完成任务</button>
  10. </div>
  11. </template>
  12. <script>
  13. export default {
  14. props: ["todoList", "updateFlagAll", "deleteFlagAll"],
  15. methods: {
  16. delFlagAll() {
  17. this.deleteFlagAll();
  18. },
  19. },
  20. computed: {
  21. allNUm() {
  22. return this.todoList.length;
  23. },
  24. trueNum() {
  25. /* reduce 根据数组的长度 执行几次
  26. returnValue 每次的返回值
  27. todo 每次的实例
  28. 0 初始值 */
  29. return this.todoList.reduce(
  30. (returnValue, todo) => returnValue + (todo.flag ? 1 : 0),
  31. 0
  32. );
  33. },
  34. flag: {
  35. get() {
  36. //如果 已完成的数量 === 全部数量 默认全选
  37. return this.trueNum === this.allNUm && this.trueNum > 0;
  38. },
  39. set(value) {
  40. //value获取当前多选框的状态 勾选 true 不勾选 false
  41. this.updateFlagAll(value);
  42. },
  43. },
  44. },
  45. };
  46. </script>
  47. <style scoped>
  48. /*footer*/
  49. .todo-footer {
  50. height: 40px;
  51. line-height: 40px;
  52. padding-left: 6px;
  53. margin-top: 5px;
  54. }
  55. .todo-footer label {
  56. display: inline-block;
  57. margin-right: 20px;
  58. cursor: pointer;
  59. }
  60. .todo-footer label input {
  61. position: relative;
  62. top: -1px;
  63. vertical-align: middle;
  64. margin-right: 5px;
  65. }
  66. .todo-footer button {
  67. float: right;
  68. margin-top: 5px;
  69. }
  70. </style>

总结 

  1. 1、组件化编码流程:
  2. (1)、拆分静态组件:组件要按照功能点拆分,命名不要与html元素冲突
  3. (2)、实现动态组件:考虑好数据的存放位置,数据是一个在用,还是一堆组件再用
  4. 1)、一个组件在用:放在组件自身即可。
  5. 2)、一些组件在用:放在他们共同的父组件上(状态提升)
  6. (3)、实现交互:从绑定事件开始。
  7. 2、props适用于:
  8. (1)、父组件 ===> 子组件 通信 (父组件创建一个函数 写点方法 让子组件传入参数调用实现功能)
  9. (2)、子组件 ===> 父组件 通信 (要求父组件传过来一个函数 再通过上方的说明实现)
  10. 3、使用v-model 时要切记:v-model 绑定的值不能是 props传过来的值,因为props是 不可以修改的!
  11. 4、props传过来的若是对象类型的值,修改对象的属性时Vue不会报错 会提示破浪线 可以运行,但不推荐使用

更新

TodoList_本地存储

App.vue

  1. data() {
  2. return {
  3. //获取存储
  4. todoList: localStorage.getItem("todos") || [],
  5. };
  6. },
  7. watch: {
  8. todoList: {
  9. deep: true, //开启深度监视
  10. handler(value) {
  11. //这里获取的 value 是todoList 被修改后的值
  12. localStorage.setItem("todos", JSON.stringify(value)); //把值转为json格式字符串
  13. },
  14. },
  15. },

TodoList_自定义事件

App.vue

  1. <template>
  2. <div id="root">
  3. <div class="todo-container">
  4. <div class="todo-wrap">
  5. <todo-head @addTodo="addTodo" />
  6. <todo-list
  7. :todoList="todoList"
  8. :deleteTodo="deleteTodo"
  9. :updateFlag="updateFlag"
  10. />
  11. <todo-fotter
  12. :todoList="todoList"
  13. @updateFlagAll="updateFlagAll"
  14. @deleteFlagAll="deleteFlagAll"
  15. />
  16. </div>
  17. </div>
  18. </div>
  19. </template>
  20. //给底部组件标签绑定两个自定义事件 @updateFlagAll @deleteFlagAll

 todo-fotter.vue

  1. <template>
  2. <div class="todo-footer" v-show="allNUm">
  3. <label>
  4. <input type="checkbox" v-model="flag" />
  5. </label>
  6. <span>
  7. <span>已完成{{ trueNum }}</span> / 全部{{ allNUm }}
  8. </span>
  9. <button class="btn btn-danger" @click="delFlagAll">清除已完成任务</button>
  10. </div>
  11. </template>
  12. <script>
  13. export default {
  14. props: ["todoList"],
  15. methods: {
  16. delFlagAll() {
  17. //this.deleteFlagAll();
  18. this.$emit("deleteFlagAll");
  19. },
  20. },
  21. computed: {
  22. allNUm() {
  23. return this.todoList.length;
  24. },
  25. trueNum() {
  26. /* reduce 根据数组的长度 执行几次
  27. returnValue 每次的返回值
  28. todo 每次的实例
  29. 0 初始值 */
  30. return this.todoList.reduce(
  31. (returnValue, todo) => returnValue + (todo.flag ? 1 : 0),
  32. 0
  33. );
  34. },
  35. flag: {
  36. get() {
  37. //如果 已完成的数量 === 全部数量 默认全选
  38. return this.trueNum === this.allNUm && this.trueNum > 0;
  39. },
  40. set(value) {
  41. //value获取当前多选框的状态 勾选 true 不勾选 false
  42. //this.updateFlagAll(value);
  43. this.$emit("updateFlagAll", value);
  44. },
  45. },
  46. },
  47. };
  48. </script>
  49. <style scoped>
  50. /*footer*/
  51. .todo-footer {
  52. height: 40px;
  53. line-height: 40px;
  54. padding-left: 6px;
  55. margin-top: 5px;
  56. }
  57. .todo-footer label {
  58. display: inline-block;
  59. margin-right: 20px;
  60. cursor: pointer;
  61. }
  62. .todo-footer label input {
  63. position: relative;
  64. top: -1px;
  65. vertical-align: middle;
  66. margin-right: 5px;
  67. }
  68. .todo-footer button {
  69. float: right;
  70. margin-top: 5px;
  71. }
  72. </style>

TodoList_事件总线

main.js

  1. //引入vue
  2. import Vue from "vue";
  3. //引入组件App
  4. import App from "./App.vue";
  5. //关闭vue的生产提示
  6. Vue.config.productionTip = false;
  7. //创建vm
  8. new Vue({
  9. el: "#app",
  10. render: (h) => h(App),
  11. beforeCreate() {
  12. Vue.prototype.$bus = this; //设置全局事件总线
  13. },
  14. });

App.vue

  1. <template>
  2. <div id="root">
  3. <div class="todo-container">
  4. <div class="todo-wrap">
  5. <todo-head @addTodo="addTodo" />
  6. <todo-list :todoList="todoList" />
  7. <todo-fotter
  8. :todoList="todoList"
  9. @updateFlagAll="updateFlagAll"
  10. @deleteFlagAll="deleteFlagAll"
  11. />
  12. </div>
  13. </div>
  14. </div>
  15. </template>
  16. <script>
  17. import TodoList from "./components/todo-list.vue";
  18. import TodoHead from "./components/todo-head.vue";
  19. import TodoFotter from "./components/todo-fotter.vue";
  20. //引入组件
  21. export default {
  22. components: { TodoHead, TodoList, TodoFotter },
  23. name: "App",
  24. data() {
  25. return {
  26. //获取存储 使用JSON把字符解析成对象
  27. todoList: JSON.parse(localStorage.getItem("todos")) || [],
  28. };
  29. },
  30. methods: {
  31. //添加
  32. addTodo(todo) {
  33. this.todoList.unshift(todo); //在数组最前方添加u
  34. },
  35. //删除
  36. deleteTodo(id) {
  37. //过滤出 不是要删除id的 所有值
  38. this.todoList = this.todoList.filter((todo) => todo.id != id);
  39. },
  40. //删除全部已选的
  41. deleteFlagAll() {
  42. this.todoList = this.todoList.filter((todo) => todo.flag === false);
  43. },
  44. //修改指定事 是否完成
  45. updateFlag(id) {
  46. this.todoList.forEach((todo) => {
  47. if (todo.id === id) todo.flag = !todo.flag;
  48. });
  49. },
  50. //修改全部的 是否完成
  51. updateFlagAll(flag) {
  52. this.todoList.forEach((todo) => {
  53. todo.flag = flag;
  54. });
  55. },
  56. //删除指定的g
  57. },
  58. mounted() {
  59. this.$bus.$on("deleteTodo", this.deleteTodo); //gei$bus设置自定义事件
  60. this.$bus.$on("updateFlag", this.updateFlag);
  61. },
  62. beforeDestroy() {
  63. this.$bus.$off("deleteTodo", "updateFlag");
  64. },
  65. watch: {
  66. todoList: {
  67. deep: true, //开启深度监视
  68. handler(value) {
  69. //这里获取的 value 是todoList 被修改后的值
  70. localStorage.setItem("todos", JSON.stringify(value)); //把值转为json格式字符串
  71. },
  72. },
  73. },
  74. };
  75. </script>
  76. <style>
  77. /*base*/
  78. body {
  79. background: plum;
  80. }
  81. .btn {
  82. display: inline-block;
  83. padding: 4px 12px;
  84. margin-bottom: 0;
  85. font-size: 14px;
  86. line-height: 20px;
  87. text-align: center;
  88. vertical-align: middle;
  89. cursor: pointer;
  90. box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2),
  91. 0 1px 2px rgba(0, 0, 0, 0.05);
  92. border-radius: 4px;
  93. }
  94. .btn-danger {
  95. color: #fff;
  96. background-color: #da4f49;
  97. border: 1px solid #bd362f;
  98. }
  99. .btn-danger:hover {
  100. color: #fff;
  101. background-color: #bd362f;
  102. }
  103. .btn:focus {
  104. outline: none;
  105. }
  106. .todo-container {
  107. width: 600px;
  108. margin: 0 auto;
  109. }
  110. .todo-container .todo-wrap {
  111. padding: 10px;
  112. border: 1px solid #ddd;
  113. border-radius: 5px;
  114. }
  115. </style>

todo-list.vue

  1. <template>
  2. <ul class="todo-main">
  3. <todo-item v-for="todo in todoList" :key="todo.id" :todo="todo" />
  4. </ul>
  5. </template>
  6. props: ["todoList"],

todo-item.vue

  1. <template>
  2. <li>
  3. <label>
  4. <!-- change:元素发生修改时调用 -->
  5. <input type="checkbox" :checked="todo.flag" @change="upd(todo.id)" />
  6. <span>{{ todo.name }}</span>
  7. </label>
  8. <button class="btn btn-danger" @click="del(todo.id)">删除</button>
  9. </li>
  10. </template>
  11. <script>
  12. export default {
  13. props: ["todo"],
  14. methods: {
  15. del(id) {
  16. //this.deleteTodo(id);
  17. if (confirm("确认删除")) {
  18. this.$bus.$emit("deleteTodo", id);
  19. }
  20. },
  21. upd(id) {
  22. //this.updateFlag(id);
  23. this.$bus.$emit("updateFlag", id);
  24. },
  25. },
  26. };
  27. </script>
  28. <style scoped>
  29. /*item*/
  30. li {
  31. list-style: none;
  32. height: 36px;
  33. line-height: 36px;
  34. padding: 0 5px;
  35. border-bottom: 1px solid #ddd;
  36. }
  37. li label {
  38. float: left;
  39. cursor: pointer;
  40. }
  41. li label li input {
  42. vertical-align: middle;
  43. margin-right: 6px;
  44. position: relative;
  45. top: -1px;
  46. }
  47. li button {
  48. float: right;
  49. display: none;
  50. margin-top: 3px;
  51. }
  52. li:before {
  53. content: initial;
  54. }
  55. li:last-child {
  56. border-bottom: none;
  57. }
  58. li:hover {
  59. background-color: pink;
  60. }
  61. li:hover button {
  62. display: block;
  63. }
  64. </style>

TodoList_消息订阅于发布

       下载包

        全装 pubsub.js(消息发布与订阅库) 

 npm i pubsub-js

引入包 

  1. //引入订阅消息与发布库
  2. import pubsub from "pubsub-js";

App.vue

  1. mounted() {
  2. this.pubId = pubsub.subscribe("deleteTodo", this.deleteTodo); //设置消息订阅
  3. this.$bus.$on("updateFlag", this.updateFlag);
  4. },

todo-item.vue

  1. del(id) {
  2. if (confirm("确认删除")) {
  3. //this.deleteTodo(id);
  4. //this.$bus.$emit("deleteTodo", id);
  5. pubsub.publish("deleteTodo", id); //发送消息
  6. }
  7. },

TodoList_nextTick

todo-item.vue

  1. <template>
  2. <li>
  3. <label>
  4. <!-- change:元素发生修改时调用 -->
  5. <input type="checkbox" :checked="todo.flag" @change="upd(todo.id)" />
  6. <span v-show="!todo.isEdit">{{ todo.name }}</span>
  7. <input
  8. type="text"
  9. :value="todo.name"
  10. v-show="todo.isEdit"
  11. @blur="nameBlur($event, todo)"
  12. ref="inputFocus"
  13. />
  14. </label>
  15. <button class="btn btn-danger" @click="del(todo.id)">删除</button>
  16. <button v-show="!todo.isEdit" class="btn btn-edit" @click="updName(todo)">
  17. 编辑
  18. </button>
  19. </li>
  20. </template>
  21. <script>
  22. //引入订阅消息与发布库
  23. import pubsub from "pubsub-js";
  24. export default {
  25. props: ["todo"],
  26. methods: {
  27. del(id) {
  28. //this.deleteTodo(id);
  29. if (confirm("确认删除")) {
  30. //this.$bus.$emit("deleteTodo", id);
  31. pubsub.publish("deleteTodo", id);
  32. }
  33. },
  34. upd(id) {
  35. //this.updateFlag(id);
  36. this.$bus.$emit("updateFlag", id);
  37. },
  38. updName(todo) {
  39. if ("isEdit" in todo) {
  40. //判断该对象 有没有 isEdit属性
  41. todo.isEdit = true;
  42. } else {
  43. console.log("@");
  44. this.$set(todo, "isEdit", true);
  45. }
  46. // $nextTick() 会在模板解析下一次执行里面的函数
  47. this.$nextTick(() => this.$refs.inputFocus.focus());
  48. },
  49. nameBlur(event, todo) {
  50. todo.isEdit = false;
  51. if (!event.target.value.trim()) return alert("不能为空");
  52. //字符 有值的时候 返回的是 true 没有返回 false
  53. this.$bus.$emit("updateName", todo.id, event.target.value);
  54. },
  55. },
  56. };
  57. </script>
  58. <style scoped>
  59. /*item*/
  60. li {
  61. list-style: none;
  62. height: 36px;
  63. line-height: 36px;
  64. padding: 0 5px;
  65. border-bottom: 1px solid #ddd;
  66. }
  67. li label {
  68. float: left;
  69. cursor: pointer;
  70. }
  71. li label li input {
  72. vertical-align: middle;
  73. margin-right: 6px;
  74. position: relative;
  75. top: -1px;
  76. }
  77. li button {
  78. float: right;
  79. display: none;
  80. margin-top: 3px;
  81. }
  82. li:before {
  83. content: initial;
  84. }
  85. li:last-child {
  86. border-bottom: none;
  87. }
  88. li:hover {
  89. background-color: pink;
  90. }
  91. li:hover button {
  92. display: block;
  93. }
  94. </style>

TodoList_动画

todo-list.vue

  1. <template>
  2. <!-- 普通的动画 -->
  3. <!-- <ul class="todo-main">
  4. <transition-group name="todo" appear>
  5. <todo-item v-for="todo in todoList" :key="todo.id" :todo="todo" />
  6. </transition-group>
  7. </ul> -->
  8. <!-- 第三方库动画 -->
  9. <ul class="todo-main">
  10. <transition-group
  11. name="animate__animated animate__bounce"
  12. appear
  13. enter-active-class="animate__bounce"
  14. leave-active-class="animate__backOutDown"
  15. >
  16. <todo-item v-for="todo in todoList" :key="todo.id" :todo="todo" />
  17. </transition-group>
  18. </ul>
  19. </template>
  20. <script>
  21. //引入
  22. import "animate.css";
  23. import todoItem from "./todo-item.vue";
  24. export default {
  25. components: { todoItem },
  26. props: ["todoList"],
  27. };
  28. </script>
  29. <style scoped>
  30. /*main*/
  31. .todo-main {
  32. margin-left: 0px;
  33. border: 1px solid #ddd;
  34. border-radius: 2px;
  35. padding: 0px;
  36. }
  37. .todo-empty {
  38. height: 40px;
  39. line-height: 40px;
  40. border: 1px solid #ddd;
  41. border-radius: 2px;
  42. padding-left: 5px;
  43. margin-top: 10px;
  44. }
  45. /* 普通的动画 */
  46. /* .todo-enter-active {
  47. animation: goto 1s linear;
  48. }
  49. .todo-leave-active {
  50. animation: goto 1s linear reverse;
  51. }
  52. @keyframes goto {
  53. from {
  54. transform: translateX(-100%);
  55. }
  56. to {
  57. transform: translateX(0%);
  58. }
  59. } */
  60. </style>

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/凡人多烦事01/article/detail/223846
推荐阅读
相关标签
  

闽ICP备14008679号