Vue.js 理论基础 | 写给 Vue 初学者的理论实操教程,(我的风格)通俗易懂,跟完就可独立上手!
本文版权归 “公众号 | 前端一万小时” 所有,欢迎转载!
转载请注明出处,未经同意,不可修改文章内容。
🔥🔥🔥“前端一万小时”两大明星专栏已于本月大改版,合二为一,欢迎点击公众号菜单栏各模块了解。
❗️❗️❗️由于篇幅原因,本文只能详细列示整个系列的前 5 篇文章,整个系列文章请点击公众号免费查看。
目录:
Vue 初识——① Hello World
Vue 初识——② 简易 TodoList
Vue 初识——③ MVVM 模式
Vue 初识——④ 使用组件改造 TodoList
Vue 初识——⑤ 简单的组件间传值
Vue 入门——① Vue 实例
Vue 入门——② Vue 实例的生命周期函数
Vue 入门——③ 模板语法
Vue 入门——④ 计算属性、方法与侦听器
Vue 入门——⑤ 计算属性的 getter 和 setter
Vue 入门——⑥ Class 与 Style 绑定
Vue 入门——⑦ 条件渲染
Vue 入门——⑧ 列表渲染
深入理解 Vue 组件——① 使用组件的细节点
深入理解 Vue 组件——② 父子组件间的数据传递
深入理解 Vue 组件——③ 组件参数校验与非 props 特性
深入理解 Vue 组件——④ 给组件绑定原生事件
深入理解 Vue 组件——⑤ 非父子组件间的传值
深入理解 Vue 组件——⑥ 在 Vue 中使用插槽
深入理解 Vue 组件——⑦ 作用域插槽
深入理解 Vue 组件——⑧ 动态组件与 v-once 指令
Vue 中的动画特效——① Vue 中的 CSS 动画原理
Vue 中的动画特效——② 在 Vue 中使用 Animate.css 库
Vue 中的动画特效——③ 在 Vue 中同时使用过渡和动画
Vue 中的动画特效——④ Vue 中的 JS 动画与 Velocity.js 的结合
Vue 中的动画特效——⑤ Vue 中多个元素或组件的过渡
Vue 中的动画特效——⑥ Vue 中的列表过渡
Vue 中的动画特效——⑦ Vue 中的动画封装
一、《Vue 介绍——① Hello World》
涉及面试题:
1. Vue.js 是什么?
2. Vue.js 的主要功能是什么?
[编号:vue_01]
❗❗️❗️️P.s. 公众号对话框回复 vue_01、vue_02、web_01、html_01 或 css_01 查看参考答案样本~
1 如何在 div 里显示一个 Hello World
字符串
1.1 用原生 JS 实现
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>前端一万小时-Hello World</title>
</head>
<body>
<div id="app"></div>
<script>
var dom = document.getElementById("app");
dom.innerHTML = "Hello World"
</script>
</body>
</html>
1.2 用 Vue.js 实现
1️⃣打开 Vue.js 官网,点击右上角“学习-教程”,完成 Vue.js 开发版本的安装(我们这里是把源代码下载到本地,然后进行引入)。
项目目录结构:
2️⃣将现有的 index.html
中的原生 JS 代码删除,编写 Vue 的代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>前端一万小时-Hello World</title>
<script src="./vue.js"></script> <!-- 2️⃣-①:从当前目录下引入 vue.js; -->
</head>
<body>
<div id="app">
{{content}} <!-- 2️⃣-⑥:用 {{}} 包裹 content,写在 #app 这个 div 里。 -->
</div>
<script>
var app = new Vue({ // 2️⃣-②:创建一个 Vue 实例;
el: '#app', // 2️⃣-③:这个实例接收的第一个参数 el,稍后会详细讲解它,暂时不管;
data: { // 2️⃣-④:接收的第二个参数 data,它指的是数据;
content: 'hello world' /*
2️⃣-⑤:定义一个叫 content 的数据,内容是“hello world”,
与原生的作区分。
*/
}
})
</script>
</body>
</html>
写完后保存,刷新网页可以看到我们使用 Vue.js 也展示出了“hello world”。
现在来详细了解一下刚才写的这段 Vue 的代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>前端一万小时-Hello World</title>
<script src="./vue.js"></script>
</head>
<body>
<div id="app">{{content}}</div> <!-- 3️⃣content 数据中的内容在 DOM 元素中用
插值表达式 “{{}}”来调用。 -->
<script>
var app = new Vue({ // ❗️创建一个名为 app 的实例,实例接收一些配置项:
el: '#app', /*
1️⃣el 配置项限制了一个 Vue 实例负责管理的区域,
这里即让“app 实例”去接管 id 为 app 的 DOM 元素标签里的所有内容;
*/
data: { /*
2️⃣data 配置项定义了一些数据,
这里即定义了内容为 "hello world" 的数据 content;
*/
content: 'hello world'
}
})
</script>
</body>
</html>
❗️题外话
假如:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>前端一万小时-Hello World</title>
<script src="./vue.js"></script>
</head>
<body>
<div id="app">{{content}}</div>
<div>{{content}}</div> <!-- ❗️再增加一个 div。
❗️使用了 {{}} 调用 content 中的内容,但无 id! -->
<script>
var app = new Vue({
el: '#app',
data: {
content: 'hello world'
}
})
</script>
</body>
</html>
保存后,刷新页面查看,发现页面上只显示了一个“hello world”和这个新 div 中的原内容“{{content}}”:
❓为什么没有显示两个“hello world”?
答:因为 Vue 实例只接管了 el
所对应的 DOM 元素标签下的所有内容,而没有接管其他部分的内容,所以它只会替换 #app
所在 DOM 标签下的 {{content}}
内容。
2 如何在几秒后,更改 data
中数据的内容
2.1 用原生 JS
var dom = document.getElementById("app");
dom.innerHTML = "hello world"
setTimeout(function() {
dom.innerHTML = "bye world"
}, 2000)
原生 JS 将“变动的数据”集中在对 DOM 的操作上。
2.2 用 Vue.js
var app = new Vue({
el: "#app",
data: { // 2️⃣-②:$data 可以理解为 data 后面的对象。
content: "hello world"
}
})
setTimeout(function() {
app.$data.content = "bye world" // ❗️Vue 关注点在数据!
// 1️⃣app 指的是这个 Vue 实例;
// 2️⃣-①:$data 是 data 的别名;
}, 2000)
Vue.js 将“变动的数据”集中在对其的管理上:数据的内容是什么,那么页面展示的就是什么。数据改变了,页面就会跟着变!
祝好,qdywxs ♥ you!
二、 Vue 介绍——② 开发 TodoList(v-model、v-for、v-on)》
涉及面试题:
1. v-model 的使用?
2. v-on 可以监听多个方法吗?
3. 如何使用事件处理程序?
4. 如何实现双向绑定?
5. v-model 支持什么修饰符?
[编号:vue_02]
1 要实现的效果
我们要使用 Vue 实现一个简易的 TodoList:输入内容点击“添加”后,可以新增内容至列表中,同时清空输入框。
2 Vue 中的循环
通过效果展示,我们知道其实要实现的内容不多,结构非常简单,只有一个 input 框、一个“添加”按钮和一个列表项。
打开编辑器,跟着我一步步来熟悉 Vue 的代码编写。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>前端一万小时-开发 TodoList</title>
<script src="./vue.js"></script> <!-- 2️⃣引入 Vue.js 库; -->
</head>
<body>
<!-- 1️⃣写出页面的结构; -->
<div id="app">
<input type="text">
<button>添加</button>
<ul> <!-- ❗️ul 中 li 标签的内容,实际应是根据数据循环显示出来的内容。 -->
<li>Oli</li>
<li>qdywxs</li>
</ul>
</div>
<script>
var app = new Vue({ // 3️⃣创建一个 Vue 的实例;
el: '#app' // 4️⃣指定使用 Vue 接管 #app 的 DOM 区域;
})
</script>
</body>
</html>
❓Vue 中如何对列表进行循环?
答:Vue 中使用 v-for
指令将数组渲染成列表。
所以既然 li 标签的内容是数据,我们就将其定义在实例的 data 内:
<div id="app">
<input type="text">
<button>添加</button>
<ul> <!-- ❗️当我们定义了 list 数据后,借助 v-for 指令把数据内容渲染在页面上! -->
<li v-for="item in list">{{item}}</li> <!-- 3️⃣保留一个 li 标签,写上 v-for 指令;
3️⃣-①:item in list 指的是循环 data 里的
list 数据,循环的每一项放入 item;
3️⃣-②:li 标签内用 {{}} 调用 item,
即渲染 list 中的每一项内容。 -->
</ul>
</div>
<script>
var app = new Vue({
el: '#app',
data: { // 1️⃣data 是固定的写法,指的是这个 Vue 实例里具体的数据;
list: ['Oli', 'qdywxs', '666'] // 2️⃣data 中定义 list 的数据,其中有三组内容;
}
})
</script>
保存后,刷新页面查看效果,三组内容都显示在了页面上:
3 Vue 中绑定事件
接下来我们给 button 绑定事件。
❓Vue 中如何绑定事件?
答:Vue 中使用 v-on
指令绑定事件。
<div id="app">
<input type="text">
<button v-on:click="handleBtnClick">添加</button> <!-- 1️⃣:在 button 标签写上 v-on 指令;
1️⃣-①:v-on 后面以冒号分隔监听的
DOM 事件 click;
1️⃣-②:当点击“添加”按钮,即 click 事
件触发后执行 handleBtnClick 方法; -->
<ul>
<li v-for="item in list">{{item}}</li>
</ul>
</div>
<script>
var app = new Vue({
el: '#app',
data: {
list: ['Oli', 'qdywxs', '666']
},
methods: { // ❗️Vue 中的方法都定义在实例的 methods 内,methods 中文即译为“方法”!
handleBtnClick() { // 2️⃣我们在 handleBtnClick 方法中让它 alert 出“click”。
alert('click')
}
}
})
</script>
我们再梳理一次 v-on
绑定事件的整个流程:因为我们在这个名为 app 的 Vue 实例中传入的 DOM 元素是 #app
这个 div,所以当点击它里面的“添加”按钮要执行 handleBtnClick
方法时,Vue 会自动到实例的 methods
中找到 handleBtnClick
这个方法并执行,最终页面弹出“click”。
4 Vue 中的双向绑定数据
搞定了事件绑定,我们就可以让 input 框里输入的内容在点击按钮后,显示在列表里了。
❓在点击按钮后,如何拿到 input 框里输入的内容?
答:使用 Vue 中的指令 v-model
实现双向数据绑定(即当 input 框里的内容发生变化时,Vue 实例中 data 的 inputValue
就会发生变化,反之亦然)。
<div id="app">
<input type="text" v-model="inputValue"> <!-- 1️⃣在 input 上写 v-model 指令,
它等于 inputValue 这个数据; -->
<button v-on:click="handleBtnClick">添加</button>
<ul>
<li v-for="item in list">{{item}}</li>
</ul>
</div>
<script>
var app = new Vue({
el: '#app',
data: {
list: [], // ❗️将 list 里的内容清除,默认为空数组!
inputValue: '' // 2️⃣把数据 inputValue 写入 data 内,默认为空字符串;
},
methods: {
handleBtnClick() {
// 3️⃣通过 push 把 input 框里的内容放入 list 中;
this.list.push(this.inputValue)
// 4️⃣当输入内容放入 list 后,让 inputValue 为空,清空输入框里的内容。
this.inputValue = ''
}
}
})
</script>
v-model
负责监听用户的输入事件以更新数据 inputValue
。当数据更新后,通过 this.inputValue
获取输入的内容放入 list 中。与此同时让 inputValue
变为空字符串,以清空输入框。
祝好,qdywxs ♥ you!
三、《Vue 介绍——③ MVVM 模式》
涉及面试题:
1. 什么是 MVVM?比之 MVC 有什么区别?
2. Vue 的优点?
3. 渐进式框架的理解?
4. 三大框架的对比?
[编号:vue_03]
MVVM 设计模式
Vue 是 MVVM 模式的框架。
当我们使用 MVVM 这种模式的框架进行编码的时候,我们不需要关注 VM 这一层到底是怎么实现的,它是 Vue 内置的。我们只需要关注“ M 层”和“ V 层”。 对 MVVM 这种模式进行编码的时候,编码的重点在于“视图层”和“模型层”。
- View:视图层,负责显示数据。 会监听数据、事件的触发(主要是 Vue 的指令)。
<div id="app">
<input type="text" v-model="inputValue">
<button v-on:click="handleBtnClick">添加</button>
<ul>
<li v-for="item in list">{{item}}</li>
</ul>
</div>
- Model:数据层,负责存储数据。 在 Vue 中,我们主要在写数据。
💡 【重点关注这一层】——面向数据开发。
<script>
var app = new Vue({
el: '#app',
data: {
list: [],
inputValue: ''
},
methods: {
handleBtnClick() {
this.list.push(this.inputValue) // 1️⃣实现了当点击时,把获取到的输入内容这个数据放入列表中;
this.inputValue = '' // 2️⃣通过改变 inputValue 数据,实现了清空输入框的功能。
}
}
})
</script>
- ViewModel: 这是 Vue 自带的一层,不需要我们编写。它将 View 层和 Model 层连接起来,当视图层变化时,数据层也跟着变化,反之亦然。这其中 ViewModel 带动其视图和数据的变化。
🏆总结:
- Vue (即 ViewModel 层)会监听到你数据变了,它会帮你去改变视图层;
- Vue 也会监听到视图层有一些事件触发,然后帮助你通过 VM 这一层去调用你写的一些逻辑代码,通过这些代码,你又改变了 M 层的“数据”。当“数据”发生变化的时候,VM 层又会自动地把“数据”的变化映射到“视图层”上面来。
🏆这样的话有一个好处: 当我们使用 Vue 这种 MVVM 框架进行开发的时候,我们只需要去关注“ M 层”的开发就可以了!我们把“数据”做一个修改,页面会自动地跟着变。同时,页面上的变化,Vue 实例也能感知到,可以方便地帮我们去操作数据。
祝好,qdywxs ♥ you!
四、《Vue 介绍——④ 使用组件改造 TodoList》
涉及面试题:
1. 引进组件的步骤?
2. 组件是什么并给个例子?
3. 组件中的全局注册是什么?
4. 为什么你需要局部注册?
5. 局部注册和全局注册在模块系统中有什么区别?
[编号:vue_04]
1 前端组件化
组件,是页面的一个部分。也就是可以把一个页面,由原来一个整体,切分成一个一个的部分,每个部分都可称之为组件。
比如上图中,一号轮播可以是组件,二号分类区域可以是组件,三号榜单可以是组件,甚至四号城市切换区域也可以是个小组件。
合理地拆分组件,可以将一个大型的项目像拼积木一样拼接起来。一个大型项目,业务逻辑可能非常复杂,但当被拆分成一个个组件时,每个组件都会变得精小,这些小的组件维护起来也会相对更容易。
真实的项目中,使用组件化进行大型项目的开发,会使得代码在后续的维护性上得到极大的提高。每一个组件其实就是页面上的一个区域。
前面,我们实现了一个简易的 TodoList:输入内容,可以将内容添加至列表内。这里的每个列表项其实也是页面的一个部分,所以我们可以把这个列表项拆分为一个组件。
2 全局组件实现“列表”组件化
🚀需求:将 TodoList 中的列表封装成一个组件。
<div id="app">
<input type="text" v-model="inputValue">
<button v-on:click="handleBtnClick">添加</button>
<ul>
<li v-for="item in list">{{item}}</li> <!-- ❗️之前的列表项是通过循环 li 标签来显示的! -->
</ul>
</div>
❓Vue 中如何把 li 标签的内容整体变为组件?
答:可以使用 Vue 中的 Vue.component
方法创建全局组件。
<div id="app">
<input type="text" v-model="inputValue">
<button v-on:click="handleBtnClick">添加</button>
<ul>
<todo-item v-for="item in list"></todo-item> <!--4️⃣在页面上使用组件替代原有的 li 标签;
4️⃣-①:组件名全小写,第二个单词前用 - 隔开;
4️⃣-②:v-for 循环添加在组件标签上,
即每次添加都让它向列表内增加一项内容。
-->
</ul>
</div>
<script>
// 1️⃣在 script 标签中注册全局组件;
Vue.component('TodoItem', { /*
2️⃣Vue.component 方法的第一个参数为组件名“TodoItem”,
组件名一般首字母大写;
*/
template: '<li>hello qdywxs</li>' /*
3️⃣第二个为组件的 template 模板项,
这里添加一个 li 标签,内容暂时为“hello qdywxs”;
*/
})
var app = new Vue({
el: '#app',
data: {
list: [],
inputValue: ''
},
methods: {
handleBtnClick() {
this.list.push(this.inputValue)
this.inputValue = ''
}
}
})
</script>
❗️注意:注册全局组件时,我们组件名定义为 TodoItem
,使用组件时可以当成小写 todo-item
。第二个词的大写字母换为小写时,前面需加上 -
。
保存,刷新页面查看效果,这里发现一个问题:当输入内容点击“添加”后,列表出现了,但是内容却都是我们写在模板中的内容 hello qdywxs
。
❓组件中如何让输入的内容显示在列表里?
答:如果想让子组件显示输入的内容,则需要把内容传递给子组件。
<div id="app">
<input type="text" v-model="inputValue">
<button v-on:click="handleBtnClick">添加</button>
<ul>
<!-- 1️⃣在组件上使用 v-bind 指令绑定 content;
❗️这里整个意思是:在循环 list 数组时,每一项值赋值给 item,然后再把 item 的内容通过 v-bind
指令绑定给属性 content,传给 todo-item 这个子组件; -->
<todo-item v-bind:content="item" v-for="item in list"></todo-item>
</ul>
</div>
<script>
Vue.component('TodoItem', {
props: ['content'], // 2️⃣子组件内通过 props 来接收父组件的内容,即接收 content;
template: '<li>{{content}}</li>' /*
3️⃣在 template 的 li 标签内使用插值表达式
显示 content 内容。
*/
})
var app = new Vue({
el: '#app',
data: {
list: [],
inputValue: ''
},
methods: {
handleBtnClick() {
this.list.push(this.inputValue)
this.inputValue = ''
}
}
})
</script>
再次查看效果,没有问题了:
这样就完成了“列表”组件化,我们再来梳理一遍逻辑:
- 定义了一个全局组件“TodoItem”,可以直接在模板里使用它(
todo-item
); - 通过循环 list 来决定输出多少个
todo-item
组件; - 同时,父组件把每一项内容 item 通过 v-bind 指令借助
content
变量传给todo-item
子组件; - 在
todo-item
子组件中,若要使用父组件传递的数据content
,则一定要在props
属性里进行接收; - 接收后,
template
的模板里用{{}}
包裹content
; - 最终页面上渲染出内容。
3 局部组件实现“列表”组件化
在 Vue 中,除了全局组件的方式来实现列表组件化,还可以使用“局部组件”来实现。
<script>
var TodoItem = { // 1️⃣定义 TodoItem 组件,props 接收 content 并将其写入模板;
props: ['content'],
template: '<li>{{content}}</li>'
}
var app = new Vue({
el: '#app',
components: { // ❗️把局部组件注册到根实例里的 components,通常用“对象 {}”来注册!
TodoItem: TodoItem /*
2️⃣注册 TodoItem 组件到 Vue 实例里,并且在这个实例内,
它还是名为 TodoItem。
*/
},
data: {
list: [],
inputValue: ''
},
methods: {
handleBtnClick() {
this.list.push(this.inputValue)
this.inputValue = ''
}
}
})
</script>
4 总结
这一篇我们初步认识了组件,包括 Vue 中“局部组件”和“全局组件”的使用。
组件就是把页面上的一些内容进行封装。 比如关于 li 标签里的所有逻辑,都封装在了 TodoItem 这个小的组件中。小组件有自己的 props
和 template
。
props
:若要接收外部传递过来的数据,需定义在这里;template
:指子组件的模板。页面内的组件标签会被子组件里的模板替换。
祝好,qdywxs ♥ you!
五、《Vue 介绍——⑤ 简单的组件间传值》
涉及面试题:
props 是什么?
[编号:vue_05]
1 父组件向子组件传值
上一篇我们封装列表组件时,让 input 框的输入内容显示在列表组件上就已经用到了“父组件向子组件传值”。
<div id="app">
<input type="text" v-model="inputValue">
<button v-on:click="handleBtnClick">添加</button>
<ul>
<todo-item v-bind:content="item"
v-for="item in list"> <!-- 2️⃣-①:使用子组件;
2️⃣-②:父组件通过 v-bind 动态绑定
content 的形式传递内容给子组件; -->
</todo-item>
</ul>
</div>
<script>
var TodoItem = {
props: ['content'], // 3️⃣子组件中以 props 接收 content;
template: '<li>{{content}}</li>' // 4️⃣在模板中使用接收到的数据。
}
var app = new Vue({ // 1️⃣父组件是 app 实例这个根组件,即整个 #app 这个 div 的内容;
el: '#app',
components: { // 2️⃣子组件是注册在根组件的 TodoItem,它在根组件里的名字也叫 TodoItem;
TodoItem: TodoItem
},
data: {
list: [],
inputValue: ''
},
methods: {
handleBtnClick() {
this.list.push(this.inputValue)
this.inputValue = ''
}
}
})
</script>
简而言之:父组件通过“属性”向子组件传值,子组件通过 props
接收属性来调用其内容。
2 子组件向父组件传值
🚀需求:当点击列表项时,删除所点击的对应内容。
也就是说,当点击子组件中的某个列表项时,父组件收到对应信息来删除对应列表项。那么完成这个需求,就涉及到“子组件向父组件传值”。
❗️注意:为了代码简洁,接下来大家已经比较熟悉的 v-bind 和 v-on 指令都将用简写!
v-on 简写为 @
,用来绑定事件监听器;v-bind 简写为 :
,用来动态绑定属性。
<div id="app">
<input type="text" v-model="inputValue">
<button @click="handleBtnClick">添加</button>
<ul>
<todo-item :content="item"
v-for="item in list"
@delete="handleItemDelete"
> <!-- 3️⃣-①:父组件在创建子组件时,通过 v-on 指令监听 delete 事件;
3️⃣-②:一旦 delete 事件被触发,父组件就执行 handleItemDelete 方法; -->
</todo-item>
</ul>
</div>
<script>
var TodoItem = {
props: ['content'],
// 1️⃣子组件的 li 标签监听 click 事件,当触发时执行 handleItemClick 方法;
template: '<li @click="handleItemClick">{{content}}</li>',
methods: { // 2️⃣-①:子组件的方法定义在子组件的 methods 中;
handleItemClick() {
this.$emit('delete') // 2️⃣-②:子组件中,通过 $emit 向外触发 delete 事件;
}
}
}
var app = new Vue({
el: '#app',
components: {
TodoItem: TodoItem
},
data: {
list: [],
inputValue: ''
},
methods: {
handleBtnClick() {
this.list.push(this.inputValue)
this.inputValue = ''
},
handleItemDelete() { // 4️⃣-①:在父组件的 methods 中定义 handleItemDelete 方法;
this.list = [] // 4️⃣-②:让 list 为空数组 []。
}
}
})
</script>
保存返回页面,刷新查看效果:我们完成了子组件向父组件传值,成功删除了列表项。但,当点击列表项时,清空了“整个”列表!
这是因为当 delete 事件触发后,父组件执行的 handleItemDelete
方法中我们让 list 为空数组。
handleItemDelete() { // 4️⃣-①:在父组件的 methods 中定义 handleItemDelete 方法;
this.list = [] // 4️⃣-②:让 list 为空数组 []。
}
而当 list 为空数组,即改变了 list 的数据,让它已有的列表项被全部清空。所以当点击某一个列表项时,我们就看到整个列表被清空。
❓如何正确删除所点击的某一项列表?
答:可以通过获取列表项的下标来完成此功能。
<div id="app">
<input type="text" v-model="inputValue">
<button @click="handleBtnClick">添加</button>
<ul>
<todo-item :content="item"
:index="index"
v-for="(item, index) in list"
@delete="handleItemDelete"
> <!-- 1️⃣当循环 list 数组时,第一项获取内容 item,
第二项获取数组的下标 index;
2️⃣动态绑定一个名为 index 的属性,当父组件向子组件传值时,
除了 content 对应的内容 item,同时再传入 index 对应的列表项下标; -->
</todo-item>
</ul>
</div>
<script>
var TodoItem = {
props: ['content', 'index'], // 3️⃣子组件要使用列表项下标,必须在 props 中接收 index 属性;
template: '<li @click="handleItemClick">{{content}}</li>',
methods: {
handleItemClick() {
this.$emit('delete', this.index) /*
4️⃣当子组件被点击时,不但触发 delete 事件,
同时把被点击列表项的下标作为参数传给父组件;
*/
}
}
}
var app = new Vue({
el: '#app',
components: {
TodoItem: TodoItem
},
data: {
list: [],
inputValue: ''
},
methods: {
handleBtnClick() {
this.list.push(this.inputValue)
this.inputValue = ''
},
handleItemDelete(index) { /*
5️⃣-①:父组件接收子组件传来的下标,
当监听到 delete 事件被触发时执行 handleItemDelete 方法;
*/
this.list.splice(index, 1) // 5️⃣-②:从传来的下标开始,删除一项。
}
}
})
</script>
现在我们完成了“当点击列表项时,删除所点击的对应内容”的需求,同时还学到了子组件向父组件传值的方式。
再简述一次此实现流程:
- 父组件通过 v-bind 指令传递下标 index 值;
- 父组件传递的值,子组件一定要在自己的
props
接收; - 子组件通过
$emit
触发delete
事件,同时传递被点击列表项的下标; - 父组件通过 v-on 监听
delete
事件,获取到子组件传递的下标并执行handleItemDelete
方法; - 最终实现当点击某项列表时,删除此项。
祝好,qdywxs ♥ you!
🔥🔥🔥篇幅原因,后续文章详情请在「公众号 | 前端一万小时」内查看。
六、《Vue 基础精讲——① Vue 实例》
涉及面试题:
1. Vue 实例是什么?
2. 如何访问根实例?
3. 如何访问父实例?
[编号:vue_06]
七、《Vue 基础精讲——② Vue 实例生命周期》
涉及面试题:
1. Vue 生命周期的作用是什么?
2. 什么是 Vue 生命周期?
3. 第一次页面加载会触发哪几个钩子?
4. 简述每个周期具体适合哪些场景?
5. created 和 mounted 的区别?
6. Vue 获取数据在哪个周期函数?
7. $nextTick 的使用?
[编号:vue_07]
八、《Vue 基础精讲——③ Vue 的模板语法》
九、《Vue 基础精讲——④ 计算属性、方法与侦听器》
涉及面试题:
computed 计算属性的用法?与 watch、methods 的区别?分别简述 computed 和 watch 的使用场景?
[编号:vue_09]
十、《Vue 基础精讲——⑤ 计算属性的 getter 和 setter》
涉及面试题:
Vue.set 视图更新?
[编号:vue_10]
十一、《Vue 基础精讲——⑥ Vue 中的样式绑定》
涉及面试题:
如何让 CSS 只在当前组件中起作用?
[编号:vue_11]
十二、《Vue 基础精讲——⑦ Vue 中的条件渲染》
涉及面试题:
1. v-show 和 v-if 指令的共同点和不同点?
2. v-if 和 v-for 的优先级?
3. 条件指令是什么?
[编号:vue_12]
十三、《Vue 基础精讲——⑧ Vue 中的列表渲染》
涉及面试题:
1. 说出几种 Vue 当中的指令和它的用法?
2. 为什么使用 key?
3. 列举常用的指令?
4. v-for 指令的目的是什么?
5. 如何复用有 key 属性的元素?
6. 为什么不能在同一个元素上同时使用 v-if 和 v-for 指令?
7. 为什么使用 for 指令时需要 key 属性?
8. 如何在一个范围内使用 v-for 指令?
9. 如何在模板上使用 v-for 指令?
10. 什么是数组检测突变的方法?
11. 什么是数组检测非突变方法?
12. 检测数组变化有什么注意事项?
13. 检测对象变化有什么注意事项?
[编号:vue_13]
十四、《深入理解 Vue 组件——① 使用组件的细节点》
涉及面试题:
1. Vue 组件中 data 为什么必须是一个函数?
2. Vue 的两个核心点?
3. 如何获取 DOM?
[编号:vue_14]
十五、《深入理解 Vue 组件——② 父子组件间的数据传递》
涉及面试题:
1. Vue 父组件向子组件传递数据?
2. 子组件像父组件传递事件?
3. 跨组件双向数据绑定?
4. 什么是可接受的 prop 类型?
5. props 后面的数据流是什么?
6. 什么是非 prop 属性?
7. props 有哪些可用的验证?
[编号:vue_15]
十六、《深入理解 Vue 组件——③ 组件参数校验与非 props 特性》
十七、《深入理解 Vue 组件——④ 给组件绑定原生事件》
十八、《深入理解 Vue 组件——⑤ 非父子组件间的传值》
涉及面试题:
组件间的通信?
[编号:vue_18]
十九、《深入理解 Vue 组件——⑥ 在 Vue 中使用插槽》
涉及面试题:
什么是 slot?
[编号:vue_19]
二十、《深入理解 Vue 组件——⑦ 作用域插槽》
廿一、《深入理解 Vue 组件——⑧ 动态组件与 v-once 指令》
涉及面试题:
什么是动态组件?
[编号:vue_21]
廿二、《Vue 中的动画特效——① Vue 中的 CSS 动画原理》
廿三、《Vue 中的动画特效——② 在 Vue 中使用 Animate.css 库》
廿四、《Vue 中的动画特效——③ 在 Vue 中同时使用过渡和动画》
廿五、《Vue 中的动画特效——④ Vue 中的 JS 动画与 Velocity.js 的结合》
涉及面试题:
提供 transitions 有什么可能的方式?
[编号:vue_25]
廿六、《Vue 中的动画特效——⑤ Vue 中多个元素或组件的过渡》
廿七、《Vue 中的动画特效——⑥ Vue 中的列表过渡》
廿八、《Vue 中的动画特效——⑦ Vue 中的动画封装》
转载自:https://juejin.cn/post/7211336358987841573