使用 Webpack 打造 vue - todo 应用实践( 四)
之前进行了webpack的相关配置,现在我们lai 实现一下具体页面
重构了目录结构
-src - assets - images - background-image.jpg - done.svg - round.svg - styles - footer.styl - global.styl - todo - footer.jsx - header.vue - item.vue - tabs.vue - todo.vue - app.vue // 模板文件 - index.js // 入口文件 -package.json -webpack.config.js代码实现
// footer.styl #footer margin 40px text-align: center color: #eee font-size 15px text-shadow 0 3px 0 2px #eee
// global.styl html, body margin 0 padding 0 width 100% height 100% body background-image url(../images/background-image.jpg) background-size cover background-position center font 14px 'microsoft yahei' color #000000 font-weight 500
// index.js import Vue from 'vue' import App from './app.vue' import './assets/styles/global.styl' const root = document.createElement('div'); // 根节点 document.body.appendChild(root); new Vue({ render: (h)=> h(App) // 将App渲染至根节点 }).$mount(root)
// app.vue <template> <div id="app"> <div class="cover"> <m-header></m-header> <todo></todo> <Footer></Footer> </div> </div> </template> <script> import MHeader from './todo/header.vue' import Footer from './todo/footer.jsx' import Todo from './todo/todo.vue' export default { data() { return { test: "testsdsassadds" }; }, components: { MHeader, Footer, Todo } }; </script> <style lang="stylus" scoped> #app position absolute left 0 right 0 top 0 bottom 0 .cover position absolute left 0 right 0 top 0 bottom 0 background-color #555 opacity 0.5 z-index 1 </style>
// header.vue <template> <header class="main-header"> <h1>Meils - todo</h1> </header> </template> <style lang="stylus" scoped> .main-header text-align: center h1 font-size: 80px color rgba(175, 47, 47, 1) margin: 20px </style>
// footer.jsx import '../assets/styles/footer.styl' export default{ data () { return { author: 'Meils', blog: 'scopedSlots' } }, render() { return ( <div id="footer"> <span>Power by {this.author},欢迎访问作者博客:{this.blog}</span> </div> ) } }
// item.vue <template> <div :class="['todo-item', todo.completed ? 'completed' : '']"> <input type="checkbox" class="toggle" v-model="todo.completed" > <label class="label">{{todo.content}}</label> <button class="destroy" @click="deleteTodo"></button> </div> </template> <script> export default { props: { todo : { type: Object, require: true } }, methods: { deleteTodo () { // this.$emit 触发del事件,并返回 todo.id this.$emit('del', this.todo.id) } } } </script> <style lang="stylus" scoped> .todo-item{ position relative background-color #fff font-size 16px border-bottom 1px solid rgba(0,0,0,0.06) &:hover{ .destroy:after{ content: '×' } } label{ white-space: pre-line; word-break: break-all; padding: 15px 60px 15px 15px; margin-left: 45px; display: block; line-height: 1.2; transition: color 0.4s; } &.completed{ label{ color: #d9d9d9; text-decoration line-through } } } .toggle{ text-align: center; width: 40px; height: 40px; line-height: 40px position: absolute; top: 0; bottom: 0; margin: auto 0; border: none; appearance: none; outline none padding-left 5px cursor pointer &:after{ content: url('../assets/images/round.svg') } &:checked:after{ content: url('../assets/images/done.svg') } } .destroy{ position: absolute; top: 0; right: 10px; bottom: 0; width: 40px; height: 40px; margin: auto 0; font-size: 30px; color: #cc9a9a; margin-bottom: 11px; transition: color 0.2s ease-out; background-color transparent appearance none border-width 0 cursor pointer outline none } </style>
// tabs.vue <template> <div class="helper"> <span class="left">{{unFinishedTodoLength}} 项待办</span> <span class="tabs"> <span v-for="state in states" :key="state" :class="[state, filter === state ? 'actived' : '']" @click="toggleFilter(state)" > {{state}} </span> </span> <span class="clear" @click="clearAllCompleted()"> 清空 </span> </div> </template> <script> export default { // props 接收父组件传过来的值 props: { filter: { type: String, required: true, }, todos: { type: Array, required: true } }, data() { return { states: ['all', 'active', 'completed'] } }, computed: { unFinishedTodoLength() { return this.todos.filter(todo => !todo.completed).length; } }, methods: { toggleFilter(state) { // 由父组件触发实现 this.$emit('toggle', state); }, clearAllCompleted() { this.$emit('clearAllCompleted'); } } } </script> <style lang="stylus" scoped> .helper { font-weight 100 display flex justify-content space-between padding 5px 0 line-height 30px background-color #ffffff font-size 14px font-smoothing: antialiased; } .left, .clear, .tabs { padding 0 10px box-sizing border-box } .left, .clear { width 150px } .left { text-align left } .clear { text-align: right cursor pointer } .tabs { width 200px display flex justify-content space-around * { display inline-block padding 0 10px cursor pointer border 1px solid rgba(175, 47, 47, 0) &.actived { border-color rgba(175, 47, 47, 0.4) border-radius 5px } } } </style>
// todo.vue <template> <section class="real-app"> <input type="text" class="add-input" autofocus="autofocus" placeholder="接下来要做什么?" @keyup.enter="addTodo($event)"> <items :todo="todo" v-for="todo in filteredTodos" :key="todo.id" @del="del"></items> <tabs @clearAllCompleted="clearAllCompleted" :filter="filters" :todos="todos" @toggle="toggleFilter"></tabs> </section> </template> <script> import Items from './item.vue' import Tabs from './tabs.vue' let id = 0; export default { data () { return { todos: [], filters: 'all' } }, computed: { filteredTodos() { if (this.filters === 'all') { return this.todos } const completed = this.filters === 'completed'; // 将todos数组中,completed为true的值过滤出来,并返回一个新数组 return this.todos.filter(todo => completed === todo.completed); } }, methods: { addTodo (e) { this.todos.unshift({ id: id++, content: e.target.value.trim(), completed: false }) }, del (id) { this.todos.splice(this.todos.findIndex(todo => todo.id === id), 1) // findIndex方法接受一个函数,返回对应元素的索引值, /* 获取数组中年龄大于 18 的第一个元素索引位置 var ages = [3, 10, 18, 20]; function checkAdult(age) { return age >= 18; } function myFunction() { document.getElementById("demo").innerHTML = ages.findIndex(checkAdult); } // 2 */ }, toggleFilter(state) { this.filters = state }, clearAllCompleted() { // 给todos赋一个新的值(即todo.completed为false的值) this.todos = this.todos.filter(todo => todo.completed === false) } }, components: { Items, Tabs } } </script> <style lang="stylus" scoped> .real-app width: 700px margin: 0px auto box-shadow : 0 0 5px #666666 .add-input position: relative margin: 0 width: 100% font-size: 20px font-family: inherit font-weight: inherit line-height: 1.4em border: 0 outline: none color: inherit box-sizing: border-box font-smoothing: antialiased padding: 16px 16px 16px 60px border: none box-shadow: inset 0 -2px 1px rgba(0, 0, 0, 0.03) </style>未完待续 ~~ 下一篇会是webpack的一些优化
相关推荐
gloria0 2020-10-26
gloria0 2020-08-09
hline 2020-07-29
不知道该写啥QAQ 2020-07-18
不知道该写啥QAQ 2020-11-12
webfullStack 2020-11-09
Yvettre 2020-09-15
想做大牛的蜗牛 2020-10-30
gaojie0 2020-09-11
SelinaChan 2020-08-14
不知道该写啥QAQ 2020-08-09
不知道该写啥QAQ 2020-08-02
SelinaChan 2020-07-28
wangdianyong 2020-07-23
webpackvuees 2020-07-23
yqoxygen 2020-07-20
waterv 2020-07-18
81463166 2020-07-17