Vue组件-组件组合
组件设计初衷就是要配合使用的,最常见的就是形成父子组件的关系:组件 A 在它的模板中使用了组件 B。
<html>
<head>
<title>Vue组件 A 在它的模板中使用了组件 B的例子</title>
<script src="vue.js"></script>
<style type="text/css">
</style>
</head>
<body>
<div id="app">
<my-item :list="list"></my-item>
</div> <script>
new Vue({
el:"#app",
data:{
list:["第一项","第二项","第三项"]
},
components:{
// 组件A
"my-item":{
template : `
<div>
<ul>
<li v-for="item in list">{{ item }}</li>
</ul>
<my-list :list="list"></my-list>
</div>
`,
props:['list'], components:{
// 组件B
"my-list":{
template : `
<div>
<ul>
<li v-for="item in list">{{ item }}</li>
</ul>
</div>
`,
props:['list']
} } },
}
})
</script>
</body>
</html>
在 Vue 中,父子组件的关系可以总结为 prop 向下传递,事件向上传递。父组件通过 prop 给子组件下发数据,子组件通过事件给父组件发送消息。看看它们是怎么工作的。
Prop
使用 Prop 传递数据
组件实例的作用域是孤立的。这意味着不能 (也不应该) 在子组件的模板内直接引用父组件的数据。父组件的数据需要通过 prop 才能下发到子组件中。
我们来看一个例子:
<html>
<head>
<title>Vue子组件的模板内直接引用父组件的数据</title>
<script src="vue.js"></script>
<style type="text/css">
</style>
</head>
<body>
<div id="app">
<child></child>
</div> <script>
new Vue({
el:"#app",
data:{
message:"Hello" },
components:{
"child":{
template:"<p>{{ message }}</p>"
} } })
</script>
</body>
</html>
这样子组件直接引用父组件的数据会出错!
子组件要显式地用 props
选项声明它预期的数据:
<html>
<head>
<title>Vue props父子之间通信</title>
<script src="vue.js"></script>
<style type="text/css">
</style>
</head>
<body>
<div id="app">
<child message="Hello Vue!!!"></child>
</div> <script>
new Vue({
el:"#app",
components:{
"child":{
template:"<p>{{ message }}</p>" ,
props:['message']
},
} })
</script>
</body>
</html>
这样就可以正常显示我们想要的结果
模板的要求
注意:组件的模板只能有一个根元素。下面的情况是不允许的。
template: `<div>这是一个局部的自定义组件,只能在当前Vue实例中使用</div>
<button>hello</button>`,
camelCase vs. kebab-case
HTML 特性是不区分大小写的。所以,当使用的不是字符串模板时,camelCase (驼峰式命名) 的 prop 需要转换为相对应的 kebab-case (短横线分隔式命名):
<div id="example">
<child myMessage="Hello Vue!!!"></child>
</div> <script>
new Vue({
el:"#example",
components:{
"child":{
template:"<p>{{ myMessage }}</p>",
props:["myMessage"]
}
}
})
</script>
这样就会报错
应改为
<div id="example">
<child my-Message="Hello Vue!!!"></child>
</div>
动态prop:
与绑定到任何普通的 HTML 特性相类似,我们可以用 v-bind
来动态地将 prop 绑定到父组件的数据。每当父组件的数据变化时,该变化也会传导给子组件:
<div id="example">
<input v-model="parentMsg"><br>
<child :message="parentMsg"></child>
</div>
<script>
Vue.component("child",{
template:"<span>{{ message }}</span>",
props:["message"] })
new Vue({
el:"#example",
data:{
parentMsg:""
}
})
</script>
浏览器打开显示
如果你想把一个对象的所有属性作为 prop 进行传递,可以使用不带任何参数的 v-bind
(即用 v-bind
而不是 v-bind:prop-name
)。
这句话怎么理解呢?我们看一个例子
<div id="app">
<my-component v-bind="todo"></my-component> <!--重点就是这-->
<!--不用将对象的属性写成 v-bind:first="todo.first" v-bind:second="todo.second"-->
</div>
Vue.component("my-component", {
template: "<div><span>第一个值是:{{first}},第二个值是:{{ second }}</span></div>",
props:["first","second"]
})
new Vue({
el:"#app",
data:{
todo:{
first:"Hello world",
second:"Hello Vue"
}
}
})
字面量语法 vs 动态语法
初学者常犯的一个错误是使用字面量语法传递数值:
<!-- 传递了一个字符串 "1" --> |
因为它是一个字面量 prop,它的值是字符串 "1"
而不是一个数值。如果想传递一个真正的 JavaScript 数值,则需要使用 v-bind
,从而让它的值被当作 JavaScript 表达式计算:
<!-- 传递真正的数值 --> |
例子如下:
<div id="example">
<child num1="4" v-bind:num2="4"></child>
</div>
<script>
Vue.component("child", {
template:"<p>使用了字面量传递数值+2得出结果:{{num1 + 2}}<br>使用了动态语法传递数值+2的结果:{{num2 + 2}}</p>",
props:["num1","num2"]
})
new Vue({
el:"#example",
})
</script>
浏览器打开显示:
单向数据流
Prop 是单向绑定的:当父组件的属性变化时,将传导给子组件,但是反过来不会。这是为了防止子组件无意间修改了父组件的状态,来避免应用的数据流变得难以理解。
另外,每次父组件更新时,子组件的所有 prop 都会更新为最新值。这意味着你不应该在子组件内部改变 prop。如果你这么做了,Vue 会在控制台给出警告。
<html>
<head>
<title>Vue单向数据流</title>
<script src="vue.js"></script>
</head>
<body>
<div id="example">
<my-button :count="count"></my-button>
</div>
<script>
Vue.component("my-button", {
props:["count"],
template:"<button @click='changeMessage'>{{ count }}</button>",
methods:{
changeMessage:function(){
this.count++
}
}
})
new Vue({
el:"#example",
data:{
count:0
}
})
</script> </body>
</html>
虽然想要做的功能实现了但vue报了个错,你不应该在子组件内部改变 prop
在两种情况下,我们很容易忍不住想去修改 prop 中数据:
Prop 作为初始值传入后,子组件想把它当作局部数据来用;
Prop 作为原始数据传入,由子组件处理成其它数据输出。
上面的例子就是第一种情况子组件怎么把它当局部数据用?
定义一个局部变量,并用 prop 的值初始化它:
data:function(){
return {
initCount: this.count
}
}
<html>
<head>
<title>Vue单向数据流</title>
<script src="vue.js"></script>
</head>
<body>
<div id="example">
<my-button :count="count"></my-button>
</div>
<script>
Vue.component("my-button", {
props:["count"],
template:"<button @click='changeMessage'>{{ initCount }}</button>",//别忘了这里也需要修改
data:function(){
return {
initCount: this.count
}
},
methods:{
changeMessage:function(){
this.initCount++
}
}
})
new Vue({
el:"#example",
data:{
count:0
}
})
</script> </body>
</html>
这样就ok了!
第二种情况请看下面例子:
<html>
<head>
<title>Vue单向数据流</title>
<script src="vue.js"></script>
</head>
<body>
<div id="example">
<input v-model="message">
<child :message="message"></child>
</div>
<script>
Vue.component("child", {
props:["message"],
template:"<p>{{ message }}</p>"
})
new Vue({
el:"#example",
data:{
message:"test"
}
})
</script>
</body>
</html>
这是一个双向绑定的例子,我们如何把输入的值将它用p标签转化成大写显示出来!
computed:{
changeMessage:function(){
return this.message.trim().toUpperCase();
}
}
<html>
<head>
<title>Vue单向数据流</title>
<script src="vue.js"></script>
</head>
<body>
<div id="example">
<input v-model="message">
<child :message="message"></child>
</div>
<script>
Vue.component("child", {
props:["message"],
template:"<p>{{ changeMessage }}</p>",
computed:{
changeMessage:function(){
return this.message.trim().toUpperCase();
}
}
})
new Vue({
el:"#example",
data:{
message:"test"
}
})
</script>
</body>
</html>
props验证
我们可以为组件的 prop 指定验证规则。如果传入的数据不符合要求,Vue 会发出警告。这对于开发给他人使用的组件非常有用。
<html>
<head>
<title>Vueprops验证</title>
<script src="vue.js"></script>
</head>
<body>
<div id="example">
<child
:name="name"
:age="age"
></child>
</div>
<script>
Vue.component("child", {
props:{
name:{
type:String,
default:"Vue",
required:true
},
age:Number
},
template:"<p>同学叫{{ name }},年龄:{{ age }}</p>",
}) new Vue({
el:"#example",
data:{
name:"胡小明",
age:18,
}
})
</script>
</body>
</html>
就从这个简单的例子分析一下用法:
type:可以使用type来声明这个参数可以接受的数据的类型,当检查规则只有一个的时候type可以略写如
当参数可以是多种类型的其中一个的时候,使用数组来表示
message:[String,Number]
type可以是以下原生类型:
String
Number
Boolean
Function
Object
Array
Symbol
required:可以使用required选项来声明这个参数是否必须传入。如果是true则为必填项,如不填则报出警告
defaule:使用default选项来指定当父组件未传入参数时props变量的默认值:
validator:当校验规则很复杂,默认提供的校验规则无法满足的时候可以使用自定义函数来校验。(上面代码没有写这个例子)
举例当小明可以去网吧上网的时候必定年龄是>=18的
props:{
age:{
validator:function(value){
return value >= 18
}
} }
Vue组件-组件组合的更多相关文章
- vue.js组件化开发实践
前言 公司目前制作一个H5活动,特别是有一定统一结构的活动,都要码一个重复的轮子.后来接到一个基于模板的活动设计系统的需求,便有了下面的内容.借油开车. 组件化 需求一到,接就是怎么实现,技术选型自然 ...
- VUE.JS组件化
VUE.JS组件化 前言 公司目前制作一个H5活动,特别是有一定统一结构的活动,都要码一个重复的轮子.后来接到一个基于模板的活动设计系统的需求,便有了下面的内容.借油开车. 组件化 需求一到,接就是怎 ...
- 如何抽象一个 Vue 公共组件
之前一直想写一篇关于抽象 Vue 组件的随笔,无奈一直没想到好的例子.恰巧最近为公司项目做了一个数字键盘的组件,于是就以这个为例聊聊如何抽象 Vue 的组件. 先上 Demo 与 源码.(demo最好 ...
- Vue 创建组件的方式
Vue 创建组件的方式 2018年08月07日 11:10:56 虔诚带着决然 阅读数:1015 版权声明:本文为博主原创文章,未经博主允许不得用做其他商业活动. https://blog.csd ...
- Vue.js 组件编码规范
本规范提供了一种统一的编码规范来编写 Vue.js 代码.这使得代码具有如下的特性: 其它开发者或是团队成员更容易阅读和理解. IDEs 更容易理解代码,从而提供高亮.格式化等辅助功能 更容易使用现有 ...
- 【06】Vue 之 组件化开发
组件其实就是一个拥有样式.动画.js逻辑.HTML结构的综合块.前端组件化确实让大的前端团队更高效的开发前端项目.而作为前端比较流行的框架之一,Vue的组件和也做的非常彻底,而且有自己的特色.尤其是她 ...
- 如何理解vue.js组件的作用域是独立的
vue.js组件的作用域是独立,可以从以下三个方面理解: 1.父组件模板在父组件作用域内编译,父组件模板的数据用父组件内data数据:2.子组件模板在子组件作用域内编译,子组件模板的数据用子组件内da ...
- Vue 子组件向父组件传参
直接上代码 <body> <div id="counter-event-example"> <p>{{ total }}</p> & ...
- vue.js 组件之间传递数据
前言 组件是 vue.js 最强大的功能之一,而组件实例的作用域是相互独立的,这就意味着不同组件之间的数据无法相互引用.如何传递数据也成了组件的重要知识点之一. 组件 组件与组件之间,还存在着不同的关 ...
随机推荐
- vue中的render函数介绍
简介:对于不了解slot的用法(参考:大白话vue-slot的用法)又刚接触render函数的同学来说,官网的解释无疑一脸懵逼,这里就整理下个人对render函数的理解 问题: 1.render函数是 ...
- 求能粘贴Word 内容(含图片)的在线编辑器
word图片转存,是指UEditor为了解决用户从word中复制了一篇图文混排的文章粘贴到编辑器之后,word文章中的图片数据无法显示在编辑器中,也无法提交到服务器上的问题而开发的一个操作简便的图片转 ...
- (转)Window 中杀死指定端口 cmd 命令行 taskkill
Windows平台 两步方法 : 1 查询端口占用,2 强行杀死进程 netstat -aon|findstr "8080" taskkill /pid 4136-t -f ...
- 虚拟机中安装Linux_Centos7操作系统(最小化安装)
我们打开之前安装的VM, 点击 “创建新的虚拟机”: 我们选 典型 安装 简单点 然后下一步: 我们稍后安装操作系统 ,点下一步: 这里选 Linux 然后下拉 选CentOS 64位,然后下一步: ...
- day29—JavaScript中DOM的基础知识应用
转行学开发,代码100天——2018-04-14 JavaScript中DOM操作基础知识即对DOM元素进行增删改操作.主要表现与HTML元素的操作,以及对CSS样式的操作.其主要应用知识如下图: 通 ...
- 拒绝从入门到放弃_《Python 核心编程 (第二版)》必读目录
目录 目录 关于这本书 必看知识点 最后 关于这本书 <Python 核心编程 (第二版)>是一本 Python 编程的入门书,分为 Python 核心(其实并不核心,应该叫基础) 和 高 ...
- SqlServer 索引和视图
Ø 索引 1. 什么是索引 索引就是数据表中数据和相应的存储位置的列表,利用索引可以提高在表或视图中的查找数据的速度. 2. 索引分类 数据库中索引主要分为两类:聚集索引和非聚集索引.SQL Serv ...
- vim-tabe多标签切换
vim-tabe多标签切换 本文转载自https://www.cnblogs.com/liqiu/archive/2013/03/26/2981949.html 1.新建标签页 使用:tabe命令和文 ...
- debain8 安装mysql8
一.下载apt源 https://dev.mysql.com/downloads/repo/apt/ 二.更新apt sudo apt-get update 三.安装mysql sudo apt-ge ...
- MySQL-第N篇杂记
1.数据的导入导出 2.查询结果的重定向 3.ON DUPLICATE KEY UPDATE对于指定的主键或者唯一键,insert时发生冲突则进行update操作. 4.解决MySQL中问乱码问题,分 ...