1.6.1. 组件
什么是组件:组件的出现, 就是为了拆分Vue实例的代码量的,能够让我们以不同的组件,来划分不同的功
能模块,将来我们需要什么样的功能,就可以去调用对应的组件即可;
组件化和模块化的不同:
+模块化:是从代码逻辑的角度进行划分的;方便代码分层开发,保证每个功能模块的职能单一- ;
+组件化:是从UI界 面的角度进行划分的;前端的组件化,方便UI组件的重用;
• 创建组件
注意template 里根标签只能有一个!
• 使用Vue.extend({temlate:…})创建
组件的名称使用驼峰式命名时,引用时应该使用 - 连接使用
<body>
<div id="app">
<my-com1>my-mom1>
div>
<script type="text/javascript">
// 步骤一:使用Vue.extend来创建全局的Vue组件
var com1 = Vue.extend({
template: '这是通过Vue.extend创建的组件
'
})
// 步骤二:使用Vue.component('组件的名称', 创建传来的组建的)
例子:Vue.component('my-com1', com1)
var vm = new Vue({
el: '#app',
data:{
},
methods:{
}
});
script>
body>
• 使用Vue.component(‘组件名’,对象)创建
<body>
<div id="app">
<my-com2>my-com2>
div>
<script type="text/javascript">
// Vue.component('my-com2', Vue.extend({
// template: '我是第二种方法练习组件
'
// }))
Vue.component('my-com2',{
template: '我是第二种方法练习组件
'
})
var vm = new Vue({
el:'#app',
data: {
name: '贾真琦'
},
methods:{
}
});
script>
body>
• 创建template标签(字面量类型的组件模板对象)
<body>
<div id="app">
<seven>seven>
div>
<template id="tmp1">
<div>
<p>篮球之神:p>
<span>hahahspan>
div>
template>
<script type="text/javascript">
Vue.component('seven', {
template: "#tmp1"
})
var vm = new Vue({
el: '#app',
data: {
name: '贾真琦'
},
methods:{
}
});
script>
body>
• 创建私有组件
var vm = new Vue({
el: '#app1',
data: {
name: '贾真琦'
},
methods:{
},
//定义私有组件
components:{
login: {
template:'#temp2'
}
}
});
使用省略方式
<body>
<div id="app">
<login>login>
div>
<script type="text/javascript">
//模板对象
var login = {
template: '我是第二种方法练习组件
'
}
var vm = new Vue({
el:'#app',
data: {
name: '贾真琦'
},
methods:{
},
//私有组件
components:{
login //直接用模板对象,调用时名字一致
}
});
script>
body>
• 组件中的data与methods
注意: 组件中的data 是一个函数返回对象,而实例中是一个对象
但是组件中方法和实例中的方法一样的
var duixiang = {msg:1}
Vue.component('count', {
template: '#tmp',
data:function() {
// return {msg: 1}
return duixiang
},
methods:{
add() {
this.msg += 1
}
}
})
• 组件切换
• v-if与v-else指令切换
主要功能代码:
代码示例:
<body>
<div id="app">
<input type="button" value="注册" @click="show1()"/>
<input type="button" value="登录" @click="show2()"/>
login>
denglu>
div>
<template id="tem1">
<div class="s1">
<p>注册p>
<div class="ss1">
div>
div>
template>
<template id="tem2">
<div class="s1">
<p>登录p>
<div class="ss2">
div>
div>
template>
<script type="text/javascript">
Vue.component('login', {
template: '#tem1'
})
Vue.component('denglu', {
template: '#tem2'
})
var vm = new Vue({
el: '#app',
data: {
msg: true
},
methods:{
show1(){
this.msg = true;
},
show2(){
this.msg = false;
}
}
});
script>
body>
• 标签占位符加属性:is绑定组件名切换
主要实现手段 :
在 在app的范围内 添加 标签,并添加:is属性,通过点击按钮改变data里存放组件名的变量
<html>
<head>
<meta charset="utf-8">
<title>v-if与v-else切换title>
<script src="../js/vue.js" type="text/javascript" charset="utf-8">script>
<style type="text/css">
.s1 {
width: 200px;
height: 200px;
background-color: #1B6D85;
}
.s1>p {
height: 20px;
text-align: center;
}
.s1>div {
margin-left: 20px ;
width: 160px;
height: 150px;
}
.s1 .ss1 {
background-color: #2B542C;
}
.s1 .ss2 {
background-color: red;
}
style>
head>
<body>
<div id="app">
<input type="button" value="注册" @click="zujianname='login'"/>
<input type="button" value="登录" @click="zujianname='denglu'"/>
<component :is="zujianname">component>
div>
<template id="tem1">
<div class="s1">
<p>注册p>
<div class="ss1">
div>
div>
template>
<template id="tem2">
<div class="s1">
<p>登录p>
<div class="ss2">
div>
div>
template>
<script type="text/javascript">
Vue.component('login', {
template: '#tem1'
})
Vue.component('denglu', {
template: '#tem2'
})
var vm = new Vue({
el: '#app',
data: {
zujianname: 'login'
}
});
script>
body>
html>
• 组件切换动画实现
直接将组件包裹在 标签,设置动画效果就可以.
• mode指令
属于 标签的一个属性 有 in-out与out-in值,实现组件切换时,动画效果的先进后出,与先出后进效果
• 父组件传子组件
• 父组件传数据给子组件
在子组件中 有一个 props:[] 存放的列表
1.在子组件的标签上 使用数据绑定 v-bind:seven = “父组件中变量”
2.在子组件的template中引用{{seven}}
3.在子组件的props:[‘seven’] :这里的数据是只读的,当修改时会提示错误
示例:
<body>
<div id="app">
login>
div>
<template id="tmp">
<div>
<p>我们接收父组件传过来的:值{{fcz}}p>
div>>
template>
<script type="text/javascript">
var vm = new Vue({
el:'#app',
data:{
msgf : 'qiqiqiqiqiiqiqiqi' },
methods:{},
components:{
'login': {
template: '#tmp',
props: ['fcz']
}
}
});
script>
body>
• 传方法
1.父组件有 方法 fu()
2.组件标签绑定父类方法 :v-on:seven=“add” (此处注意直传名,不能带括号,不然传的是方法的值)
3.组件内定义方法zi() ,zi()方法通过 this.$emit(‘seven’,参数)调用父类方法
(此处的参数,父类方法可以接收,在输出,或者把子类传来的数据保存到父类data中)
4.标签中的标签调用zi()方法即可
代码示例:
<body>
<div id="app">
login>
<hr >
<p>id:{{id}},name:{{name}}p>
div>
<template id="tmp">
<div>
<p>我们接收父组件传过来的:值{{fcz}}p>
<input type="button" value="点击我" @click="count()"/>
<p>显示数字:{{numf}}p>
div>>
template>
<script type="text/javascript">
var vm = new Vue({
el:'#app',
data:{
msgf : 'qiqiqiqiqiiqiqiqi',
num : 1,
id : 0,
name: ''
},
methods:{
add(data1) {
this.num +=1;
console.log("我是父组件的方法:"+this.num);
console.log(data1);
this.id = data1.id;
this.name = data1.name;
}
},
components:{
'login': {
template: '#tmp',
props: ['fcz','numf'],
data:function(){
return {
shuji: {id:7,name:'贾真琦'}
}
},
methods:{
count() {
this.$emit('seven',this.shuji);
}
}
}
}
});
script>
body>
• $emit(‘seven’,data1,data2)
• 评论区案例
<html>
<head>
<meta charset="utf-8">
<title>评论案例title>
<script src="../js/vue.js" type="text/javascript" charset="utf-8">script>
<link rel="stylesheet" type="text/css" href="../css/bootstrap.css"/>
head>
<body>
<div id="app">
<pl v-on:shuaxin="loadComment">pl>
<ul class="list-group">
<li class="list-group-item" v-for="item in list">
<span class="badge">评论人:{{item.user}}span>
{{item.content}}
li>
ul>
div>
<template id="pinglun">
<div>
<div class="form-group">
<label>评论人:label>
<input type="text" class="form-control" v-model="user"/>
div>
<div class="form-group">
<label>评论内容:label>
<textarea class="form-control" v-model="content">
textarea>
div>
<div class="form-group">
<input type="button" class="btn btn-primary" value="发表评论" @click="postComment"/>
div>
div>
template>
<script type="text/javascript">
var commentBox = {
template: '#pinglun',
data: function() {
return {
user: '',
content: ''
}
},
methods: {
postComment() {
console.log(this.user);
//获取输入数据
var comment = {id: Date.now(), user: this.user, content: this.content};
//从localStorage 获取所有评论
var list = JSON.parse(localStorage.getItem('cmts') '[]');
//把新输入的放到数组中
list.push(comment);
//重新保存最新数据
localStorage.setItem('cmts', JSON.stringify(list));
//输入框清空
this.user = this.content = '';
//自动刷新
this.$emit('shuaxin');
}
}
var vm = new Vue(
el:'#app',<w:br/>
data: {
list: [
{id: Date.now(), user: '李白', content: '天生我才必有用'},
{id: Date.now(), user: '科比', content: '你见过凌晨四点的洛杉矶吗'}
]
},
methods:{
loadComment() {
var list = JSON.parse(localStorage.getItem('cmts') '[]');
this.list = list;
}
},
components:{
'pl': commentBox
},
beforeCreate(){},
created() {
this.loadComment();
}
});
script>
body>
html>
1.6.2. 插槽
• 插槽的使用
1.在组件中加入标签(可带参数)
2.在引用组件的时候 直接传入用到的标签即可
<自定义标签>使用的标签(可多个)<自定义标签>
例子:
<login>
<p>hahap>
<img src="..." />
login>
• 具名插槽
组件中含多个 标签时,进行区别每个插槽 为每个 标签设置name属性: 例如: 在使用时指定标签的slot属性为插槽的name
例如:我是按钮我是p
注意: 当全部的插槽指定了名字后,传入标签无slot属性的话,不会该表默认插槽的值,除非有没有name属性的插槽
代码示例:
<div id="app">
<c1>
<button type="button">我是按钮button>
<p slot="s1">我是pp>
c1>
div>
<template id="tmp1">
<div>
<h1>以下为插槽无默认值h1>
<slot>无线slot>
<slot name="s1">左slot>
<slot name="s2">中slot>
<slot name="s3">下slot>
div>
template>
• 编译作用域
官方准则:
父组件模板的东西都会在父级的作用域内编译,子组件模板的所有定西都会在子级作用域内编译
编译作用域, 看当时设置属性的标签属于那个实例,则就是那个实例的数据
例如;
这一组都属于app实例
<div id="app">
<p v-show="isshow">哈哈哈p>
<cc v-show="isshow">
<button type="button" v-show="isshow">我是按钮button>
cc>
div>
这一组都属于组件实例,但是slot好像不受控制
<template id="tmp">
<div>
<p v-show="isshow">测试编译作用域p>
<slot v-show="isshow">
<p>默认的插槽p>
slot>
div>
template>
• 作用域插槽
父组件替换插槽里的标签,但是内容由子组件来提供
个人理解:父类提供显示模板,子类提供数据
具体操作步骤:
1.在组件得插槽中 指定 属性绑定变量 :seven
2.在使用标签时,指定属性 slot-scope=“自定义值”,例如 slot-scope=“slot_t”
3.在使用插值表达式 时,可以使用 {{slot_t.seven}},使用到子组件的变量值了