一、什么是组件
组件的出现,就是为了拆分Vue实例的代码量的,能够让我们以不同的组件,来划分不同的功能模块,将来我们需要什么样的功能,就可以去调用对应的组件即可; 组件化和模块化的不同:
-
模块化: 是从代码逻辑的角度进行划分的;方便代码分层开发,保证每个功能模块的职能单一;
-
组件化: 是从UI界面的角度进行划分的;前端的组件化,方便UI组件的重用
二、组件的创建
- 创建方式1
var test_cx = Vue.extend({
template: '<h1>创建组件</h1>'
});
Vue.component('testcx', test_cx); //其中testXcx是组件名称
- 方式1的简略写法
Vue.component('test-cx', Vue.extend({
template: '<h2>创建组件</h2>'
}));
- 方式2
Vue.component('test-cx', {
template: '<h3>这是直接使用 Vue.component 创建出来的组件</h3>'
})
- 方式3
<body>
<div id="app">
<test-cx></test-cx>
</div>
<template id="test">
<h4>创建组件</h4>
</template>
<script>
Vue.component('test-cx', {
template: '#test'
});
var vm = new Vue({
el: '#app',
data: {},
methods: {}
});
</script>
</body>
渲染:
<!-- 有大写的要转成驼峰-->
<div id="app">
<test-cx></test-cx> <!--组件的名称-->
</div>
结果:

- 创建私有组件
<body>
<div id="app1">
<test></test>
</div>
<template id="cx1">
<div>
<h3>我是私有组件</h3>
</div>
</template>
<script>
var vm = new Vue({
el: '#app1',
data: {
},
methods: {
},
// 定义实例内部私有组件的
components: {
test: {
template: '#cx1'
}
}
})
</script>
</body>
结果:

三、组件中的data
<body>
<div id="app">
<my></my>
</div>
<script>
//组件中的data必须是一个有返回值的方法,和实例中的data使用不一样
Vue.component('my', {
template: '<h3>这是全局组件 --- {{msg}}</h3>',
data: function () {
return {
msg: '我是vue中的data----组件中的data必须有一个返回值,和实例中的data使用不一样'
}
}
})
var vm = new Vue({
el: '#app',
data: {
},
methods:{
//组件方法
}
})
</script>
</body>
结果:

四、使用components属性定义局部子组件
<body>
<div id="app">
<account>
<login></login>
</account>
</div>
<script>
var vm = new Vue({
el: '#app',
data: {},
methods: {},
components: { // 定义子组件
account: { // account 组件
template: '<div><h1>这是Account组件{{name}}</h1><login></login></div>', // 在这里使用定义的子组件
components: { // 定义子组件的子组件
login: { // login 组件
template: "<h3>这是登录组件</h3>"
}
}
}
}
});
</script>
</body>
结果:

五、组件的切换
- 使用component实现组件的切换
<body>
<div id="app">
<!-- 组件需要加上单引号,不然应该是以字符串输出了-->
<a href="" @click.prevent="comName='login'">登录</a>
<a href="" @click.prevent="comName='register'">注册</a>
<!-- component 是一个占位符, :is 属性,可以用来指定要展示的组件的名称 -->
<component :is="comName"></component>
</div>
<script>
Vue.component('login', {
template: '<h3>登录组件</h3>'
})
Vue.component('register', {
template: '<h3>注册组件</h3>'
})
var vm = new Vue({
el: '#app',
data: {
// 当前 component 中的 :is 绑定的组件的名称
comName: 'login'
}
})
</script>
</body>
- 使用v-if和v-else实现组件的切换
<body>
<div id="app">
<a href="" @click.prevent="flag=true">登录</a>
<a href="" @click.prevent="flag=false">注册</a>
<login v-if="flag"></login>
<register v-else="flag"></register>
</div>
<script>
Vue.component('login', {
template: '<h3>登录组件</h3>'
})
Vue.component('register', {
template: '<h3>注册组件</h3>'
})
var vm = new Vue({
el: '#app',
data: {
flag: false
}
})
</script>
</body>
结果:
注意:这里需要加上.prevent,防止预设行为,不然切换到注册的一瞬间就又切换回来了。
六、父子组件的传值
- 父组件 传值 给子组件
<body>
<div id="app">
<!-- 父传子可以通过 v-bind 属性绑定方式传值,简写为 : -->
<yk :parentmsg="msg"></yk>
</div>
<script>
var vm = new Vue({
el: '#app',
data: {
msg: '我是父组件的数据'
},
methods: {
},
components: {
//子组件是无法直接获取父组件中的data上的数据和methods 中的方法
yk: {
template: '<h3 @click="change">我是子组件 --- {{parentmsg}}</h3>',
// props 中的数据都是父组件传来的,都是只读的,无法重新赋值
props: ['parentmsg'],
methods: {
//即使强制修改,VUE会报错
change() {
this.parentmsg = '被修改了'
}
}
}
}
})
</script>
</body>
- 父组件 传方法 给子组件
<body>
<div id="app">
<!-- 父组件向子组件传递方法,使用的是事件绑定机制v-on,简写为@ -->
<!-- 当我们自定义了一个事件属性之后,那么子组件就能够通过某些方式来调用传递进去的方法了 -->
<!-- 如果show()带括号就是将调用完show的方法的结果返回给func,不带括号的就将show的方法给func-->
<com2 @func="show"></com2>
</div>
<template id="tmpl">
<div>
<h1>这是 子组件</h1>
<input type="button" value="这是子组件中的按钮 - 点击它,触发父组件传递过来的func方法" @click="myclick">
</div>
</template>
<script>
var com2 = {
template: '#tmpl',
methods: {
myclick() {
this.$emit('func')
}
}
}
var vm = new Vue({
el: '#app',
data: {
msg: '我是父组件的数据'
},
methods: {
show() {
console.log('调用了父组件身上的 show 方法: --- ');
}
},
//加载子组件
components: {
com2
}
})
</script>
</body>
结果:

- 子组件 传值 给父组件(子组件需要使用父组件的方法传值)
<body>
<div id="app">
<com2 @func="show"></com2>
</div>
<template id="tmpl">
<div>
<h1>这是 子组件</h1>
<input type="button" value="这是子组件中的按钮 - 点击它,触发 父组件传递过来的 func 方法" @click="myclick">
</div>
</template>
<script>
var com2 = {
template: '#tmpl',
data() {
return {
sonmsg: { name: '张三', age: 16 }
}
},
methods: {
myclick() {
//调用父组件的方法并且传值给组件
// this.$emit('func', 123)
//传对象
this.$emit('func', this.sonmsg)
}
}
}
var vm = new Vue({
el: '#app',
data: {
msg: '我是父组件的数据'
},
methods: {
show(data) {
//获取子组件传来的值
// console.log('调用了父组件身上的 show 方法: ---获取子组件传的值 ' + data);
//获取子组件传的对象
this.msg = data
console.log("使用子组件的值 " + this.msg.name + " " + this.msg.age);
}
},
//加载组件
components: {
com2
}
})
</script>
</body>
结果:

七、使用ref获取组件和DOM元素
vue不推荐直接操作dom元素
<body>
<div id="app">
<input type="button" value="获取" @click="getElement" ref="mybtn">
<h3 ref="myH3"> 学习使用ref获取组件和DOM元素</h3>
<hr>
<!-- 组件也是可以通过ref引用的 -->
<login ref="mylogin"></login>
</div>
<script>
var login = {
template: '<h1>登录组件</h1>',
data() {
return {
msg: '我是子组件的数据'
}
},
methods: {
show() {
console.log('调用了子组件的方法')
}
}
}
var vm = new Vue({
el: '#app',
data: {
},
methods: {
getElement() {
//获取dom元素数据
console.log(this.$refs.myH3.innerText)
//通过ref调用子组件的数据
console.log(this.$refs.mylogin.msg);
//通过ref调用子组件的方法
this.$refs.mylogin.show()
}
},
components: {
login
}
})
</script>
</body>
结果:

八、关于vue中的 $emit 和 $on
Event.$emit('msg',this.msg);
//发送数据,第一个参数是发送数据的名称,接收时还用这个名字接收,第二个参数是这个数据现在的位置;
Event.$on('msg',function(msg){
//接收数据,第一个参数是数据的名字,与发送时的名字对应,第二个参数是一个方法,要对数据的操作
274





