实验目的
(1)掌握组件的创建方法(全局组件、局部组件);
(2)重点学会组件之间的数据传递(prop传值、自定义事件);
(3)学会动态组件的创建。
相关知识点
组件是 Vue.js 提供的最强大的功能之一。通过开发组件可以封装可复用的代码,并注册为标签,从而实现扩展 HTML 元素的功能。
(1)注册组件:有全局注册和局部注册两种方式。
全局组件(全局注册的组件)可以在所有实例中使用。注册全局组件的语法格式如下:
Vue.component(tagName, options)
其中,tagName表示组件名称,建议遵循 W3C 规范中组件命名方式,即字母全部小写并包含一个连字符“-”;option可以是应用 Vue.extend()方法创建的一个组件构造器,也可以是组件的选项对象。
在组件注册之后,就可以在 Vue 根实例中以自定义元素形式来使用该组件了。使用组件的语法格式如下:
其中,tagName:表示组件名称。
通过使用 Vue 实例或父组件中的 components 选项,可以注册一个局部组件(只能在当前实例或父组件中使用)。其中,属性名表示所定义组件的名称,属性值表示该组件的选项对象。
(2)数据传递
因为组件实例的作用域是相互独立的,所以子组件的模板无法直接引用父组件中的数据,反之亦然。为了实现组件之间的数据传递,Vue.js提供了相应的数据传递机制。
父组件通过使用自定义属性 Prop 给子组件传递数据。在组件选项对象的props选项中定义 Prop 属性。除了可以传递静态数据外,可以通过使用v-bind 指令绑定属性的方式将父组件中的data数据传递给子组件。每当父组件的数据发生变化时,子组件也会随之变化。由于HTML中的属性名是不区分大小写的,所以当 props 中的命名采用“小驼峰”方式,需要在调用组件的标签中使用其等价的短横线分割的命名方式来命名属性。
子组件使用自定义事件来向父组件传递数据。子组件可以通过调用内建的
e
m
i
t
(
)
方法并传入自定义事件名称来触发自定义事件。格式如下:
v
m
.
emit()方法并传入自定义事件名称来触发自定义事件。格式如下: vm.
emit()方法并传入自定义事件名称来触发自定义事件。格式如下:vm.emit(eventName, […args])
其中,eventName: 传入的事件名称;[…args]: 可选,触发事件传递的参数。
父组件则可以像处理原生DOM事件一样通过v-on指令监听子组件实例的自定义事件。
如果想要在某个组件的根元素上监听一个原生事件,可以使用 v-on 指令的 native 修饰符。
(3)动态组件
Vue.js允许使用动态组件,让多个组件使用同一个挂载点,根据条件在不同组件之间动态切换。动态组件通常应用在路由控制或选项卡切换中。
通过使用元素,动态绑定它的 is 属性,根据 is 属性的值来判断使用哪个组件。有时需要保持某些组件的状态,以避免重复渲染,可以使用一个元素将动态组件包裹起来。
实验内容及要求
运用组件的相关知识实现选项卡的切换,点击删除,删除相应电影,效果如图1~3所示。
图1
图2
图3
参考基础代码如下:
请在此基础上,利用Vue组件相关知识完成代码的编写和调试。
代码实现
<!DOCTYPE html>
<html>
<head>
<title>Vue 电影票房排序示例</title>
<meta charset="UTF-8">
<style>
body {
font-family: Arial, sans-serif;
background-color: #f7f7f7;
margin: 0;
padding: 0;
}
#app {
max-width: 400px;
margin: 0 auto;
padding: 20px;
background-color: #fff;
border-radius: 5px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
}
h1 {
font-size: 24px;
margin-bottom: 20px;
}
button {
background-color: #007bff;
color: #fff;
border: none;
border-radius: 3px;
padding: 5px 10px;
cursor: pointer;
margin-right: 10px;
}
ul {
list-style: none;
padding: 0;
}
li {
margin-bottom: 10px;
}
</style>
</head>
<body>
<div id="app">
<!-- 排序按钮 -->
<button @click="sortByBoxOffice">热播</button>
<button @click="reverseOrder">经典</button>
<!-- 电影列表 -->
<ul>
<li v-for="movie in movies" :key="movie.id">
{{ movie.name }} - 票房: {{ movie.boxOffice }}
<!-- 删除按钮 -->
<button @click="deleteMovie(movie.id)">删除</button>
</li>
</ul>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
<script>
new Vue({
el: '#app',
data: {
movies: [
{ id: 1, name: '原神,启动!', boxOffice: 900 },
{ id: 2, name: '我要玩王者荣耀', boxOffice: 1200 },
{ id: 3, name: '三国杀司马游戏', boxOffice: 500 },
{id:4,name:'一就是一而就是二',boxOffice:1000}
// 更多电影...
],
originalOrder: []
},
created() {
// 在组件创建时保存原始顺序
this.originalOrder = [...this.movies];
},
methods: {
sortByBoxOffice() {
// 按票房排序当前电影列表
this.movies.sort((a, b) => b.boxOffice - a.boxOffice);
},
reverseOrder() {
// 恢复到删除操作之前的顺序
this.movies = [...this.originalOrder];
},
deleteMovie(id) {
// 删除指定 ID 的电影并更新原始顺序
this.movies = this.movies.filter(movie => movie.id !== id);
this.originalOrder = this.originalOrder.filter(movie => movie.id !== id);
}
}
});
</script>
</body>
</html>
效果
点击经典
点击热播
点击删除
删除后仍然可以排序