Vue组件
趁team leader的安排,在团队内部进行一次技术分享的机会。整理下这半年用到的比较多的Vue内容,至今Vue的源码还未细心研读过,从开发使用层面上开两个专题:Vue组件和Vue Router。1.工程搭建打开pycharm后,file–&am
趁team leader的安排,在团队内部进行一次技术分享的机会。整理下这半年用的比较多的Vue.js内容,从开发使用层面上做一个简单的总结和入门,开两个专题:Vue组件和Vue Router。
1.工程搭建
打开pycharm后,file–>new–>project.按照下图一路next到底。
2.组件总述
个人理解,Vue中的组件技术类似于后端开发中常用的一些工具类或方法,如果一个方法或功能在多个地方要用到,我们就需要将其进行抽离出来,在Vue中,组件就是一种很好的复用一个功能的手段。比如页面上的按钮、输入框等都可以以组件的形态存在,以供多个页面去复用使用。
下面,本文档将以组件的使用流程为主线进行简单的梳理和总结。
- 创建组件 (第四部分)
- 注册组件 (第三部分)
- 调用组件 (穿插在第三四部分)
3.注册组件
创建组件放在后面讲,先看下注册组件。首先假设存在一个已经开发好的组件M(可能是个人开发的,也可能是别人开发的,亦可能是通过npm install安装的第三方库的组件),在我们的项目中如何去注册。
组件注册主要分**全局注册和局部注册**。
全局组件通常使用 Vue.component(tagName, {options})的格式注册;
局部组件则在实例中的components中注册。
注意:
要确保在初始化根实例之前注册了组件,即:先注册组件,再初始化Vue实例;
建议将组件提取出来放在单独js文件中,按需引用。
4.创建组件
如果页面A上使用某个组件M,统一称呼的口径,全文约束调用方页面A为父组件,被调用方组件M称之为子组件。
组件使用和开发的核心就是父子组件的数据传递(通信)问题,按照数据传递方向可分为三类:
- 父组件(调用方)与子组件(被调用方)的数据传递:props
- 子组件向父组件传递数据:$emit()
- 子组件与子组件(兄弟组件)数据传递:vuex
4.1 父–>子组件 props:
<template>
<div>
<p>我是子组件,父组件通过props传递过来的值是</p>
{{postTitle}}
</div>
</template>
<script>
export default {
name: 'parent-child',
// props: ['postTitle'],
props: {
'postTitle': String
}
}
</script>
<style scoped>
</style>
注意:
1.子组件中的驼峰命名的 prop 名在父组件赋值的时候需要使用其等价的短横线分隔命名;
2.props如果不加类型校验则是一个数组;若加上类型校验则是一个对象。
4.2 子–>父组件 :$emit()
props里面的属性字段值是单向的,只能是父组件传递给子组件,如果在子组件对其进行修改父组件是无感知的。子组件如果想跟父组件进行反馈,通过在子组件利用emit()定义一个事件回调函数。
<template>
<div>
<button v-on:click="btnClickEvent">
子组件的按钮
</button>
</div>
</template>
<script>
export default {
name: 'child-parent',
methods: {
// 在子组件内部通过emit定义btn-click事件,在父组件中去监听btn-click事件并实现对其的响应
btnClickEvent: function () {
this.$emit('btn-click')
}
}
}
</script>
<style scoped>
</style>
------------------- 分割线: 以下是调用上面子组件的父组件 ---------------------
<!-- 子组件通过emit注册的事件回调父组件的事件响应函数 -->
<template>
<div>
<!-- 监听子组件预定义的btn-click事件 -->
<child-parent @btn-click="callback_fn"></child-parent>
</div>
</template>
<script>
import childParent from '@/components/child-parent'
export default {
name: 'emit',
methods: {
callback_fn () {
alert('父组件预定义的供子组件回调的函数 ==> (由子组件触发)')
}
},
components: {
childParent
}
}
</script>
<style scoped>
</style>
小结:Props 向下传递数据,事件向上传递数据。
在标准组件和自定义组件上分别使用v-model
1.在标准组件上使用v-model
<!-- 在标准组件input上使用v-model实现变量的双向绑定 -->
<div id="app">
<input :value="name" @input="name = $event.target.value" />
<input v-model="name" />
</div>
上面示例代码中的两行input标签效果是一样的,在标准组件上使用v-model 节约了不少代码,最重要的是可以少定义一个事件处理函数,所以 v-model 实际干的事包括:
- 使用 v-bind(即 :)单向绑定一个属性(示例::value=“name”)
- 绑定 input 事件(即 @input)到一个事件处理函数(示例:@input=“name = $event.target.value”
2.在自定义组件上使用v-model
如同在标准组件上使用v-model一样,如果在自定义的子组件上利用v-model绑定某个值,就相当于子组件内部实现上的props里面有个value属性,同时还注册一个input事件,如下所示:
<custom-input
v-bind:value="searchText"
v-on:input="searchText = $event"
></custom-input>
Vue.component('custom-input', {
props: ['value'],
template:
<input
v-bind:value="value"
v-on:input="$emit('input', $event.target.value)"
>
})
再看下面代码所示为父组件的一个例子,在该父组件中引用了子组件model-input,其中
<model-input :value="msg" @input="(res) => {this.msg = res}"></model-input>
这一行代码就说明在model-input子组件中必须得有一个接收value值的props和利用$emit注册一个input事件。
<!-- 父组件上使用v-model,子组件上使用model -->
<template>
<div>
<!-- 在input标签上时 v-model == value + input -->
<model-input :value="msg"></model-input>
<model-input :value="msg" @input="(res) => {this.msg = res}"></model-input>
<model-input v-model="msg"></model-input>
<span>父组件:{{msg}}</span>
<!-- model选项可以指定当前的事件类型和传入的props, 因此可以解决v-model默认只能是value + input -->
<model-conponent value="type1" :checked="checked"></model-conponent>
<model-conponent value="type2" :checked="checked" @change="change"></model-conponent>
<model-conponent value="type3" v-model="checked"></model-conponent>
<p>父组件中的当前选中状态: {{this.checked}}</p>
</div>
</template>
<script>
import modelConponent from '@/components/v-model'
import modelInput from '@/components/model-input'
export default {
name: 'vModel',
data () {
return {
msg: 'byteDance',
checked: false
}
},
methods: {
change (value) {
console.log('父组件事件回调响应函数 ==>', value)
this.checked = value
}
},
components: {
modelConponent,
modelInput
}
}
</script>
---------------------------分割线,以下是子组件的代码----------------------------
<template>
<div>
<input ref="input" type="text" :value="value" @input="input"/>
</div>
</template>
<script>
export default {
name: 'modelInput',
// 利用model强制修改默认input事件为input-fn事件
// model: {
// prop: 'value',
// event: 'input-fn'
// },
props: {
value: String
},
methods: {
input () {
console.log('子组件 == ', event.target.value)
this.$emit('input', event.target.value)
}
}
}
</script>
可以在子组件中用model对v-model默认的value属性和input事件进行修改,上面示例代码中,子组件<model-conponent value="type1" :checked="checked"></model-conponent>
就是利用model改变默认的value和input为checked和change。
子组件上使用model的示例
4.3 子组件与子组件(兄弟组件)数据传递:vuex
个人理解,把各组件间用到的共享数据,抽离出到一个全局共享变量中,交由vuex进行集中管理。
1.将vuex引入到当前工程:
- 安装:npm install vuex --save
- 定义Vuex对象:在src/store/store.js文件(若无则新建)中定义一个new Vuex.Store对象
- 在src/main.js中的Vue实例中引入vuex store
2.引入到工程中后,在工程组件中使用的步骤,详见store.js
除了以上内容外,下面在总结下组件的两个高级特性:slot和动态组件
5.slot
slot(插槽)类似于props,也是父组件到子组件传递数据的一种方式,区别于props的子组件标签内属性数据传递,而slot是子组件标签之间的数据传递,可以传递像dom之类的template内容,也包括html和一些其他组件。
上述截图所示,如果子组件slot-child内部没有<slot></slot>
则父组件的
<span>我是从父组件传递到子组件的数据</span>
是无法展示的。以下是子组件代码:
<template>
<div>
子组件Slot-Child:
<br/>
<button @click="update"> {{btnName}} </button>
<br/>
<!-- 如果注释掉下面的slot标签,则无法接受父组件内容 -->
<slot></slot>
</div>
</template>
<script>
export default {
name: 'slot-child',
props: {
btnName: String,
default: '子组件按钮'
},
methods: {
update () {
this.$emit('update', '子组件回调函数的入参')
}
}
}
</script>
6.动态组件
动态组件:通过使用 <component>
标签,让多个组件可以使用同一个挂载点,并动态切换,<component :is="currentTabComponent" class="tab"></component>
根据 v-bind:is=“组件名” 中的组件名去自动匹配组件,显示相应的组件内容。
附录
-
文章对应的项目源码
-
后续todo:
1.localstorage
2.vuex-persistedstate
3.vue-codemirror
4.函数内部函数的局部this -
Vue学习资料
Webpack原理剖析:https://wx.kaikeba.com/presaledata/5?channel=0ebwxz
vue-router前端路由原理剖析:https://wx.kaikeba.com/presaledata/4?channel=pwvrgj
Vue源码解析:https://wx.kaikeba.com/presaledata/21?channel=fiqp7b
react组件化:https://wx.kaikeba.com/presaledata/22?channel=kw2iey
react原理剖析:https://wx.kaikeba.com/presaledata/23?channel=lfdb15
Koa2源码解读:https://wx.kaikeba.com/presaledata/3?channel=p1ina4
如何通过数据劫持实现vue框架:https://wx.kaikeba.com/presaledata/6?channel=3a2mxj
Web全栈Vue资料:https://pan.baidu.com/s/1e4rQqDf3Pn7ZRD276bsTnQ
提取码:cmws
更多推荐
所有评论(0)