【Vue组件系统】
"vue.js既然是框架,那就不能只是简单的完成数据模板引擎的任务,它还提供了页面布局的功能。本文将详细介绍使用vue.js进行页面布局的强大工具——vue.js组件系统。
每一个新技术的诞生,都是为了解决特定的问题。
组件的出现就是为了解决页面布局等等一系列的问题。
Vue中的组件分为两种:全局组件与局部组件.
@
全局组件
注册
方式一:
<body>
<div id="app"></div>
<script>
// 下面的'global-component'是自定义的组件名,也是自定义的标签名
Vue.component('global-component', {
// 错误写法:(网页中不会显示)
// template: `<h1>{{ zyk }}</h1><h1>{{ zyk }}</h1>`,
// 正确写法:(要在外面套一层标签)
template: `
<div>
<h1>{{ zyk01 }}</h1>
<h1>{{ zyk02 }}</h1>
</div>
`,
// data必须是函数,固定写法
data() {
return {
zyk01: 'Hello zyk01',
zyk02: 'Hello zyk02',
};
},
});
new Vue({
el: '#app',
template: '<global-component></global-component>',
});
</script>
</body>
方式二:
<body>
<div id="app">
<!--调用自定义的标签名 可重复调用 -->
<global-component></global-component>
<global-component></global-component>
</div>
<script>
// 下面的'global-component'是自定义的组件名,也是自定义的标签名
Vue.component('global-component', {
// 错误写法:(网页中不会显示)
// template: `<h1>{{ zyk }}</h1><h1>{{ zyk }}</h1>`,
// 正确写法:(要在外面套一层标签)
template: `
<div>
<h1>{{ zyk }}</h1>
</div>
`,
// data必须是函数,固定写法
data() {
return {
zyk: 'Hello zyk',
};
},
});
new Vue({
el: '#app',
});
</script>
</body>
局部组件
全局注册往往是不够理想的。比如,如果你使用一个像 webpack 这样的构建系统,全局注册所有的组件意味着即便你已经不再使用一个组件了,它仍然会被包含在你最终的构建结果中。这造成了用户下载的 JavaScript 无谓的增加。
全局组件适中是存在的,除非程序结束,如果组件越来越大,那么程序所占用的空间和消耗的性能就会更大。
所以我们需要使用局部组件。不用的时候,被垃圾回收。
注册
方式一:
<body>
<div id="app">
<!--第三步:在根元素中使用-->
<!--会将当前div渲染进DOM(也就是这里id为app的div)-->
<my-header></my-header>
</div>
<script>
// 第一步:创建局部组件
let Header = {
template: `
<div>
<button @click='count++'>{{ count }}</button>
<button @click='count++'>{{ count }}</button>
</div>
`,
data() {
return {
count: 0,
};
},
};
new Vue({
el: '#app',
// 第二步:在根实例中调用它
components: {
'my-header': Header,
},
});
</script>
</body>
方式二:
<body>
<div id="app"></div>
<script>
let Header = {
template: `
<div>
<button @click="count++">{{ count }}</button>
<button @click="count++">{{ count }}</button>
</div>
`,
data() {
return {
count: 0,
};
},
};
new Vue({
el: '#app',
// 这种方法不会将div渲染进DOM,以template为根元素
template: `<my-header></my-header>`,
// template: `<my-header/>`,
components: {
'my-header': Header,
},
});
</script>
</body>
对于components 对象中的每个属性来说,其属性名就是自定义元素的名字,其属性值就是这个组件的选项对象。
子组件的用法
<body>
<div id="app"></div>
<script>
// 第一步:创建一个局部组件(作为子组件)
let Header01 = {
template: `
<div style='color: green;'>
<h1>{{ greeting }}</h1>
</div>
`,
data () {
return {
greeting: "我是子组件:Header01",
};
},
};
// 再创建一个吧(子组件)
let Header02 = {
template: `
<div style='color: blue;'>
<h1>{{ greeting }}</h1>
</div>
`,
data () {
return {
greeting: "我是子组件:Header02",
};
},
};
// 下面的这个作为父组件
let App = {
// 第二步:在父组件中调用子组件
template: `
<div style='background-color: black;'>
<app-header01></app-header01>
<app-header02></app-header02>
</div>
`,
// 第三步:在父组件中注册子组件
components: {
'app-header01': Header01,
'app-header02': Header02,
},
};
new Vue({
el: '#app',
template: `<App></App>`,
components: {
App,
},
});
</script>
</body>
父子组件的通讯
<body>
<div id="app"></div>
<script>
// 子组件
let Header = {
// ==== 第四步:调用提取后的数据 ====
template: `
<div>
<h1>{{ greeting }} {{ fatherData }} </h1>
</div>
`,
// ==== 第三步:提取传入的数据====
props: ['fatherData'],
// props:["传入时指定的关键字", "..."] -> 固定写法,可传入多个值
data() {
return {
greeting: 'Hello',
};
},
};
// 父组件
let App = {
// ==== 第一步:将数据传入子组件 ====
// 下面的:fatherData="name"为传入子组件中数据,前者为传入关键字,后者为data中返回的数据
template: `
<div>
<app-header :fatherData="name"></app-header>
</div>
`,
components: {
'app-header': Header,
},
data() {
return {
// ==== 第一步:先定义一个数据 ====
name: 'zyk',
};
},
};
new Vue({
el: '#app',
template: `<App></App>`,
components: {
App,
},
});
</script>
</body>
子父组件的通讯
下面示例的基本思路:
·
子组件与父组件各定义一个事件,且子组件事件函数中可触发父组件的事件.
- 先触发子组件中的事件——执行子组件事件函数;
- 在子组件的事件函数中触发父组件的事件,同时向父组件传入数据;
- 父组件事件被触发,同时接收传入的数据,执行事件,ok.
<body>
<div id="app"></div>
<script>
// 子组件
let Header = {
template: `
<div>
<button @click="somClick">点我让BaBa变大</button>
</div>
`,
methods: {
somClick: function () {
// Vue中给我提供的触发自定义事件的方式:
this.$emit('change-size', 0.1);
// this.$emit("父组件事件名", "参数(即传入父组件的数据)")
},
},
};
// 父组件
let App = {
// 下面的change-size是自定义的事件名,fatherClick是事件函数
template: `
<div>
<my-header @change-size="fatherClick"></my-header>
<span :style="{ fontSize: postFontSize + 'em' }">我是BaBa</span>
</div>
`,
components: {
'my-header': Header,
},
data() {
return {
postFontSize: 1,
};
},
methods: {
fatherClick: function (value) {
// value是this.$emit('change-size', 0.1);传过来的参数(0.1)
this.postFontSize += value;
},
},
};
new Vue({
el: '#app',
template: `<App></App>`,
components: {
App,
},
});
</script>
</body>
非父子组件的通讯
<body>
<div id="app">
<zyk01></zyk01>
<zyk02></zyk02>
</div>
<script>
// 用作中间调度器
let Event = new Vue();
let zyk01 = {
template: `
<div>
<h1>zyk01</h1>
<button @click="click01">点击向zyk02传数据</button>
</div>
`,
methods: {
click01: function () {
// Event.$emit('事件函数名', "要传的数据");
Event.$emit('click02', "这是zyk01向zyk02发送的消息");
},
},
};
let zyk02 = {
template: `
<div>
<h1>zyk02</h1>
<span>{{ say }}</span>
</div>
`,
data() {
return {
say: '',
};
},
mounted() {
let that = this;
// 监听中间调度器中的方法:$on("事件函数名", "要执行的函数")
Event.$on('click02', function (data) {
console.log(data);
that.say = data;
})
}
};
const app = new Vue({
el: '#app',
components: {
zyk01: zyk01,
zyk02: zyk02,
},
});
</script>
</body>
混入
混入可提高代码的重用性.
<body>
<div id="app">
<test01></test01>
<test02></test02>
</div>
<script>
let mixs = {
methods: {
show: function (name) {
console.log(name + "来了");
},
hide: function (name) {
console.log(name + "走了");
},
},
};
let Test01 = {
// mouseenter:获取光标 mouseleave:失去光标
template: `
<div>
<button @mouseenter="show('鼠标01')" @mouseleave="hide('鼠标01')">鼠标01</button>
</div>
`,
mixins: [mixs], // !
};
let Test02 = {
template: `
<div>
<button @mouseenter="show('鼠标02')" @mouseleave="hide('鼠标02')">鼠标02</button>
</div>
`,
mixins: [mixs], // !
};
new Vue({
el: '#app',
components: {
'test01': Test01,
'test02': Test02,
},
});
</script>
</body>
插槽
有时候我们需要向组件传递一些数据,这时候可以使用插槽.
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.16/vue.min.js"></script>
<title>test</title>
<style>
.box {
width: 50px;
height: 50px;
background-color: green;
float: left;
margin-left: 5px;
}
</style>
</head>
<body>
<div id="app">
<global-component>test01</global-component>
<global-component>test02</global-component>
<global-component>test03</global-component>
<global-component>test04</global-component>
<global-component>test05</global-component>
</div>
<script>
// 下面的<slot></slot>标签,就是插槽(内容分发)
Vue.component("global-component", {
template: `
<div class="box">
<slot></slot>
</div>
`,
});
new Vue({
el: '#app',
});
</script>
</body>
</html>
具名插槽
该操作使用了组件的复用,通过使用具名插槽,我们可以在同一个组件内写入不同的页面,并且给不同的内容命名.
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.16/vue.min.js"></script>
<title>test</title>
<style>
.box {
width: 50px;
height: 65px;
background-color: green;
float: left;
margin-left: 5px;
}
</style>
</head>
<body>
<div id="app">
<global-component>
<!--定义具名插槽-->
<div slot="test01">test01</div>
<div slot="test02">test02</div>
<div slot="test03">test03</div>
<div>test04</div>
<div>test05</div>
</global-component>
</div>
<script>
Vue.component("global-component", {
// <slot name="指定上面定义的具名插槽"></slot>
// 注意显示顺序,是按照调用的先后排序的
// 最后面的<slot></slot>是默认插槽(未命名插槽),它会作为所有未匹配到插槽的内容的统一出口
template: `
<div class="box">
<slot name="test01"></slot>
<slot name="test03"></slot>
<slot name="test02"></slot>
<slot></slot>
</div>
`,
});
new Vue({
el: '#app',
});
</script>
</body>
</html>
使用组件的注意事项
单个根元素
当构建一个内容页面的组件时,我们的组件可能包含多个HTML标签。
<h1>Hello World</h1>
<h2>Hello Vue</h2>
然而如果你在模板中尝试这样写,Vue 会显示一个错误,并解释道 every component must have a single root element (每个组件必须只有一个根元素)。你可以将模板的内容包裹在一个父元素内,来修复这个问题,例如:
<div>
<h1>Hello World</h1>
<h2>Hello Vue</h2>
</div>
解析特殊的HTML元素
有些HTML元素,必须< ul >、< ol >、< table >和< select >,对于哪些元素可以出现在其内部是有严格限制的,而有些元素,例如< li >、< tr >和< option >,只能出现在其它某些特定元素的内部。
这会导致我们使用这些有约束条件的元素时遇到一些问题。例如:
<table>
<blog-post-row></blog-post-row>
</table>
这个自定义组件 < blog-post-row > 会被作为无效的内容提升到外部,并导致最终渲染结果出错。幸好这个特殊的 is 特性给了我们一个变通的办法:
<table>
<tr is="blog-post-row"></tr>
</table>
需要注意的是,如果我们从以下来源使用模板的话,这条限制是不存在的:
字符串 (例如:template: '...')
单文件组件 (.vue)
<script type="text/x-template">
使用组件实现导航栏
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>导航栏</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.16/vue.min.js"></script>
<!-- 引入样式 -->
<link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css">
<!-- 引入组件库 -->
<script src="https://unpkg.com/element-ui/lib/index.js"></script>
<style>
body {
margin: 0;
padding: 0;
}
.header {
position: fixed;
top: 0;
left: 0;
width: 100%;
}
.el-menu {
display: flex;
align-items: center;
justify-content: center;
}
.footer {
position: fixed;
bottom: 0;
left: 0;
width: 100%;
}
.header img {
position: absolute;
left: 80px;
top: -4px;
width: 118px;
height: 70px;
z-index: 999;
}
</style>
</head>
<body>
<div id="app">
</div>
<template id="header">
<div class="header">
<img src="https://www.luffycity.com/static/img/head-logo.a7cedf3.svg"/>
<el-menu :default-active="activeIndex" class="el-menu-demo" mode="horizontal">
<el-menu-item index="1">标题01</el-menu-item>
<el-menu-item index="2">标题02</el-menu-item>
<el-menu-item index="3">标题03</el-menu-item>
<el-menu-item index="4">标题04</el-menu-item>
<el-menu-item index="5">标题05</el-menu-item>
<el-menu-item index="6">标题06</el-menu-item>
<el-menu-item index="7">标题07</el-menu-item>
<el-menu-item index="8">标题08</el-menu-item>
</el-menu>
</div>
</template>
<template id="footer">
<div class="footer">
<el-menu class="el-menu-demo" mode="horizontal" background-color="black">
<el-menu-item index="1">关于我们</el-menu-item>
<el-menu-item index="2">联系我们</el-menu-item>
<el-menu-item index="3">商业合作</el-menu-item>
<el-menu-item index="4">帮助中心</el-menu-item>
<el-menu-item index="5">意见反馈</el-menu-item>
<el-menu-item index="6">新手指南</el-menu-item>
</el-menu>
</div>
</template>
<script>
let pageHeader = {
template: "#header",
data() {
return {
activeIndex: "1",
}
}
};
let pageFooter = {
template: "#footer",
};
let App = {
template: `
<div>
<div>
<page-header></page-header>
</div>
<div>
<page-footer></page-footer>
</div>
</div>
`,
components: {
'page-header': pageHeader,
'page-footer': pageFooter,
}
};
new Vue({
el: "#app",
template: `<app></app>`,
components: {
'app': App,
}
})
</script>
</body>
</html>
"
【Vue组件系统】的更多相关文章
- vue组件系统
1. 全局组件的注册 <body> <div id="app"> <!--<global-component>< ...
- Vue 组件系统
vue.js既然是框架,那就不能只是简单的完成数据模板引擎的任务,它还提供了页面布局的功能.本文详细介绍使用vue.js进行页面布局的强大工具,vue.js组件系统. 每一个新技术的诞生,都是为了解决 ...
- 【Vue】详解Vue组件系统
Vue渲染的两大基础方式 new 一个Vue的实例 这个我们一般会使用在挂载根节点这一初始化操作上: new Vue({ el: '#app' }) 注册组件并使用—— 全局注册 通过Vue.comp ...
- Vue框架之组件系统
1,Vue组件系统之全局组件 1.1Vue全局组件的在实例化调用Vue的模板中导入组件的名称 <!DOCTYPE html> <html lang="zh-cn" ...
- Vue.js之组件系统
vue.js既然是框架,那就不能只是简单的完成数据模板引擎的任务,它还提供了页面布局的功能.本文详细介绍使用vue.js进行页面布局的强大工具,vue.js组件系统. Vue.js组件系统 每一个新技 ...
- vue学习之四组件系统
vue.js既然是框架,那就不能只是简单的完成数据模板引擎的任务,它还提供了页面布局的功能.本文详细介绍使用vue.js进行页面布局的强大工具,vue.js组件系统. 一.Vue.js组件系统 每一个 ...
- JS组件系列——又一款MVVM组件:Vue(二:构建自己的Vue组件)
前言:转眼距离上篇 JS组件系列——又一款MVVM组件:Vue(一:30分钟搞定前端增删改查) 已有好几个月了,今天打算将它捡起来,发现好久不用,Vue相关技术点都生疏不少.经过这几个月的时间,Vue ...
- canvas实现倒计时效果示例(vue组件内编写)
前言: 此事例是在vue组件中,使用canvas实现倒计时动画的效果.其实,实现效果的逻辑跟vue没有关系,只要读懂canvas如何实现效果的这部分逻辑就可以了 canvas动画的原理:利用定时器,给 ...
- 一套代码小程序&Web&Native运行的探索06——组件系统
接上文:一套代码小程序&Web&Native运行的探索05——snabbdom 对应Git代码地址请见:https://github.com/yexiaochai/wxdemo/tre ...
随机推荐
- VS Code中Ionic serve命令 执行跳出的问题
项目情况:用vscode编写的ionic(tab类型)项目(具体使用到的技术Angular\Typescrip\Ionic) 具体情况如下: 找到的可能原因: 出错的项目情况:在一个ts文件中编写两个 ...
- C++——多态性
多态是指发出同样的消息被不同类型的对象接收时有可能导致完全不同的行为: 多态的实现:函数重载:运算符重载:虚函数 为什么需要重载运算符? 在C++没有复数运算,进行复数运算之前我们要事先写一个复数类, ...
- 番外:你真的了解 Oracle 的启动流程吗?
番外系列说明:该系列所有文章都将作为独立篇章进行知识点讲解,是对其他系列博文进行的补充说明,来自于博客园AskScuti. 主题:关于数据库启动流程的三个阶段 内容预览:本篇涉及数据库启动的三个阶段分 ...
- Vue.js ---Hello---1
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title> ...
- 其他 - YAML 入门
概述 简单介绍 YAML 语言 背景 很多地方, 都在使用 YAML k8s spring 其他 准备 验证工具 YAML.YML在线格式化校验工具 一个 YAML 转换 JSON 的工具 通常来说, ...
- vscode+vue 一些基本操作
1.安装好 vscode 和 node.js 安装node.js是为了用npm(管理项目依赖) 2.调出终端 crtl +~ , 3.终端全局安装 vue-cli 安装整个脚手架,能快速给我们构建v ...
- soundtouch change pitch matlab implementation
function output = changePitch(input, pitchInSemitones) % one octave is 12 semitones octave = pitchIn ...
- RGBA alpha 透明度混合算法
RGBA alpha 透明度混合算法 .分类: 图像处理 Ps技术 2011-05-25 09:11 1112人阅读 评论(0) 收藏 举报 Alpha 透明度混合算法,网上收集整理,分成以下三种: ...
- Oracle查询当前用户和当前用户下的所有表
转载自:http://blog.itpub.net/29485627/viewspace-1246317/ Oracle查询当前用户和当前用户下的所有表 (1)查询当前用户 SQL> show ...
- bzoj3626: [LNOI2014]LCA (树链剖分)
很神奇的方法 感觉是有生之年都想不到正解的这种 考虑对i 到根的节点权值 + 1,则从根到z的路径和就是lca(i,z)的深度 所以依次把0 ~ n - 1的点权值 + 1 对于询问[l, r] 这个 ...