模块化在Node中是一个规范,定义一些模块的相关的规则,从代码角度上来说,方便做区别,如果不使用模块化,写在js文件中不利于后期维护和扩展,从代码的层面上就把相关的功能脱离出来,所以模块化从从代码的角度触发,分析项目,把项目中一些功能类型的代码,单独抽离为一个个的模块,那么为了保证大家以相同的方式去封装模块,于是我们就创造了CommentJS规范
在我们项目中,如果需要是实现相同的功能,就不需要再重写,所以模块化从一定程度上提高我们的开发效率,有一些相关模块,直接调用就可以了,方便项目开发,和后期的维护与扩展
把页面中样式差不多的东西抽为单独的小组件,把需要经常复用的东西封装为一个单独的,今后需要用的时候直接拿就可以,不用再重写,从ui的角度触发去考虑问题,把页面中代码结构类似的区域抽离出来,封装成一个单独的小组件 ;前端的组件化,方便UI组件的重用;
随着项目规模的发展,我们手中的组件会越来越多,我们今后一个页面的ui,几乎都可以从手中拿现成的组件拼接出来,方便项目的开发和维护
Vue.extend()
得到组件的构造函数 var com1 = Vue.extend({
template: '这是创建的第一个全局组件
'
// template 属性,表示这个组件的 UI 代码解构
})
vue.component('组件的名称',组件的构造函数)
来注册全局组件 Vue.component('mycom1', com1)
//com1就是组件的构造函数
注意:
组件的名称如果是驼峰命名,那么引入的时候表名称得加连字符-
1.如果 Vue.component(‘myCom1’,‘com1’)
对应的组件标签是
2. 如果是Vue.component(‘myCom1Test’,‘com1’)
对应组件标签为:
3. 如果Vue.component(‘my-com1’,‘com1’)
对应组件标签为:
<div id="app">
<mycom1>mycom1>
div>
来吧展示:
vue.component('组件的名称','组件对象')
// Vue.component 的第二个参数,既接收 一个 组件的构造函数, 同时,也接受 一个对象
Vue.component('mycom2', {
template:'这是直接使用 Vue.component 创建出来的组件
'
})
<div id="app">
<mycom2>mycom2>
div>
来吧展示:
注意:
1.template 属性中,不能单独放一段文本,必须用标签包裹起来;
2. 如果在 template 属性中,想要放多个元素了,那么,在这些元素外,必须有唯一的一个根元素进行包裹;
Vue.component('mycom2', {
template:'嘿嘿嘿嘿嘿
这是直接使用 Vue.component 创建出来的组件
哈哈哈哈
'
})
template
添加一个id选择器Vue.component('mycom3', {
template: '#tpl'
})
<div id="app">
<mycom3>mycom3>
div>
<template id="tpl">
<h2>这是创建全局组件的第三种方式h2>
template>
注意:
template标签中里面也必须有唯一的一个根元素进行包裹
也就是如果没有根元素包裹,那么下面代码是执行不出来了会报错
<template id="tmpl">
<h2>这是创建全局组件的第三种方式h2>
<p>哟哟哟哟哟哟p>
template>
正确写法:
<template id="tmpl">
<div>
<h2>这是创建全局组件的第三中方式h2>
<p>嘿嘿嘿嘿嘿嘿嘿嘿嘿嘿p>
div>
template>
<div id="app">
<mycom3>mycom3>
div>
<div id="app2">
<mycom3>mycom3>
div>
<template id="tmpl">
<h2>这是创建全局组件的第三中方式h2>
template>
<script>
Vue.component('mycom3', {
template: '#tmpl'
})
var vm = new Vue({
el: '#app',
});
var vm2 = new Vue({
el: '#app2',
});
script>
创建一个私有组件
<div id="app">
<mycom4>mycom4>
div>
var vm = new Vue({
el: '#app',
data: {
},
methods: {
},
components: {
// 定义实例中私有组件的 组件的名称 和组件的 解构
'mycom4': {
template: '这是定义的私有组件
'
}
}
});
创建多个私有组件:
<div id="app">
<mycom4>mycom4>
<mycom5>mycom5>
div>
components:{
mycom4:{
template:'这是我定义的私有组件1
'
},
mycom5:{
template:'这是我定义的私有组件2
'
}
}
Vue.component('mycom', {
template: '这是自定义的全局组件 ------ {
{ msg }}
',
data: function () {
//
// 在 组件中,可以有自己的私有数据
// 但是,组件的 data 必须是一个 function
// 并且内部 return 一个 数据对象
return {
msg: '我是组件的内部data'
}
},
methods: {
// 尝试定义组件的私有方法
show() {
// console.log('出发了组件的私有show方法!')
alert('我是组件内部的方法')
}
}
})
思考:
为什么要把 组件中的 data 定义为一个function呢?
因为这样做的话,每当我们在页面上引用一次组件,必然会先调用 这个 data function,
从而得到一个当前组件私有的 数据对象;
v-if
与 v-else
实现组件的切换<div id="app">
<input type="button" value="显示登录" @click="flag=true"/>
<input type="button" value="显示注册" @click="flag=false"/>
<login v-if="flag">login>
<res v-else="flag">res>
div>
<script>
Vue.component('login', {
template: '登录
'
})
Vue.component('res', {
template: '注册
'
})
// 创建 Vue 实例,得到 ViewModel
var vm = new Vue({
el: '#app',
data:{
flag:false
},
methods:{
}
})
script>
<div id="app">
<component :is="'com1'">component>
<component :is="'com3'">component>
div>
Vue.component('com1', {
template: '我是第1个组件
'
})
Vue.component('com2', {
template: '我是第2个组件
'
})
Vue.component('com3', {
template: '我是第3个组件
'
})
Vue.component('com4', {
template: '我是第4个组件
'
})
<div id="app">
<a href="#" @click="comname='com1'">显示组件1a>
<a href="#" @click="comname='com2'">显示组件2a>
<a href="#" @click="comname='com3'">显示组件3a>
<a href="#" @click="comname='com4'">显示组件4a>
<component :is="comname">component>
div>
var vm = new Vue({
el: '#app',
data:{
comname:'com1'
},
//当vue解析文件到component标签时,如果有:is属性就会解析后面的字符串"comname"
//然后去data中寻找这个变量
//comname:'com1'
//正好是一个字符串的变量的名称,就会显示名称叫com1的组件
methods:{
}
})
<transition>
<component :is="comname">component>
transition>
<style>
.v-enter,
.v-leave-to{
opacity:0;
transform: translate(100px);
}
.v-enter-active,
.v-leave-active{
transition: all 0.4s ease;
}
style>
如上图效果显示,有标准流的影响,所以要脱离标准流的影响,让离开的组件脱离标准流
<style>
.....
.v-enter-active,
.v-leave-active{
transition: all 0.4s ease;
position: absolute;
}
style>
如图动画效果是先进入再离开,如果想要实现先离开再进入,则只需要在transition
中添加mode="out-in"
<transition mode="out-in"> -
<component :is="comname">component>
transition>
<style>
.v-enter {
/* 即将进入时候的坐标 */
opacity: 0;
transform: translateX(100px);
}
.v-leave-to {
/* 离开时候,最终到达的位置 */
opacity: 0;
transform: translateX(-100px);
}
style>
v-bind
绑定到子组件身上 <com :sonmsg="pmsg">com>
props
来接收一下 props: ['sonmsg']
props
的时候,一定要和父组件中传递过来的自定义属性名称保持一致 template: '我是子组件-----{
{sonmsg}}
',
具体代码如下:
<body>
<div id="app">
<com :sonmsg="pmsg">com>
div>
<script>
var vm = new Vue({
el: '#app',
data: {
pmsg:'我是父组件中的数据'
},
methods: {
},
components: {
// 定义私有组件
'com': {
// 在Vue中,默认,子组件无法直接获取父组件中的数据
template: '我是子组件-----{
{sonmsg}}
',
props: ['sonmsg']
// 在Vue中,只有 props 是数组,其它带 s 后缀的属性都是 对象
}
}
});
script>
body>
v-bind
绑定到子组件身上 <com1 :msgobj123="msgObj">com1>
props
来接收一下 props: ['msgobj123']
props
的时候,一定要和父组件中传递过来的自定义属性名称保持一致 template: '后面传递的是父组件中对象 ---- {
{ JSON.stringify(msgobj123) }}
'
template: '<h3>哈哈 {
{ JSON.stringify(msgobj) }}h3>',
具体代码如下:
<body>
<div id="app">
<com1 :msgobj123="msgObj">com1>
div>
<script>
var vm = new Vue({
el: '#app',
data: {
msgObj: {
id:1,
name:'千夏Chinatsu',
age:18
}
},
methods: {
},
components: {
'com1': {
template: '后面传递的是父组件中对象 ---- {
{ JSON.stringify(msgobj123) }}
',
props: ['msgobj123']
}
}
});
script>
body>
v-on
绑定事件到子组件身上<com v-on:func="show()">com>
$emit()
来接收一下 this.$emit('func')
$emit()
中,一定要和父组件中传递过来的方法名称保持一致具体代码:
<body>
<div id="app">
<com v-on:func="show()">com>
div>
<script>
var vm = new Vue({
el:'#app',
data:{
},
methods:{
show(){
console.log('触发了父组件中的show()方法')
}
},
components: {
'com': {
template: '',
methods:{
btnClick(){
// console.log('hhhh')
this.$emit('func')
}
}
}
}
})
script>
body>
总结:
1.如果要向子组件传递 data 中的数据,则 使用 属性绑定的形式v-bind:
2. 如果要向子组件传递 methods 中的 方法,则 使用 事件绑定的形式v-on:
<body>
<div id="app">
<com v-on:func="show">com>
div>
<script>
var vm = new Vue({
el:'#app',
data:{
},
methods:{
show(arg){
console.log('触发了父组件中的show()方法' + arg)
// '--------'
}
},
components: {
'com': {
template: '',
data:function(){
return{
sonmsg:'这是子组件中的数据'
}
},
methods:{
btnClick(){
this.$emit('func','嘿嘿嘿嘿嘿')
}
}
}
}
})
script>
body>
methods:{
show(arg){
console.log('触发了父组件中的show()方法' +'--------'+ arg)
// '--------'
}
},
components: {
'com': {
template: '',
data:function(){
return{
sonmsg:'这是子组件中的数据'
}
},
methods:{
btnClick(){
// console.log('hhhh')
this.$emit('func','嘿嘿嘿嘿嘿')
// this.$emit('func',this.sonmsg)
}
}
}
}
methods: {
show(arg) {
// console.log('触发了父组件中的show()方法' +'--------'+ arg)
// 把子组件传递过来的数据,保存到 父组件的 data 中
this.msgFormSon = arg
console.log(this.msgFormSon)
}
},
总结:
子组件向父组件传值,本质上,还是调用了父组件传递过来的方法
只不过,子组件在调用的时候,把 数据 当作参数,传给这个方法了;
<body>
<div id="app">
<cmt-box @func="addNewCmt">cmt-box>
<ul>
<cmt-item v-for="(item, i) in list" :item="item" :key="i">cmt-item>
ul>
div>
<script>
Vue.component('cmt-item', {
template: `
评论人:{
{ item.name }}
评论内容:{
{ item.content }}
`,
props: ['item']
})
Vue.component('cmt-box', {
template: `
`,
data: function () {
return {
name: '',
content: ''
}
},
methods: {
postComment() {
// 发表评论
// console.log('ok')
const cmt = {
name: this.name, content: this.content }
// 子组件中,调用父组件传递过来的方法,然后可以把 子组件的数据,当作参数,传递给父组件的方法去使用
this.$emit('func', cmt)
this.name = this.content = ''
// console.log(cmt)
}
}
})
var vm = new Vue({
el: '#app',
data: {
list: [
{
name: 'zs', content: '沙发' },
{
name: 'ls', content: '板凳' },
{
name: 'qqq', content: '凉席' },
{
name: 'eee', content: '砖头' }
]
},
methods: {
addNewCmt(cmt) {
// 添加新评论
// console.log(cmt)
this.list.push(cmt)
}
}
});
script>
body>
<body>
<div id="app">
<input value="按钮" type="button" @click="show()"/>
<h2 id="myh2" ref="hhh">{
{msg}}h2>
div>
<script>
var vm = new Vue({
el:'#app',
data:{
msg:'嘿嘿嘿嘿嘿'
},
methods:{
show(){
//原生想要获取h2中的数据的方法
// var res = document.getElementById('myh2').innerHTML
//console.log(res)
console.log(this)
console.log(this.$refs.hhh)
console.log(this.$refs.hhh.innerHTML)
}
}
})
script>
body>
在h2标签中没有加入ref
属性的打印console.log(this)
结果
在h2标签加入ref
属性的打印console.log(this)
结果
所以可以通过ref
可以很方便的来获取元素
console.log(this)
console.log(this.$refs.hhh)
console.log(this.$refs.hhh.innerHTML)
所以可以根据msg去修改组件内部的数据或者调用子组件中的方法
<body>
<div id="app">
<input value="按钮" type="button" @click="getCom()" />
<com1 ref="xxxxx">com1>
div>
<script>
Vue.component('com1', {
template:'这是一个小组件---{
{msg}}
',
data:function () {
return {
msg:'这是组件内部数据'
}
},
methods:{
show(){
console.log('子组件中的方法被调用了')
}
}
})
var vm = new Vue({
el:'#app',
data:{
msg:'这是父组件的数据'
},
methods:{
getCom(){
// console.log(this)
this.$refs.xxxxx.msg = '组件内部数据被修改了'
this.$refs.xxxxx.show()
}
}
})
//页面上可以为很多元素创建ref的引用
script>
body>
data
在组件中,要被定义成一个function,并且要返回一个对象props
在组件中,要被定义成数组,其中,数组的值都是字符串名,表示从父组件传递过来的数据props
中的数据,不要直接拿来修改,如果想要修改,必须在data上重新定义一个属性,然后把属性的值从this.props
直接拿过来data
上的数据,都是组件自己私有的,数据都是可读可写的props
都是外界传递过来的数据,数据只能读取,不能重新写入