《Vue开发实战-从0开始搭建大型Vue项目》是
Ant Design Vue
的作者在极客时间开的一门视频课,笔者记录一下学习笔记,仅供参考。
我们通常把可拆分的html,以及拆分后的逻辑,样式组合在一起称之为组件。
通过一个例子了解一下:一个简单的TodoList项目代码如下:
<div id="app">
<ul>
<li>
<input type="checkbox">
<span>学习 Vue 属性span>
<button>删除button>
li>
<li>
<input type="checkbox">
<span>学习 Vue 事件span>
<button>删除button>
li>
<li>
<input type="checkbox">
<span>学习 Vue 插槽span>
<button>删除button>
li>
ul>
div>
看到上面的代码,我们可以把li标签独立出来。
在Vue中,通过Vue.component定义(注册)一个组件:
1、起名:‘todo-item’
2、template:写上html
Vue.component('todo-item', {
template: `
学习 Vue 插槽
`
})
3、组件使用:
<div id="app">
<ul>
<todo-item>todo-item>
<todo-item>todo-item>
<todo-item>todo-item>
ul>
div>
4、需提供挂载点
// 首先我们new Vue 一个实例,提供一个挂载点
new Vue({
el: '#app'
})
关于缺失的学习 Vue 插槽
,学习 Vue 事件
,就需要用到Vue的属性。
加载组件时,我们同样可以传递不同的参数(属性),组件也可以接受参数(属性)来显示不同的内容。
<div id="app">
<ul>
<todo-item item="学习 Vue 属性">todo-item>
<todo-item item="学习 Vue 事件">todo-item>
<todo-item item="学习 Vue 插槽">todo-item>
ul>
div>
Vue.component('todo-item', {
// 声明能接收的参数(属性)
props: ['item'],
// {{item}} 使用传递过来的 item
template: `
{{item}}
`
})
精简一下代码:
<div id="app">
<ul>
<todo-item
v-for="item in list"
:item="item"
>
todo-item>
ul>
div>
<script>
new Vue({
el: 'app',
data() {
return {
list: [
'学习 Vue 属性',
'学习 Vue 事件',
'学习 Vue 插槽'
]
}
}
})
script>
那么怎么删除?
vue提供了一个简单的方式进行绑定事件
就是使用@xxx就可以进行事件绑定
Vue.component('todo-item', {
props: ['item'],
// 使用@click="xxx"
template: `
{{item}}
`,
methods: {
handleClick() {
// vue提供了一个api,让子组件发射事件给父组件,父组件通过@delete方式来绑定接收delete事件
this.$emit("delete", this.item)
}
}
})
<todo-item
v-for="item in list"
:item="item"
@delete="handleDelete"
>
todo-item>
最后在父组件methods上面定义一个handleDelete方法去改变list数组就可以完成删除操作。
new Vue({
el: 'app',
data() {
return {
list: [
'学习 Vue 属性',
'学习 Vue 事件',
'学习 Vue 插槽'
]
}
},
methods: {
handleDelete(item) {
/**
* findIndex用法
* 1、findIndex() 方法返回传入一个测试条件(函数)符合条件的数组第一个元素位置。
* 2、findIndex() 方法为数组中的每个元素都调用一次函数执行:
* 1)、当数组中的元素在测试条件时返回 true 时, findIndex() 返回符合条件的元素的索引位置,之后的值不会再调用执行函数。
* 2)、如果没有符合条件的元素返回 -1
*
* 注意:
* 1、findIndex() 对于空数组,函数是不会执行的。
* 2、findIndex() 并没有改变数组的原始值。
*/
const index = this.list.findIndex(text=>text === item)
this.list.splice(index, 1)
}
}
})
1、默认插槽:
比如想让todolist中的学习 Vue XXX
前加个图标icon,怎么办?
我们不能通过属性传递这些带有标签的内容,而是通过一种名叫插槽
的东西进行传递。
<todo-item
v-for="item in list"
:item="item"
@delete="handleDelete"
>
<span>我是Iconspan>
todo-item>
同时也不能用{{}}
来解析,我们需要使用
写法来解析:
Vue.component('todo-item', {
props: ['item'],
// 添加 下面这种称之为默认插槽
template: `
{{item}}
`,
methods: {
handleClick() {
this.$emit("delete", this.item)
}
}
})
2、具名插槽:
如果需要加两个图标,一个前,一个后,怎么处理?
这时需要我们添加name,称之为具名插槽。
<todo-item
v-for="item in list"
:item="item"
@delete="handleDelete"
>
<span slot="prefixIcon">我是前缀Iconspan>
<span slot="suffixIcon">我是后缀Iconspan>
todo-item>
同样template需要添加:
Vue.component('todo-item', {
props: ['item'],
template: `
{{item}}
`,
methods: {
handleClick() {
this.$emit("delete", this.item)
}
}
})
3、作用域插槽:
如果我们想通过input checkbox的选中与否来改变图标的颜色,该怎么做?
1、先记录input checkbox的选中状态,我们使用Vue的v-model进行input的双向绑定:
Vue.component('todo-item', {
props: ['item'],
data() {
return {
checked: false // 默认不选中
}
},
template: `
{{item}}
`,
methods: {
handleClick() {
this.$emit("delete", this.item)
}
}
})
2、状态有了,把这个状态传递给上层:
<slot name="prefixIcon" v-bind="{checked}">slot>
3、接收到状态后,控制样式
<span
slot="prefixIcon"
slot-scope="props"
:style="{color: props.checked ? 'red' : 'blue'}"
>
我是前缀Icon
span>
<html>
<head>
<style>
.item {
color: red;
}
style>
head>
<body>
<div id="app">
{{msg}}
<div>
<input type="text" v-model="info">
<button @click="handleClick">添加button>
div>
<ul>
<todo-item v-for="item in list" :item="item">todo-item>
ul>
div>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.js">script>
<script>
Vue.component('todo-item', {
props: ['item'],
template: '{{item}} '
})
new Vue({
el: '#app',
data() {
return {
msg: 'hello vue!',
info: '',
list: [],
}
},
methods: {
handleClick() {
this.list.push(this.info)
this.info = ''
}
}
})
script>
body>
html>