十、组件
10.1 组件介绍及示例
组件,就是讲通用的 HTML 模块进行封装 —— 可复用的 Vue 实例
通常一个应用会以一棵嵌套的组件树的形式来组织:
10.1.1 组件注册
将通用的 HTML 模块封装注册到 vue 中
自定义组件 my-components.js:
Vue.component('header-button', { template: `<div style="width: 100%; height: 80px; background: salmon"> <table width="100%"> <tr> <td width="200" align="right" valign="middle"> <img src="img/1.jpg" height="80" /> </td> <td> <label style="color: deepskyblue; font-size: 32px; font-family: 'Adobe 楷体 Std R'; margin-left: 30px"> 登录 </label> </td> </tr> </table> </div>` });
10.1.2 组件引用
- 定义组件需要依赖 vue.js,在引用自定义组件 js 文件要先引用 vue.js
- 组件的引用必须在 vue 实例 el 指定的容器中 ,即要在Vue实例范围内
10.2 组件注册
10.2.1 自定义组件的结构
Vue.component()
注册组件data
定义组件的模板渲染的数据
template
组件的 HTML 模块(HTML 标签 CSS 样式)methods
定义组件中的标签事件中绑定的 JS 函数
my-components.js:
Vue.component('header-button', { data: function () { // 组件中 data 是通过函数返回的对象 return { name: "貂蝉" }; }, template: `<div style="width: 100%; height: 80px; background: salmon"> <table width="100%"> <tr> <td width="200" align="right" valign="middle"> <img src="img/1.jpg" height="80" /> </td> <td> <label style="color: deepskyblue; font-size: 32px; font-family: 'Adobe 楷体 Std R'; margin-left: 30px"> 登录人: {{name}} </label> </td> <td> <button @click="test">组件按钮</button> </td> </tr> </table> </div>`, methods: { test: function () { alert("组件中 header-button 定义的函数事件") } } });
10.2.2 组件的封装
- 将模板中的 css 样式提取出来,单独封装到 css 文件存储在 css 目录
- 将模板中的图片存储在 img 目录
- 将定义组件的 js 文件和 vue 文件存放到 js 目录
Vue 组件封装的结构
注:在编码过程中学到,Vue 中同一个 DOM 元素绑定多个点击事件:可以使用逗号分隔。
10.2.3 组件的复用
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <link rel="stylesheet" href="css/my-components.css" /> <script src="https://cdn.staticfile.org/jquery/1.10.2/jquery.min.js"></script> <!-- 最新版本的 Bootstrap 核心 CSS 文件 --> <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css" integrity="sha384-HSMxcRTRxnN+Bdg0JdbxYKrThecOKuH5zCYotlSAcp1+c8xmyTe9GYg1l9a69psu" crossorigin="anonymous"> <!-- 最新的 Bootstrap 核心 JavaScript 文件 --> <script src="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/js/bootstrap.min.js" integrity="sha384-aJ21OjlMXNL5UyIl/XNwTMqvzeRMZH2w8c5cRVpzpU8Y5bApTppSuUkhZXN0VxHd" crossorigin="anonymous"></script> <script src="js/vue.js"></script> </head> <body> <div id="app-19"> <header-button></header-button> <hr /> <header-button></header-button> </div> <script src="js/my-components.js"></script> <script type="text/javascript"> var vm = new Vue({ el: '#app-19' }) </script> </body> </html>
10.3 组件通信
vue 实例本身就是一个组件(模板就是 el 指定容器,data 就是组件数据,methods 就是组件的事件函数)
在 vue 实例指定的 el 容器中引用的组件称为子组件,当前 vue 实例就是父组件
注:子组件按钮模板不能触发父组件的方法,子组件的按钮可以触发子组件的方法。
10.3.1 父传子
vue 实例引用组件的时候,传递数据到引用的组件中
通过组件的属性实现父组件传递数据到子组件
示意图
10.3.2 子传父 – 使用 props
属性动态传递参数
通过子组件的按钮“调用”父组件的函数,通过函数传值
流程示意图
父组件:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <link rel="stylesheet" href="css/my-components.css" /> <script src="js/vue.js"></script> </head> <body> <div id="app-21"> <!-- 组件的引用必须在 vue 实例指定的容器中 --> <header-bar :name="message" @my-event="parentMethod"></header-bar> 子组件传到父组件的标题名称: {{title}} <hr /> <header-bar name="关羽"></header-bar> </div> <script src="js/my-components-bar2.js"></script> <script type="text/javascript"> var vm = new Vue({ el: '#app-21', data: { message: "貂蝉", title: "" }, methods: { parentMethod: function (res) { vm.title = res; } } }) </script> </body> </html>
子组件:
Vue.component('header-bar', { data: function() { return { title: "三国 -- √" } }, template: `<div class="divStyle"> <table class="tableStyle"> <tr> <td width="200" align="right" valign="middle"> <img src="img/1.jpg" class="logoImg" /> </td> <td> <label class="nameStyle"> 登录人: {{name}} </label> </td> <td> <button @click="childMethod">组件按钮点击次数</button> </td> </tr> </table> </div>`, props: ["name"], methods: { childMethod: function () { this.$emit("my-event", this.title); } } });
10.3.3 总结
父组件通信子组件
props
: 子组件通过props获取定义父组件传递的自定义属性this.$refs
: 引用子组件this.$children
: 父组件childrens属性,存储着所有的子组件
子组件通信父组件(或根组件)
this.$emit
: 子组件通过$emit
访问父组件传递的自定义事件this.$parent
: 访问父组件this.$root
: 访问根组件。根组件root就是new Vue({el: "#app"});
中的el元素
10.4 组件插槽
当我们自定义 vue 组件时,允许组件中的部分内容在调用组件时进行定义 —— 插槽
10.4.1 插槽的使用
- 在自定义组件时通过
slot
标签在组件的模板中定义插槽
my-components-bar-slot.js:
Vue.component('header-bar', { data: function() { return { title: "三国 -- √" } }, template: `<div class="divStyle"> <table class="tableStyle"> <tr> <td width="200" align="right" valign="middle"> <img src="img/1.jpg" class="logoImg" /> </td> <td> <label class="nameStyle"> 登录人: {{name}} </label> </td> <td> <slot></slot> </td> <td> <button @click="childMethod">组件按钮点击次数</button> </td> </tr> </table> </div>`, props: ["name"], methods: { childMethod: function () { this.$emit("my-event", this.title); } } });
- 在父组件中调用此组件时,指定插槽填充的模板
示例1:插槽填充 搜索框
<header-bar :name="message"> <input /> <button>搜索</button> </header-bar>
示例2:插槽填充 按钮
<header-bar :name="message" @my-event="parentMethod"> <div> <a href="#">首页</a> <a href="#">后台</a> <a href="#">管理</a> <a href="#">关于</a> </div> </header-bar>
10.4.2 具名插槽
当组件中的插槽数量 > 1 时,需要给组件中的
slot
标签添加name
属性指定插槽的名字
- 定义组件
Vue.component(‘page-frame’, {
template: <div> <div id="header" style="width: 100%; height: 100px; background: pink"> {{title}}<br /> slot1 : <br /> <slot name="slot1"></slot> </div> <div style="width: 100%; height: 580px"> slot2 : <br /> <slot name="slot2"></slot> </div> <div id="footer" style="width: 100%; height: 40px; background: lightblue">{{cr}}</div> </div>,
props: [“title”, “cr”]
});
10.4.3 插槽作用域
- 定义组件时,将组件中的数据绑定到
slot
标签
my-components-bar-slot.js:
Vue.component('page-frame-scope', { template: `<div> <div id="header" style="width: 100%; height: 100px; background: pink"> {{title}}<br /> slot1 : <br /> <slot name="slot1"></slot> </div> <div style="width: 100%; height: 580px"> slot2 : <br /> <slot name="slot2" v-bind:sites="sites"></slot> </div> <div id="footer" style="width: 100%; height: 40px; background: lightblue">{{cr}}</div> </div>`, props: ["title", "cr"], data: function () { return { sites: [ { "name": "菜鸟教程", "url": "www.runoob.com" }, { "name": "google", "url": "www.google.com" }, { "name": "微博", "url": "www.weibo.com" } ] } } });
- 引用组件时,在填充插槽的模板上使用
slot-scopt
属性获取插槽绑定的值
搜索
名称 | 网站 |
{{site.name}} | {{site.url}} |
十一、axios 异步通信
11.1 axios 介绍
vue 可以实现数据的渲染,但是如何获取数据呢?
vue 本身不具备通信能力,通常结合 axios —— 一个专注于异步通信的 js 框架来使用(Vue.js 2.0 版本推荐使用 axios 来完成 ajax 请求。)
axios 数据通信
vue 数据渲染
什么是 axios
Axios 是一个基于 promise 的 HTTP 库,可以用在浏览器和 node.js 中。
菜鸟教程 axios 说明文档:https://www.runoob.com/vue2/vuejs-ajax-axios.html
11.2 axios 入门使用
- axios —— 实现步骤复杂
- JQuery 笨重
- axios 简洁、高效,对 RESTful 支持良好
11.3 axios 异步请求方法
axios 提供了多种异步请求方法,实现对 RESTful 风格的支持