“最难不过坚持”
本人承接扒站仿站,php网站维护,病毒查杀,网站编辑,网站改版,html制作
有需要网站维护,改版,病毒查杀,网站编辑,网站备案,html制作等相关的工作可以联系我。
本人有多年相关工作经验,也可提供免费咨询,交个朋友。
有需要探讨问题的朋友,也可以加我微信,共同探讨!
微信:15011482830 QQ:408917339
- https://jueru.net/
-
- :weixiao:
-
- :shuijiao: :weiqu: :zhenbang: :leng:
-
- :yiwen: :yiwen: :yiwen: :yiwen:
-
- 这个业务逻辑多少都有点奇怪了,阅读浏览次数增值在新闻详情页的控制器方法里setInc,这怎么还写进模型事件里了。如果非要用onAfterRead也可以,把新闻文章的内容单独分出来一个news_content表,然后把它和news做关联,然后给news_content表的onAfterRead事件做增值处理,这样点进新闻页内查询到文章内容时才会触发它。
-
案例的效果如下
一、组件化编码流程:
(1).拆分静态组件:组件要按照功能点拆分,命名不要与html元素冲突。
(2).实现动态组件:考虑好数据的存放位置,数据是一个组件在用,还是一些组件在用:
1).一个组件在用:放在组件自身即可。
2). 一些组件在用:放在他们共同的父组件上(状态提升)。
(3).实现交互:从绑定事件开始。
拆分好的页面结构如下:
1,App组件
<template> <div id="app"> <TodoHeader/> <TodoList :todos="todos"/> <TodoFooter :todos="todos"/> </div> </template> <script> import pubsub from 'pubsub-js' import TodoHeader from './components/TodoHeader.vue' import TodoList from './components/TodoList.vue' import TodoFooter from './components/TodoFooter.vue' export default { name: 'App', components: { TodoHeader,TodoList,TodoFooter }, data(){ return{ // todos:[ // {id:'001',title:'吃饭',done:true}, // {id:'002',title:'睡觉',done:false}, // {id:'003',title:'打豆豆',done:false}, // ] todos:JSON.parse(localStorage.getItem('todos')) || [] } }, // 监视 watch:{ todos:{ deep:true, // 深度监视 handler(value){ localStorage.setItem('todos',JSON.stringify(value)) } } }, methods: { // 添加任务 addTodo(_,obj){ this.todos.unshift(obj) }, // 选中/取消 checkTodo(_,id){ this.todos.forEach((todo)=>{ if(todo.id === id) todo.done = !todo.done }) }, // 删除 deleteTodo(_,id){ this.todos = this.todos.filter((todo)=>{ return todo.id != id }) }, // 修改 updateTodo(_,data){ // console.log('updateTodo:',data.title); this.todos.forEach((todo)=>{ if(todo.id == data.id) todo.title = data.title }) }, // 清除已完成 clearAllTodo(){ this.todos = this.todos.filter((todo)=>{ return !todo.done }) }, // 全选 checkAllTodo(_,done){ this.todos.forEach((todo)=>{ todo.done = done }) } }, // 挂载 mounted() { // 消息订阅与发布-订阅 this.addTodoId = pubsub.subscribe('addTodo',this.addTodo) this.checkTodoId = pubsub.subscribe('checkTodo',this.checkTodo) this.deleteTodoId = pubsub.subscribe('deleteTodo',this.deleteTodo) this.updateTodoId = pubsub.subscribe('updateTodo',this.updateTodo) this.clearAllTodoId = pubsub.subscribe('clearAllTodo',this.clearAllTodo) this.checkAllTodoId = pubsub.subscribe('checkAllTodo',this.checkAllTodo) }, // 销毁前 beforeDestroy() { pubsub.unsubscribe(this.addTodoId) pubsub.unsubscribe(this.checkTodoId) pubsub.unsubscribe(this.deleteTodoId) pubsub.unsubscribe(this.updateTodoId) pubsub.unsubscribe(this.clearAllTodoId) pubsub.unsubscribe(this.checkAllTodoId) }, } </script> <style> </style>2,TodoHeader组件
<template> <div> <input type="text" @keyup.enter="add"> </div> </template> <script> import {nanoid} from 'nanoid' import pubsub from 'pubsub-js' export default { name:'TodoHeader', methods: { add(e){ if(!e.target.value.trim()) return alert('输入不能为空') const todoObj = {id:nanoid(),title:e.target.value,done:false} // console.log(todoObj); // 消息订阅与发布-发布 pubsub.publish('addTodo',todoObj) e.target.value = '' } }, } </script> <style> </style>3,TodoList组件
<template> <div> <ul> <TodoItem v-for="todo in todos" :key="todo.id" :todo="todo"/> </ul> </div> </template> <script> import TodoItem from './TodoItem.vue' export default { name:'TodoList', components:{ TodoItem }, props:['todos'] } </script> <style> </style>4,TodoItem组件
<template> <li> <input type="checkbox" :checked="todo.done" @change="handleCheck(todo.id)"> <span v-show="!todo.isEdit">{{todo.title}}</span> <input type="text" v-show="todo.isEdit" :value="todo.title" @blur="handleBlur(todo,$event)" ref="inputTitle"> <button v-show="!todo.isEdit" @click="handleEdit(todo)">编辑</button> <button @click="handleDelete(todo.id)">删除</button> </li> </template> <script> import pubsub from 'pubsub-js' export default { name:'TodoItem', props:['todo'], methods: { // 选中/取消 handleCheck(id){ pubsub.publish('checkTodo',id) }, // 删除 handleDelete(id){ pubsub.publish('deleteTodo',id) }, // 编辑 handleEdit(todo){ // 判断是否保护isEdit属性 if(todo.hasOwnProperty('isEdit')){ todo.isEdit = true }else{ this.$set(todo,'isEdit',true) } // 点击编辑按钮,输入框自动获得焦点 this.$nextTick(function(){ this.$refs.inputTitle.focus() }) }, // 失去焦点,提交修改 handleBlur(todo,e){ // 编辑状态改为false todo.isEdit = false if(!e.target.value.trim()) return alert('输入不能为空') // console.log(e.target.value); pubsub.publish('updateTodo',{id:todo.id,title:e.target.value}) } }, } </script> <style scoped> button{ display: none; } li:hover{ background: #eee; } li:hover button{ display: inline; } </style>5,TotoFooter组件
<template> <div v-show="total"> <!-- 方式一 --> <!-- <input type="checkbox" :checked="isAll" @change="checkAll"> --> <!-- 方式二 --> <input type="checkbox" v-model="isAll"> 已完成{{doneTotal}} / 全部 {{total}} <button @click="clearAll">清除已完成</button> </div> </template> <script> import pubsub from 'pubsub-js' export default { name:'TodoFooter', props:['todos'], computed:{ total(){ return this.todos.length }, doneTotal(){ return this.todos.reduce((pre,todo)=>{ return pre + (todo.done ? 1 : 0) },0) }, isAll:{ get(){ return this.total === this.doneTotal }, set(value){ pubsub.publish('checkAllTodo',value) } } }, methods:{ clearAll(){ // 消息订阅与发布-发布 pubsub.publish('clearAllTodo') }, checkAll(e){ pubsub.publish('checkAllTodo',e.target.checked) } } } </script> <style> </style>
其他:
1,nanoid生成唯一id
安装:
npm i nanoid
使用:
import { nanoid } from 'nanoid';
let id = nanoid()
2,pubsub-js消息订阅与发布
安装:
npm i pubsub-js
使用:
import PubSub from 'pubsub-js'
// 发布消息
PubSub.publish('msg', data)
// 订阅消息
PubSub.subscribe('msg', function(msg, data){})
3,本地存储
Window.sessionStorage--存储的内容会随着浏览器窗口关闭而消失
Window.localStorage --存储的内容,需要手动清除才会消失。
以上两种存储方式,它们的API是完全相同的。主要区别就在是否是会存储到本地。相关API如下:
☆添加:xxxxxStorage.setItem('key', 'value');
☆获取:xxxxxStorage.getItem('person');
☆删除:xxxxxStorage.removeItem('key');
☆清空:xxxxxStorage.clear()
在必要的时候搭配JSON.stringify和JSON.parse方法使用。
注意:xxxxxStorage.getItem(xxx) 如果xxx对应的value获取不到,那么getItem的返回值是null。JSON.parse(null)的结果依然是null。