04、手把手教Vue--props
PS:转载请注明出处
作者: TigerChain
地址: https://www.jianshu.com/p/87ff57037d9c
本文出自 TigerChain 简书 手把手教 Vue 系列
本节大纲
![](https://img.haomeiwen.com/i1586207/dbfaf88a938ec433.png)
教程简介
- 1、阅读对象
本篇教程适合新手阅读,老手直接略过 - 2、教程难度
初级,本人水平有限,文章内容难免会出现问题,如果有问题欢迎指出,谢谢 - 3、Demo 地址:https://github.com/githubchen001/vue-lesson 请看 02、vue组件 组件这一节
正文
一、v-bind
在说 props 之前,我们先说说 v-bind 这个指令
1、什么是 v-bind?
v-bind 用来动态的绑定一个或多个属性,或一个组件的 prop ,比如绑定图片地址、标签的样式等,v-bind 的缩写是 :
2、v-bind 的用法
比如,我们给 img 一个图片资源地址
<img v-bind:src="imageSrc"/>
再比如,我给一个 div 设置 css 样式,如下
<div v-bind:class="{divstyle:isShowStyle}"></div>
<style>
.divstyle {
background-color: red;
}
</style>
<script>
var vm = new Vue({
el:"#root",
data:{
// 如果 isShowStyle 为 true 的话,那么
// v-bind:class="{divstyle:isShowStyle}" 表示此 div 的 class 就是 divstyle
isShowStyle:true
}
})
</script>
等等,拿官方的举例来说,v-bind 可以绑定属性「以数据驱动」,在绑定 class 或 style「内联样式」 的时候支持数据或对象,以下是官方举例基本上把 v-bind 的使用场景介绍完了,html 的属性只能使用 v-bind 来绑定「除非你使用原生写法,不使用 v-bind」
<!-- 绑定一个属性 -->
<img v-bind:src="imageSrc">
<!-- 缩写 -->
<img :src="imageSrc">
<!-- 内联字符串拼接 -->
<img :src="'/path/to/images/' + fileName">
<!-- class 绑定 -->
<div :class="{ red: isRed }"></div>
<div :class="[classA, classB]"></div>
<div :class="[classA, { classB: isB, classC: isC }]">
<!-- style 绑定 -->
<div :style="{ fontSize: size + 'px' }"></div>
<div :style="[styleObjectA, styleObjectB]"></div>
<!-- 绑定一个有属性的对象 -->
<div v-bind="{ id: someProp, 'other-attr': otherProp }"></div>
<!-- 通过 prop 修饰符绑定 DOM 属性 -->
<div v-bind:text-content.prop="text"></div>
<!-- prop 绑定。“prop”必须在 my-component 中声明。-->
<my-component :prop="someThing"></my-component>
<!-- 通过 $props 将父组件的 props 一起传给子组件 -->
<child-component v-bind="$props"></child-component>
<!-- XLink -->
<svg><a :xlink:special="foo"></a></svg>
3、写个 demo 感受一下吧,这里直接在 script 引入 vue.js 来写
- 1、核心代码如下:
<body>
<div id="container">
<!-- 第一种写法 其中 img 是宽度为 35 的 style 样式-->
<img v-bind:src="imgSrc" v-bind:class="{'img':show}" >
<!-- 第二种写法 -->
<img v-bind:src="'./imgs/logo.png'" v-bind:style="imgStyle" >
<p v-bind:style="{color:'red'}">{{msg}}</p>
<!-- 标签的属性的都可以使用 v-bind 替换 -->
<input v-bind:type="'text'" v-bind:placeholder="'输入内容'" v-model="clickBtnText"><!-- :value="''" 和 v-model 同时出现会报错-->
{{clickBtnText}} <br/>
<!-- 这里是行内样式 -->
<input type="button" value="测试" v-bind:style="{'margin-top':'10px'}">
</div>
<script>
// 定义一个样式
var imgStyle = {
height: '40px',
width: '40px'
}
var vm = new Vue({
el: '#container',
data: {
msg:"123",
imgStyle:imgStyle,
imgSrc:'./imgs/logo.png',
show:true,
clickBtnText:''
}
})
</script>
</body>
- 2、查看结果
![](https://img.haomeiwen.com/i1586207/3bea0e081789656c.png)
我们看到我们使用 v-bind 设置图片,设置样式「行内样式和行外样式」,并且代替 html 原有的属性等,并且成功显示,调试窗口也没有报错
二、props 属性
Vue 和 React 一样,是使用 props「单向数据流」 来传递数据的「父组件的数据传递给后代组件」,props 在本组件中是不能修改的「和 React 也是一毛一样」
1、一般格式
我们知道组件有四种格式,不管那种格式 props 用法都是相同的,这里以全局组件为例子
Vue.component('customcomponent',{
// 定义接收的 props 等待父组件传递
props:['message'],
template: '<span>{{message}}</span>',
... 数据和方法等省略
})
2、直接写代码感受一下
在以下 demo 中,我们使用 props 来传递字符串、对象、样式来感受一下 props
- 1、直接在上面的代码基础上修改,添加以下代码
<hr>
<h4>以下是 props 例子</h4>
<div id="app2">
<!-- 如果要使用 props 来传递对象,就要使用 v-bind -->
<mycomponent message="你好" :mydata="{username:'tigerchain',age:28}" name-style="color:red"></mycomponent>
</div>
<script>
// 定义一个组件
var myComponent = Vue.extend({
// 定义 props
props: {
message:"",
mydata:{},
//样式 ,如果这里使用驼峰标识 ,则在标签中使用就要使用 name-style 传递
nameStyle:{}
},
template: '<div>{{ message }} <div> <span v-bind:style="nameStyle">{{ mydata.username}}</span></div> </div>'
})
// 全局注册组件 组件的别名要是小写,否则会报错
Vue.component('mycomponent', myComponent)
var vm2 = new Vue({
el:'#app2',
})
</script>
为了便于观察,我们重新定义了一个 id 为 app2 的 div 和一个新的 Vue 实例「vm2」 ,我们定义一个组件并且添加如下的 props
![](https://img.haomeiwen.com/i1586207/c7afc33bcba6aab3.png)
在使用组件的时候就可以传递数据了
![](https://img.haomeiwen.com/i1586207/409c7f8a6c8564d0.png)
- 2、运行查看结果
![](https://img.haomeiwen.com/i1586207/662e1b5a3effd714.png)
我们看到,传递过来的数据完美的接收到并显示出来了,在这里注意以几下几点
- 如果 props 中声明的是数据是驼峰标识,那么传值的时候就要使用 - 标识
比如 props 中的数据是 myData 那么在组件中传值时就要使用 my-data="" ,如果没有使用驼峰那不牵扯
- 在组件中使用 props 传值的时候默认传的是字符串
如果想要传值「比如对象,数据等」那么就要使用 v-bind="" 来传值,上面的 message 和 mydata 就显示了这两种方式
-
props 中就定义一些默认的值,不能直接修改 props,只能间接的通过 data 来修改「在 data 里面定义数据,值就是 props ,这一点 React 是一样的」,其实 Vue 中的 data 就和 React 中的 state 是一样的
-
props 中的值,我们在 Vue 实例中可以使用 this.props 的值来访问「和仿问 data 是一样的」
三、 props 验证
想要写一个有“良心”的组件,指定 props 的验证规则非常有必要,比如我们在 props 中定义传递过来的 name 必须是字符串否则就发出警告「这对使用插件的人来说是非常友好的」
1、验证规则
直接引用官方的验证规则吧
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 value > 10
}
}
}
其中 type 有以下几种类型:
- String:字符串
- Number:数字
- Boolean: boolean 类型
- Function: props 能传递方法,这样的话,组件方法的回调是非常 easy 的
- Object: 对象
- Array: 数组
- Symbol: 原始类型
2、写段代码看一下吧,我们在原有代码基础上添加如下代码「红框所示」
![](https://img.haomeiwen.com/i1586207/8f5f7c95b59cca8c.png)
在这里我们就可以传递方法「实现了方法的回调」,并且规定了 age 只能传递数字,然后再看 vm2 实例中添加方法,如下所示
![](https://img.haomeiwen.com/i1586207/a2ac2cef844ce2c7.png)
那么我们的 show 方法是如何来的呢,细心的朋友会发现,我们在组件中调用了 props 中声明的方法,这个 show 就是我们在使用组件的时候伟递过来的,我们看看代码
<div id="app2">
<!-- 如果要使用 props 来传递对象,就要使用 v-bind -->
<mycomponent
message="你好"
:mydata="{username:'tigerchain',age:28}"
name-style="color:red"
age="100"
:clickme="show()"
/>
</div>
由于 clickme 是 props 中规定的必须是方法,所以这里传递一个方法过去,在 vue 实例中直接实现这个方法就 ok 了「这样我们就可以在多组件开发中使用 props 来传递方法来达到方法回调的作用」,并且我们为了验证 age 故意传了一个字符串,我们在 chrome 调试容器能看到报错了,说 age 要传一个数字「这里就不截图了,大家可以自行实验」,上面的例子虽然把方法回调回来了,但是这在实际开发中还是有缺陷的,回调回来的方法没有带个参数「这肯定不能满足常用的开发呀」,我们修改一下上面的代码来实现回调传参
修改一:props 传递方法处
![](https://img.haomeiwen.com/i1586207/ab83889a025f20bf.png)
修改二:调用 props 传参方法
![](https://img.haomeiwen.com/i1586207/9cef4b9576a9d345.png)
修改三:回调方法实现
![](https://img.haomeiwen.com/i1586207/04c8e8b4c5b9efa4.png)
经过以上三处修改,我们就使用 props 来回调子组件的方法「并且带参数」完美实现了
3、显示结果如下
![](https://img.haomeiwen.com/i1586207/d0cb6ca02a6340c0.gif)
我们可以看到,使用 props 传递方法,并且把子组件中的"你好"当作方法参数回传回来
以上我们就把 props 基本上介绍完了,细心的朋友可以发现,我们在 props 中传递方法的时候,未修改之前的方法是带括号的,后面的方法没有带括号,那么这有什么区别呢?再给大家赠送一些 Vue 中的方法的一些知识
三、Vue 中的方法
Vue 中的方法可以定义在 methods 中「这不废话吗」,也可以定义在 data 中,针对于无参数方法可以带括号,也可以不带括号来说明「有参数方法则必须带括号」,那么这些到底有什么区别呢?我们实际写一个例子来总结一下吧
- 1、新建一个 vue-method.html 文件「并引入 vue.js」
核心代码如下
<h3>Vue 中的方法</h3>
<div id="container">
<button v-bind:class="{bg:isShowbgStyle}" @click="testDataFun">在 data 调用 testDataFun 方法</button>
<button v-bind:class="{bg:isShowbgStyle}" @click="testDataFun()">在 data 调用 testDataFun() 方法</button>
<button v-bind:class="{bg:isShowbgStyle}" @click="testInMethodsFun">在 methods 调用 testInMethodsFun 方法</button>
<button v-bind:class="{bg:isShowbgStyle}" @click="testInMethodsFun()">在 data 调用 testInMethodsFun() 方法</button>
</div>
<script>
var vm = new Vue({
el:"#container",
data:{
isShowbgStyle:true,
testDataFun(){
console.log(this,arguments)
}
},
methods: {
testInMethodsFun() {
console.log(this,arguments)
}
}
})
</script>
- 运行查看结果
![](https://img.haomeiwen.com/i1586207/221a3107b3a0ec94.png)
通过 Demo 我们清楚的知道以下结论
- 1、在 data 或是 methods 中调用无参方法,那么默认会把 Event 对象传递进去,比如上面的 1、3 方法
- 2、如果想让 this 指向 Vue 实例化的对象,如果在 data 方法调用就必须加上括号
- 3、在 Vue methods 中的方法不管加参数还是不加参数「带括号或是不带括号」,this 都指向 Vue 的实例化对象
- 4、综上所术,我们把 Vue 中的方法都放在 methods 中是最好的选择,如果想要想绑定事件,那么不加括号是最好的选择。
有的朋友可能会问了,那我想在 data/methods 中声明方法,既绑定事件又传参数如何搞呢?可以做到吗,肯定可以,我们添加测试代码如下
<button v-bind:class="{bg:isShowbgStyle}" @click="testInMethodsFun('msg',$event)">在 data 调用 testInMethodsFun(参数,事件) 方法</button>
我们可以使用 $event 显示的把原生事件传递过去,查看一下输出结果
Vue$3 {_uid: 0, _isVue: true, $options: {…}, _renderProxy: Proxy, _self: Vue$3, …}
Arguments(2) ["msg", MouseEvent, callee: ƒ, Symbol(Symbol.iterator): ƒ]
怎么样,Arguments 参数中第一个是方法参数,第二个就是传递过来的事件,在 data 方法是同理
到此为止,我们把 vue props 就说完了,请大家动手写写感受一下
四、回顾一下
-
v-bind 是用来绑定属性的和 props 传递对象或值使用的「props 默认传递的是字符串,如果想要传值、对象,那么就要使用 v-bind」
-
如果 props 中声明的是数据是驼峰标识,那么传值的时候就要使用 - 标识
如:props 中的数据是 myData 那么在组件中传值时就要使用 my-data="" ,如果没有使用驼峰那不牵扯
-
props 用来定义一些默认值,我们不能直接修改 props 的值,只能通过 data 来间接修改
-
要写一个"合格"的 vue 组件,那么 props 最好加上验证
-
props 也可以用来传递方法,达到父组件调用子组件方法并且回调的目标
-
vue 中的方法建议写在 methods 中,无参方法调用时就不要加括号
怎么样,说了这么多就这么几个知识点,再次提示一定要动手写一写「感受一下」
点赞富一生,转发富五代,更多文章请关注我的微信公号来查阅「手机扫描即可关注」
公众号:TigerChain