我如何在 Vue-cli 中使用道具、$ref 和 $emit?
How can I use props, $ref and $emit in Vue-cli?
我一直在用 Vue-cli 学习 Vuejs。
我正在尝试了解 props
和 $emit
的工作原理。
我无法弄清楚的一件事是如何处理与多个组件相关的 function
。
All
、Ongoing
、Done
按钮应该根据每个复选框的值过滤列表,并且在激活时其颜色变为绿色。
我不知道把我目前在 ListTodo.vue
中添加的 filteredTodos() {}
东西放在哪里,因为它们在 Swichers.vue
和 ListTodo.vue
中都是相关的。
我的代码是:Here
如果有人知道,你能告诉我怎么做吗?
谢谢
本着 vuejs 的精神,避免引用并在子组件中拥有状态会更好。
该应用程序包含项目和过滤器,todolist.vue 将道具绑定到过滤列表(计算 属性)。
切换器在过滤器上采用 v 模型(双向绑定)。
全部删除作为回调传递 属性。
(编辑)
App.vue
<template>
<div>
<h1>TODO</h1>
<input type="text" v-model="inputTask" placeholder="Enter your task">
<button @click="addTask">Add task</button>
<Switchers
v-model='filter'
:onRemoveAll="removeAllItem"
/>
<ListTodo :todos='filtered' :noTask='noTask' :onRemoveTask='removeTask' :onToggleStatus='toggleStatus' />
</div>
</template>
<script>
import Switchers from "./components/Switchers";
import ListTodo from "./components/ListTodo";
export default {
keyName: 'myTodoList',
components: {
Switchers,
ListTodo,
},
created() {
let keyObject =JSON.parse(localStorage.getItem(this.keyName))
if (keyObject) {
this.todos = keyObject;
}
},
data() {
return {
inputTask: '',
// filtered:'',
filter: 'all',
todos: [],
};
},
computed: {
filtered() {
this.filter; this.todos;
return this.filteredTodos()
},
id() { return this.todos.length+1 },
noTask() {
return {
'all': 'No tasks',
'ongoing': 'No ongoing tasks',
'done': 'No done tasks',
}[this.filter]
},
},
methods: {
addTask() {
if (this.inputTask==='') {
return
}
this.addTaskChild(this.inputTask);
this.inputTask=''
},
addTaskChild(inputValue) {
const todo = {id: this.id, task:inputValue, done:false}
this.todos.push(todo)
localStorage.setItem(this.keyName, JSON.stringify(this.todos));
this.filter = 'all'
},
removeAllItem() {
this.todos = []
localStorage.clear();
this.filter = 'all'
},
filteredTodos() {
return this.todos.filter(todo => {
if (this.filter === 'ongoing') {
return !todo.done;
} else if (this.filter === 'done') {
return todo.done;
} else {
return true;
}
});
},
toggleStatus(todo) {
todo.done = !todo.done
localStorage.setItem(this.keyName, JSON.stringify(this.todos));
},
removeTask(t) {
this.todos = this.todos.filter(todo => todo.id !== t.id)
},
}
};
</script>
ListTodo.vue
<template>
<div>
<p>{{todos.length}} tasks left / {{todos.length}} tasks of all</p>
<ul>
<li v-for="todo in todos" :class="{done:todo.done}" :key="todo.id">
<input type="checkbox" :checked="todo.done" @click="status(todo)">
{{ todo.task }}
<button @click="onRemoveTask(todo)">Remove task</button>
</li>
</ul>
<p v-show="todos.length===0">{{noTask}}</p>
</div>
</template>
<script>
export default {
props: {
todos: {
type: Array,
required: true
},
onRemoveTask: {
type: Function,
required: true
},
onToggleStatus: {
type: Function,
required: true
},
noTask: {
type: String,
required: true
}
},
data() {
return {
id: 1,
done:false,
};
},
methods: {
status(todo) {
this.onToggleStatus(todo)
},
},
};
</script>
Switchers.vue
<template>
<div>
<button :class="{active: filter ==='all'}" @click="set_filter('all')">All</button>
<button :class="{active: filter ==='ongoing'}" @click="set_filter('ongoing')">Ongoing</button>
<button :class="{active: filter ==='done'}" @click="set_filter('done')">Done</button>
<button @click="onRemoveAll">Remove all</button>
</div>
</template>
<script>
export default {
props: {
value: {
type: String,
required: true
},
onRemoveAll: {
type: Function,
required: true
}
},
watch: {
value: {
handler(v) {
if (this.filter !== v)
this.filter = v
},
immediate: true
}
},
data() {
return {
filter:'',
};
},
methods: {
set_filter(f) {
this.filter = f
this.$emit('input', f)
},
},
};
</script>
<style lang="scss" scoped>
.active {background: turquoise;}
</style>
地道的 vuejs 更喜欢响应式属性而不是命令式样式。在这种情况下,我们宁愿保留一份待办事项列表 + 过滤条件(在 App 中),并为下一个 ID、过滤列表和 noTask 消息公开计算属性。
Switchers
是一个纯控制器组件:它没有状态,它的唯一作用是转换用户选择以调用 App 模型。
ListTodo
是一个视图,只负责显示作为道具给出的待办事项列表。它不关心列表是否被过滤。
也可以进行一些小的样式更改,但它们与 vuejs / emit 没有任何关系,所以我没有进行。
我一直在用 Vue-cli 学习 Vuejs。
我正在尝试了解 props
和 $emit
的工作原理。
我无法弄清楚的一件事是如何处理与多个组件相关的 function
。
All
、Ongoing
、Done
按钮应该根据每个复选框的值过滤列表,并且在激活时其颜色变为绿色。
我不知道把我目前在 ListTodo.vue
中添加的 filteredTodos() {}
东西放在哪里,因为它们在 Swichers.vue
和 ListTodo.vue
中都是相关的。
我的代码是:Here
如果有人知道,你能告诉我怎么做吗?
谢谢
本着 vuejs 的精神,避免引用并在子组件中拥有状态会更好。
该应用程序包含项目和过滤器,todolist.vue 将道具绑定到过滤列表(计算 属性)。 切换器在过滤器上采用 v 模型(双向绑定)。 全部删除作为回调传递 属性。
(编辑)
App.vue
<template>
<div>
<h1>TODO</h1>
<input type="text" v-model="inputTask" placeholder="Enter your task">
<button @click="addTask">Add task</button>
<Switchers
v-model='filter'
:onRemoveAll="removeAllItem"
/>
<ListTodo :todos='filtered' :noTask='noTask' :onRemoveTask='removeTask' :onToggleStatus='toggleStatus' />
</div>
</template>
<script>
import Switchers from "./components/Switchers";
import ListTodo from "./components/ListTodo";
export default {
keyName: 'myTodoList',
components: {
Switchers,
ListTodo,
},
created() {
let keyObject =JSON.parse(localStorage.getItem(this.keyName))
if (keyObject) {
this.todos = keyObject;
}
},
data() {
return {
inputTask: '',
// filtered:'',
filter: 'all',
todos: [],
};
},
computed: {
filtered() {
this.filter; this.todos;
return this.filteredTodos()
},
id() { return this.todos.length+1 },
noTask() {
return {
'all': 'No tasks',
'ongoing': 'No ongoing tasks',
'done': 'No done tasks',
}[this.filter]
},
},
methods: {
addTask() {
if (this.inputTask==='') {
return
}
this.addTaskChild(this.inputTask);
this.inputTask=''
},
addTaskChild(inputValue) {
const todo = {id: this.id, task:inputValue, done:false}
this.todos.push(todo)
localStorage.setItem(this.keyName, JSON.stringify(this.todos));
this.filter = 'all'
},
removeAllItem() {
this.todos = []
localStorage.clear();
this.filter = 'all'
},
filteredTodos() {
return this.todos.filter(todo => {
if (this.filter === 'ongoing') {
return !todo.done;
} else if (this.filter === 'done') {
return todo.done;
} else {
return true;
}
});
},
toggleStatus(todo) {
todo.done = !todo.done
localStorage.setItem(this.keyName, JSON.stringify(this.todos));
},
removeTask(t) {
this.todos = this.todos.filter(todo => todo.id !== t.id)
},
}
};
</script>
ListTodo.vue
<template>
<div>
<p>{{todos.length}} tasks left / {{todos.length}} tasks of all</p>
<ul>
<li v-for="todo in todos" :class="{done:todo.done}" :key="todo.id">
<input type="checkbox" :checked="todo.done" @click="status(todo)">
{{ todo.task }}
<button @click="onRemoveTask(todo)">Remove task</button>
</li>
</ul>
<p v-show="todos.length===0">{{noTask}}</p>
</div>
</template>
<script>
export default {
props: {
todos: {
type: Array,
required: true
},
onRemoveTask: {
type: Function,
required: true
},
onToggleStatus: {
type: Function,
required: true
},
noTask: {
type: String,
required: true
}
},
data() {
return {
id: 1,
done:false,
};
},
methods: {
status(todo) {
this.onToggleStatus(todo)
},
},
};
</script>
Switchers.vue
<template>
<div>
<button :class="{active: filter ==='all'}" @click="set_filter('all')">All</button>
<button :class="{active: filter ==='ongoing'}" @click="set_filter('ongoing')">Ongoing</button>
<button :class="{active: filter ==='done'}" @click="set_filter('done')">Done</button>
<button @click="onRemoveAll">Remove all</button>
</div>
</template>
<script>
export default {
props: {
value: {
type: String,
required: true
},
onRemoveAll: {
type: Function,
required: true
}
},
watch: {
value: {
handler(v) {
if (this.filter !== v)
this.filter = v
},
immediate: true
}
},
data() {
return {
filter:'',
};
},
methods: {
set_filter(f) {
this.filter = f
this.$emit('input', f)
},
},
};
</script>
<style lang="scss" scoped>
.active {background: turquoise;}
</style>
地道的 vuejs 更喜欢响应式属性而不是命令式样式。在这种情况下,我们宁愿保留一份待办事项列表 + 过滤条件(在 App 中),并为下一个 ID、过滤列表和 noTask 消息公开计算属性。
Switchers
是一个纯控制器组件:它没有状态,它的唯一作用是转换用户选择以调用 App 模型。
ListTodo
是一个视图,只负责显示作为道具给出的待办事项列表。它不关心列表是否被过滤。
也可以进行一些小的样式更改,但它们与 vuejs / emit 没有任何关系,所以我没有进行。