概述
这门课在慕课网是免费的,但有部分包已被弃用需要用其他包代替,详细见官网。我还不想看官网,所以先放着吧。
关于模块打包的课程可以重刷
【仅个人记录,还不完整。暂时没有参考意义哦】
别人的项目源码、我的项目源码
实现的布局图
MockPlus还不会用,随便弄的
实现出来的效果
线上效果
项目结构
步骤
1、编写app.vue
根据布局图可以写出大概的框架
<template>
<div id="app">
<div id="cover"></div> <!-- 背景 -->
<Header></Header>
<Todo></Todo>
<Footer></Footer>
</div>
</template>
<script>
import Header from './todo/header.vue'
import Footer from './todo/footer.jsx'
import Todo from './todo/todo.vue'
export default {
components:{
Header,
Todo,
Footer
}
}
</script>
<style lang="stylus" scoped>
/* 这里就不贴啦,详细的见源代码叭 */
</style>
另外,header.vue 和 footer.vue都很简单,主要讲todo.vue
2、todo.vue
todo组件由input(输入框)、item组件 和 tabs组件组成。
item组件:显示todo的项目。而数据todo是由todo.vue里传去的(父组件到子组件),因此会用到绑定属性。
tabs组件:由布局图可知。
todo组件先实现input:
<!-- todo.vue -->
<template>
<section class="real-app">
<input
type="text"
class="add-input"
autofocus="autofocus"
placeholder="接下去要做什么?"
@keyup.enter="addTodo"
/>
</section>
</template>
<script>
export default {
methods: {
addTodo() {}
}
};
</script>
3、item.vue
item.vue实现"1条todo项目的显示",用到props将数据todo(是一个对象) 从父组件(todo.vue)传到子组件(item.vue)。而且,item还有一个功能是删除,由于数据在父组件里,因此要用到emit(数据从子组件传到父组件),即写一个触发事件 this.$emit('del', this.todo.id) ,将数据(this.todo.id)从子组件传到父组件,再在父组件里删除相应的数据。
item.vue里用到了v-model="todo.completed",这个双向绑定是将item组件的todo.completed与todo组件的todo.completed绑在一起。
item.vue还用到了:class,因为想实现“当复选框为checked时,增加一条删除线表示已完成”的效果,所以会有两种不同的状态:勾选和未勾选,因此class属于动态属性,动态属性需要绑定。
<!-- item.vue -->
<template>
<div :class="['todo-item', todo.completed ? 'completed' : '']">
<input type="checkbox" class="toggle" v-model="todo.completed" />
<label>{{todo.content}}</label>
<button class="destory" @click="deleteTodo"></button>
</div>
</template>
<script>
export default {
props: {
todo: {
type: Object,
required: true
}
},
methods: {
deleteTodo() {
this.$emit('del', this.todo.id);
}
}
};
</script>
<!-- todo.vue -->
<template>
<section class="real-app">
<!-- ... -->
<Item
v-for="todo in todos"
:todo="todo"
:key="todo.id"
@del = "deleteTodo"
/>
</section>
</template>
<script>
import Item from "./item.vue";
let id = 0;
export default {
data() {
return {
todos:[]
};
},
components: {
Item
},
methods: {
addTodo(e) {
this.todos.unshift({
id:id++,
content:e.target.value.trim(),
completed:false
});
e.target.value = '';
},
deleteTodo(id){
this.todos.splice(this.todos.findIndex(todo => todo.id === id), 1);
}
}
};
</script>
findIndex() 方法返回传入一个测试条件(函数)符合条件的数组第一个元素位置。
findIndex() 方法为数组中的每个元素都调用一次函数执行:
- 当数组中的元素在测试条件时返回 true 时, findIndex() 返回符合条件的元素的索引位置,之后的值不会再调用执行函数。
- 如果没有符合条件的元素返回 -1
注意: findIndex() 对于空数组,函数是不会执行的。
注意: findIndex() 并没有改变数组的原始值。
4、tabs.vue
filter是父组件传来的属性,表示的是选中的某一个状态(all、actived或completed)。利用filter与三种状态进行对比,会将与filter匹配成功的state增加一个class值:actived(激活),利用动态的class属性 :class
filter如何得到选中的状态值呢?子组件(tabs.vue)将state值通过emit传到父组件(todo.vue)里的filter中。子组件里点击中间的按钮,会直接调用toggleFilter函数,这个函数会调用emit。注意,中间的三个按钮的显示是利用了v-for遍历,在遍历的同时,对每个按钮绑定了click事件。
一个思考:为什么要在顶级组件(todo.vue)里弄一个filter呢?如果是单纯为了改actived样式,直接在tabs组件里就能实现,为什么要通过子组件传给父组件,再由父组件传给子组件这么麻烦呢?(在tabs里直接实现的想法是:在data属性里增加一个变量用来存当前按下的按钮值就好了)
<!-- tabs.vue -->
<template>
<div class="helper">
<span class="left"><!-- 左 -->
<span> {{unFinishTodoLength}} items left</span>
</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">Clear completed</span>
</div>
</template>
<script>
export default {
props:{
filter:{
type:String,
required:true
},
todos:{
type: Array,
required:true
}
},
data(){
return{
states:['all','active','completed']
}
},
computed:{
unFinishTodoLength(){
return this.todos.filter(todo => !todo.completed).length;
}
},
methods:{
toggleFilter(state){
this.$emit('toggle', state);
},
clearAllCompleted(){
this.$emit('clearAllCompleted');
}
}
}
</script>
<!-- todo.vue -->
<template>
<section class="real-app">
<input />
<Item />
<Tabs
:filter="filter"
:todos="todos"
@toggle = 'toggleFilter'
@clearAllCompleted = 'clearAllCompleted'
/>
</section>
</template>
<script>
import Item from "./item.vue";
import Tabs from "./tabs.vue";
let id = 0;
export default {
data() {
return {
todos:[],
filter:'all'
};
},
components: {
Item,
Tabs
},
computed:{
filteredTodos(){
if(this.filter === 'all'){
return this.todos;
}
const completed = this.filter === 'completed'; //filter是当前用户选择想看的是哪个。active、completed
return this.todos.filter(todo => todo.completed === completed);//这个的思路可以细品
}
},
methods: {
addTodo(e) {
//...
},
deleteTodo(id){
//...
},
toggleFilter(state){
this.filter = state;
},
clearAllCompleted(){
this.todos = this.todos.filter(todo => !todo.completed);
}
}
};
</script>
还有一些零碎的东西,具体就见源代码叭
学习笔记:
- 学习如何工程化比业务开发更重要
- 前端价值
- 搭建前端工程,如数据缓存
- 网络优化,如加快http请求的速度
- API定制
- nodejs层
- 新建项目的步骤
- npm init(生成包管理文件package.json)
- npm i webpack vue vue-loader(这里没有区分生产环境和开发环境)
- 把出现了WARN和peer(第三方依赖)两个单词的文件也进行安装
- 新建.gitignore文件让git忽略node_modules文件
- 配置Webpack
- 热加载:当修改部分代码时只改动对应的功能,而不会刷新界面。好处:不会丢失前面操作的数据
- vue的学习
- 数据的传递
- 数据从父组件传到子组件要用props
- 数据从子组件传到父组件要用emit、on
- “数据在哪里声明,就在哪里进行操作”
- 使用v-for要绑定唯一的key属性,因为循环是一个非常耗时耗资源的操作,指定了key之后,下一次循环如果key值相同,vue是会复用当前的节点,而不会生成一个新的节点。这样可以提高性能
- v-bind与v-model还不太清晰
- 在交互实现中经常用到数组的filter方法(todo.vue文件)
- 实现界面的步骤是先实现基本的界面,比如
,再实现交互,比如<span>2 items left</span>
<span>{{unFinishTodoLength}} items left </span>
- 数据的传递
- jsx是通过babel编译的,因此课程里有下载babel的操作。
- 不管是vue还是react,最后都是解析成render方法,然后进行dom的插入(说法貌似不准确,还需要确定)
- ChunkHash与hash。使用ChunkHash的话,每个chunk都会有一个不同的hash值。
- 打包和优化的课程没怎么听懂,由于课程提到的配置Commons ChunkPlugin都弃用了,自己没有重新配。
- 参考链接1,参考链接2,参考链接3,参考链接4
- 讲师对前端的看法。链接
- 前端开发不仅仅是业务开发,最好学会做方便自己开发的流程(类似于dev-server这样的工具)推荐:Webpack官网
- 眼界要放宽:先了解作为一个前端工程要去解决一个什么问题
参考链接
- webpack打包踩坑之TypeError: Cannot read property 'bindings' of null
- cross-env使用
- webpack-dev-server使用方法,看完还不会的来找我~
最后
以上就是端庄小甜瓜为你收集整理的Vue+Webpack打造todo应用(慕课学习笔记)实现的布局图实现出来的效果项目结构步骤 学习笔记:参考链接的全部内容,希望文章能够帮你解决Vue+Webpack打造todo应用(慕课学习笔记)实现的布局图实现出来的效果项目结构步骤 学习笔记:参考链接所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复