Vue.js 2.x笔记:组件(5)
1. 组件简介
组件(Component)是 Vue.js 最强大的功能之一,组件可以扩展 HTML 元素,封装可重用的代码。
组件:为了拆分Vue实例的代码量,以不同的组件来划分不同的功能模块,需要什么样的功能,可以去调用对应的组件。
模块化和组件化的区别:
◊ 模块化:是从代码逻辑的角度进行划分的;方便代码分层开发,保证每个功能模块的职能单一。
◊ 组件化:是从UI界面的角度进行划分的;前端的组件化,方便UI组件的重用。
2. 注册组件
Vue.js提供两种组件注册方式:全局注册和局部注册。
2.1 全局组件
全局注册需要在根实例初始化之前注册,这样组件才能在任意实例中被使用。
注册全局组件语法格式:
Vue.component(tagName, options)
其中,tagName 为组件名,options 为配置选项。
这条语句需要写在var vm = new Vue({ options })之前。
注册组件后调用方式:
<tagName></tagName>
所有实例都能用全局组件。
组件名定义方式:PascalCase和kebab-case。在组件命名时可以采用PascalCase或kebab-case,但在DOM中只能使用kebab-case。
PascalCase示例:
<div id="app">
<my-component></my-component>
</div>
<script>
Vue.component('MyComponent', {
template: '<div>标题</div>'
}); var vm = new Vue({
el: "#app"
});
</script>
kebab-case示例:
<div id="app">
<my-component></my-component>
</div>
<script>
Vue.component('my-component', {
template: '<div>标题</div>'
}); var vm = new Vue({
el: "#app"
});
</script>
<div id="app">
<home></home>
</div>
<script>
Vue.component("home", {
template: "<div>{{text}}</div>",
data: function () {
return {
text: "主页"
};
}
}); new Vue({
el: "#app"
});
</script>
<div id="app">
<home></home>
</div>
<script>
var homeTpl = Vue.extend({
template: "<div>{{text}}</div>",
data: function () {
return {
text: "主页"
};
}
}); Vue.component('home', homeTpl); new Vue({
el: "#app"
});
</script>
使用template标签:
<div id="app">
<home></home>
</div>
<template id="tpl">
<div>{{text}}</div>
</template>
<script>
Vue.component("home", {
template: "#tpl",
data: function () {
return {
text: "主页"
};
}
}); new Vue({
el: "#app"
});
</script>
2.2 局部组件
局部组件只能在被注册的组件中使用,不能在其他组件中使用。
<div id="app">
<home></home>
</div>
<script>
new Vue({
el: "#app",
components: {
"home": {
template: "<div>{{text}}</div>",
data: function () {
return {
text: "主页"
};
}
}
}
});
</script>
2.3 Vue.extend
2.3.1 基本使用
<div id="app">
<home></home>
</div>
<script>
var home = Vue.extend({
template: "<div>标题</div>"
}); Vue.component("home", home); new Vue({
el: "#app"
});
</script>
2.3.2 参数data
data:在 Vue.extend() 中必须是函数。
<body>
<task></task> <script>
var task = Vue.extend({
template:"<div>{{ taskName }}</div>",
data:function(){
return {
taskName:"任务名称"
}
}
}); new task().$mount("task");
</script>
</body>
2.3.3 使用$mount
在实例中没有el选项时,可通过mount挂载。
mount:挂载,将vue实例挂靠在某个dom元素上的一个过程。
<!DOCTYPE html>
<html> <head>
<meta charset="utf-8">
<title>libing.vue</title>
<script src="node_modules/vue/dist/vue.min.js"></script>
</head> <body>
<div id="app"></div>
<script>
var home = Vue.extend({
template: "<div>标题</div>"
}); new home().$mount("#app");
</script>
</body> </html>
3. 组件通信
3.1 props:父组件向子组件传递数据
prop 是组件用来传递数据的自定义特性,在组件上注册自定义属性。
prop特性注册成为组件实例的属性。
props
:父组件向子组件传递数据。
一个组件默认可以拥有任意数量的 prop,任何值都可以传递给任何 prop。
3.1.1 静态props
示例:
<div id="app">
<home text="主页"></home>
</div>
<script>
var homeTpl = Vue.extend({
props:["text"],
template: "<div>{{text}}</div>"
}); Vue.component('home', homeTpl); new Vue({
el: "#app"
});
</script>
3.1.2 动态props
使用 v-bind 动态绑定 props 的值到父组件的数据中。每当父组件的数据变化时,该变化也会传导给子组件。
<div id="app">
<home v-bind:text="text"></home>
</div>
<script>
var homeTpl = Vue.extend({
props: ["text"],
template: "<div>{{text}}</div>"
}); Vue.component('home', homeTpl); new Vue({
el: "#app",
data: {
text: "主页"
}
});
</script>
由于HTML Attribute不区分大小写,当使用DOM模板时,camelCase的props名称要转为kebab-case。
<div id="app">
<home warning-text="提示信息"></home>
</div>
<script>
Vue.component('home', {
props: ['warningText'],
template: '<div>{{ warningText }}</div>'
}); var vm = new Vue({
el: "#app"
});
</script>
传递的数据可以是来自父级的动态数据,使用指令v-bind来动态绑定props的值,当父组件的数据变化时,也会传递给子组件。
<div id="app">
<home v-bind:warning-text="warningText"></home>
</div>
<script>
Vue.component('home', {
props: ['warningText'],
template: '<div>{{ warningText }}</div>'
}); var vm = new Vue({
el: "#app",
data: {
warningText: '提示信息'
}
});
</script>
注:prop 是单向传递,当父组件的属性变化时,将传递给子组件,但是不会反过来。这是为了防止子组件无意修改了父组件的状态。
示例:
<template>
<li>{{ id }}-{{ text }}</li>
</template>
<script>
export default {
name: "TodoItem",
props: ["id", "text"]
};
</script>
TodoItem.vue
<template>
<ul>
<TodoItem
v-for="item in list"
:key="item.id"
:id="item.id"
:text="item.text"
></TodoItem>
</ul>
</template>
<script>
import TodoItem from "./TodoItem"; export default {
name: "TodoList",
components: {
TodoItem
},
data: function() {
return {
list: [
{
id: 1,
text: "To Do"
},
{
id: 2,
text: "In progress"
},
{
id: 3,
text: "Done"
}
]
};
}
};
</script>
TodoList.vue
<template>
<div id="app">
<TodoList />
</div>
</template> <script>
import TodoList from './views/TodoList' export default {
name: 'App',
components: {
TodoList
}
}
</script>
App.vue
3.1.3 props验证
为组件的 prop 指定验证要求,如果有一个需求没有被满足,则 Vue 会在控制台中警告。
Vue.component('my-component', {
props: {
// 基础的类型检查 (`null` 匹配任何类型)
propA: Number,
// 多个可能的类型
propB: [String, Number],
// 必填的字符串
propC: {
type: String,
required: true
},
// 带有默认值的数字
propD: {
type: Number,
default: 100
},
// 带有默认值的对象
propE: {
type: Object,
// 对象或数组且一定会从一个工厂函数返回默认值
default: function () {
return {
message: 'hello'
}
}
},
// 自定义验证函数
propF: {
validator: function (value) {
// 这个值必须匹配下列字符串中的一个
return ['success', 'warning', 'danger'].indexOf(value) !== -1
}
}
}
});
类型检查:type可以是下列原生构造函数中的一个:String、Number、Boolean、Array、Object、Date、Function、Symbol,也可以是一个自定义的构造函数,并且通过 instanceof 来进行检查确认。
示例:
<div id="app">
<parent-component></parent-component>
</div> <template id="child-component1">
<h2>{{ message }}</h2>
</template>
<template id="child-component2">
<h2>{{ message }}</h2>
</template>
<template id="parent-component">
<div>
<child-component1></child-component1>
<child-component2></child-component2>
</div>
</template> <script>
Vue.component('parent-component', {
template: '#parent-component',
components: {
'child-component1': {
template: '#child-component1',
data() {
return {
message: '子组件1'
};
}
},
'child-component2': {
template: '#child-component2',
data() {
return {
message: '子组件2'
};
}
}
}
}); var vm = new Vue({
el: "#app"
});
</script>
示例:
<div id="app">
<todo :todo-data="taskList"></todo>
</div> <template id="tpl-todo-item">
<li>{{ id }} - {{ text }}</li>
</template> <template id="tpl-todo-list">
<ul>
<todo-item v-for="item in todoData" :id="item.id" :text="item.text"></todo-item>
</ul>
</template> <script>
// 构建一个子组件
var todoItem = Vue.extend({
template: "#tpl-todo-item",
props: {
id: {
type: Number,
required: true
},
text: {
type: String,
default: ''
}
}
}) // 构建一个父组件
var todoList = Vue.extend({
template: "#tpl-todo-list",
props: {
todoData: {
type: Array,
default: []
}
},
// 局部注册子组件
components: {
todoItem: todoItem
}
}) // 注册到全局
Vue.component('todo', todoList) new Vue({
el: "#app",
data: {
taskList: [{
id: 1,
text: 'New'
},
{
id: 2,
text: 'InProcedure'
},
{
id: 3,
text: 'Done'
}
]
}
});
</script>
3.2 自定义事件:子组件向父组件传递数据
每一个Vue实例都实现事件接口:
$on(eventName)
:监听事件
$emit(eventName)
:触发事件,自定义事件。推荐始终使用 kebab-case 的事件名。
子组件需要向父组件传递数据时,子组件用$emit(eventName)
来触发事件,父组件用$on(eventName)
来监听子组件的事件。
示例1:
<template>
<div>
<button @click="onparent">子组件触发父组件</button>
</div>
</template>
<script>
export default {
methods: {
onparent() {
this.$emit("onchild");
}
}
};
</script>
Child.vue
<template>
<div>
<Child @onchild="inparent"></Child>
</div>
</template>
<script>
import Child from "./Child";
export default {
components: {
Child
},
methods: {
inparent() {
console.log("父组件响应了");
}
}
};
</script>
Parent.vue
<template>
<div id="app">
<Parent />
</div>
</template> <script>
import Parent from './views/Parent' export default {
name: 'App',
components: {
Parent
}
}
</script>
App.vue
示例2:
<div id="app">
<searchbar></searchbar>
</div> <template id="tpl-search-form">
<div class="input-group form-group" style="width: 500px;">
<input type="text" class="form-control" placeholder="请输入查询关键字" v-model="keyword" />
<span class="input-group-btn">
<input type="button" class="btn btn-primary" value="查询" @click="search">
</span>
</div>
</template>
<template id="tpl-search-bar">
<searchform @onsearch="search"></searchform>
</template> <script>
// 构建一个子组件
var searchform = Vue.extend({
template: "#tpl-search-form",
data: function () {
return {
keyword: 'libing'
};
},
methods: {
search: function () {
this.$emit('onsearch', this.keyword);
}
}
}); // 构建一个父组件
var searchbar = Vue.extend({
template: "#tpl-search-bar",
components: {
searchform: searchform
},
methods: {
search(keyword) {
console.log(keyword);
}
}
}) // 注册到全局
Vue.component('searchbar', searchbar); new Vue({
el: "#app"
});
</script>
购物车示例:
<div id="app">
<shoppingcart :shopppingcarts="products" @calc="getTotal"></shoppingcart>
<div>总计:{{ totalPrice }}</div>
</div>
<template id="shoppingcart">
<table>
<tr>
<th>商品ID</th>
<th>商品名称</th>
<th>单价</th>
<th>数量</th>
</tr>
<tr v-for="item in shopppingcarts">
<td>{{ item.ID }}</td>
<td>{{ item.ProductName }}</td>
<td>{{ item.UnitPrice }}</td>
<td><input type="text" v-model="item.Quantity" @change="calcTotal" /></td>
</tr>
</table>
</template>
<script>
var shoppingcart = Vue.extend({
template: "#shoppingcart",
props: ["shopppingcarts"],
methods: {
calcTotal: function () {
this.$emit("calc");
}
}
}); new Vue({
el: "#app",
components: {
shoppingcart: shoppingcart
},
data: {
totalPrice: 100,
products: [{
ID: 1,
ProductName: "手机",
UnitPrice: 1000,
Quantity: 2
}, {
ID: 2,
ProductName: "电脑",
UnitPrice: 5000,
Quantity: 5
}]
},
methods: {
getTotal() {
console.log(new Date());
this.totalPrice = 0;
this.products.forEach(product => {
this.totalPrice += product.UnitPrice * product.Quantity;
});
}
},
mounted() {
//当vue执行完毕之后,去执行函数
this.getTotal();
}
});
</script>
3.3 EventBus:非父子组件通信
非父子组件包括:兄弟组件、跨级组件。
通过实例化一个Vue对象 (如:const bus = new Vue() ) 作为总线,在组件中通过事件传递参数( bus.$emit(event, [...args]) ),再在其他组件中通过bus来监听此事件并接受参数( bus.$on(event, callback) ),从而实现通信。
示例:
bus.js
import Vue from 'vue' const bus = new Vue(); export default bus;
Send.vue
<template>
<div class="send">
<h1>发送参数:{{msg}}</h1>
<button @click="send">发送</button>
</div>
</template>
<script>
import bus from "../utils/bus.js"; export default {
data() {
return {
msg: "Hello World"
};
},
methods: {
send() {
bus.$emit("receive", this.msg);
}
}
};
</script>
Receive.vue
<template>
<div class="receive">
<h1>接收参数:{{msg}}</h1>
</div>
</template>
<script>
import bus from "../utils/bus.js"; export default {
data() {
return {
msg: "Hello"
};
},
created() {
bus.$on("receive", param => {
this.msg = param;
});
},
beforeDestroy() {
bus.$off("receive");
}
};
</script>
App.vue
<template>
<div id="app">
<Send></Send>
<Receive></Receive>
</div>
</template> <script>
import Send from './views/Send'
import Receive from './views/Receive' export default {
name: 'App',
components: {
Send,
Receive
}
}
</script>
Vue.js 2.x笔记:组件(5)的更多相关文章
- 两万字Vue.js基础学习笔记
Vue.js学习笔记 目录 Vue.js学习笔记 ES6语法 1.不一样的变量声明:const和let 2.模板字符串 3.箭头函数(Arrow Functions) 4. 函数的参数默认值 5.Sp ...
- 基于Vue.js的表格分页组件
有一段时间没更新文章了,主要是因为自己一直在忙着学习新的东西而忘记分享了,实在惭愧. 这不,大半夜发文更一篇文章,分享一个自己编写的一个Vue的小组件,名叫BootPage. 不了解Vue.js的童鞋 ...
- Vue.js的表格分页组件
转自:http://www.cnblogs.com/Leo_wl/p/5522299.html 有一段时间没更新文章了,主要是因为自己一直在忙着学习新的东西而忘记分享了,实在惭愧. 这不,大半夜发文更 ...
- 从零开始学习Vue.js,学习笔记
一.为什么学习vue.js methods 只有纯粹的数据逻辑,而不是去处理 DOM 事件细节. vue.js兼具angular.js和react的优点,并且剔除了他们的缺点 官网:http://cn ...
- vue.js应用开发笔记
看vue.js有几天了,之前也零零散散的瞅过,不过一直没有动手去写过demo,这几天后台事比较少,一直在讨论各种需求(其实公司对需求还是比较重视与严谨的,一个项目需求讨论就差不多一周了,这要搁之前,天 ...
- vue.js初学,笔记1,安装
最近学习vue.js,下面是笔记: 说明:因为npm安装插件是从国外服务器下载,受网络影响大,可能出现异常,如果npm的服务器在中国就好了,所以我们乐于分享的淘宝团队干了这事.来自官网:"这 ...
- 基于 Vue.js 的移动端组件库mint-ui实现无限滚动加载更多
通过多次爬坑,发现了这些监听滚动来加载更多的组件的共同点, 因为这些加载更多的方法是绑定在需要加载更多的内容的元素上的, 所以是进入页面则直接触发一次,当监听到滚动事件之后,继续加载更多, 所以对于无 ...
- vue.js中的全局组件和局部组件
组件(Component)是 Vue.js 最强大的功能之一.组件可以扩展 HTML 元素,封装可重用的代码.在较高层面上,组件是自定义元素, Vue.js 的编译器为它添加特殊功能. 组件的使用有三 ...
- Vue.js 2.x笔记:状态管理Vuex(7)
1. Vuex简介与安装 1.1 Vuex简介 Vuex是为vue.js应用程序开发的状态管理模式,解决的问题: ◊ 组件之间的传参,多层嵌套组件之间的传参以及各组件之间耦合度过高问题 ◊ 不同状态中 ...
随机推荐
- 将你的前端应用打包成docker镜像并部署到服务器?仅需一个脚本搞定
1.前言 前段时间,自己搞了个阿里云的服务器.想自己在上面折腾,但是不想因为自己瞎折腾而污染了现有的环境.毕竟,现在的阿里云已经没有免费的快照服务了.要想还原的话,最简单的办法就是重新装系统.而一旦重 ...
- 深入Go的底层,带你走近一群有追求的人
目录 缘起 自我介绍的技巧 硬核知识点 什么是plan9汇编 汇编角度看函数调用及返回过程 汇编角度看slice 正确参与Go夜读活动的方式 阅读原文 上周六晚上,我参加了"Go夜读&quo ...
- IOS多态在项目中的应用
今天我们讲述一个知识点(大家可能遗漏的) 多态是面试程序设计(OOP)一个重要特征,但在iOS中,可能比较少的人会留意这个特征,实际上在开发中我们可能已经不经意的使用了多态.比如说: 有一个table ...
- 如何在已有项目中引入FineUIMvc
FineUIMvc简介 FineUIMvc 是基于 jQuery 的专业 ASP.NET MVC 控件库,其前身是基于 WebForms 的开源控件库 FineUI(历时9年120多个版本).Fine ...
- .net简介(一)
什么是.NET 微软的开发平台,包含规范.编程语言.标准类.工具等.一般认为.net就是微软的软件开发技术.同时微软的所有产品也提供.NET类型的API. .NET概览 .net的组成: 开发语言,遵 ...
- Python二级-----------程序冲刺1
1. 仅使用 Python 基本语法,即不使用任何模块,编写 Python 程序计算下列数学表达式的结果并输出,小数点后保留3位. ...
- iis读取不到本地证书问题
导入证书时,通过mmc命令打开控制台->添加管理单元或删除单元->选择本地计算机账号->然后导入证书,解决 ssl证书无法与www.xxx通信. 证书导入后,不能正常读取.有两个问题 ...
- Dynamics 365-关于Solution的那些事(一)
关于CRM Solution,我准备写两到三篇的博客来做下介绍:包括一些基本信息,超大solution,还有增量更新solution操作等. CRM中的component,都是放在一个名叫Soluti ...
- 27号华为笔试(三道ac两道)
三道题目case:100,100,0: 三个题目: 前两个都全部ac了,第三题没时间: 记录一下大概的思路: 第一题 主要通过Java中的字符串处理函数:然后控制字符串输入格式: 卡bug的点: 1: ...
- MyDAL - .QueryListAsync() 使用
索引: 目录索引 一.API 列表 .QueryListAsync() .QueryListAsync<M>() 如: .QueryListAsync<AgentInventoryR ...