目录
1. Java高阶函数的使用
编程范式:命令式编程/声明式编程
编程范式:面向对象编程(对象)/函数式编程(函数)
filter/map/reduce
(过滤)filter中的回调函数有一个要求,必须返回一个boolean值
true:当返回true时,函数内部会自动将这次回调的n加入到新的数组中
false:当返回false时,函数会自动过滤这次的n
(映射)map:在回调函数中对数字进行处理
(聚合)reduce的作用:对数字中的所有内容进行汇总
//1 filter函数的使用
//取出小于100的数字
const nums = [10,20,30,40,50,60,70,566,343]
let newNums = nums.filter(function(n){ //newNums接受结果 newNums[]
return n<100; //n符合则加入到新数组
})
console.log(newNums); // [10, 20, 30, 40, 50, 60, 70]
-------------------------
//2 map函数的使用
let new2Num = newNums.map(function (n) {
return n*2;
})
console.log(new2Num); //[20, 40, 60, 80, 100, 120, 140]
-------------------------
//3 reduce函数的使用
/*
new2Num.reduce(function (preValue,n) {
return 100; //preValue拿到上一次函数返回的值
},0) 初始值
*/
//第一次:preValue:0 , n:20
//第二次:preValue:100 , n:40
//第三次:preValue:100 , n:60
let total = new2Num.reduce(function (preValue,n) {
return preValue+n
},0) //初始
console.log(total); //560
//第一次:preValue:0 , n:20
//第二次:preValue:20 , n:40
//第三次:preValue:60 , n:60
//链式
let total = nums.filter(function (n) {
return n < 100;
}).map(function (n) {
return n*2;
}).reduce(function (prevalue,n) {
return preValue + n;
},0)
//等效
let total= nums.filter(n => n<100).map(n => n*2).reduce((preValue,n)=>preValue+n);
console.log(total); //560
2. 表单绑定 v-model
- 双向绑定原理
* vue中使用v-model指令来实现表单元素和数据的双向绑定。
当我们在输入框中输入内容时,因为input中的v-model绑定了message,所以会将实时输入的内容传递给message,使message发生改变。
当message发生改变时,因为上面使用了mustache语法,将message的值插入到dom中,所以dom会发生相应的变化。
<div id="app">
<!-- v-model实现双向绑定 -->
<!-- <input type="text" v-model='message'> -->
<!-- 原理 -->
<!--1 :value="message" 数据和view的绑定 -->
<!--<input type="text" :value="message" @input="valueChange"> input:监听输入 -->
<!-- 等效v-model -->
<input type="text" :value="message" @input="message = $event.target.value"> <!-- $event直接获取事件 -->
<h2>{{message}}</h2>
</div>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el:"#app",
data:{
message:'哈哈哈',
},
methods:{
valueChange(event){ //产生事件浏览器会有event事件对象
//上面不传参,浏览器会自动传入event
this.message = event.target.value; //2 输入的数据绑定到message
}
}
})
</script>
- v-model:redio
<div id="app">
<!-- 加上name属性实现互斥选择,但是一旦v-model绑定同一个变量,也可以实现互斥,可以省略name属性,服务器提交需要name作为key -->
<!-- value是要绑定到sex里的值 -->
<label for="male">
<input type="radio" id="male" value="男" v-model="sex">男
</label>
<label for="female">
<input type="radio" id="female" value="女" v-model="sex">女
</label>
<h2>您选择的性别是:{{sex}}</h2>
</div>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el:"#app",
data:{
message:'哈哈哈',
sex:'男' //默认值
},
methods:{
}
})
</script>
- v-model:checkbox
<div id="app">
<!-- 1 checkbox单选框 -- 布尔类型
<label for="agree">
<input type="checkbox" id="agree" v-model="isAgree">同意协议
</label>
<h2>您选择的是{{isAgree}}</h2>
<button :disabled="!isAgree">下一步</button>
-->
<!--
2 checkbox多选框 -- 数组类型
-->
<!-- value是用来获取的 -->
<input type="checkbox" value="篮球" v-model="hobbies">篮球
<input type="checkbox" value="足球" v-model="hobbies">足球
<input type="checkbox" value="兵乓球" v-model="hobbies">兵乓球
<input type="checkbox" value="排球" v-model="hobbies">排球
<h2>您的爱好是:{{hobbies}}</h2>
</div>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el:"#app",
data:{
message:'哈哈哈',
isAgree:false,
hobbies:[],
}
})
</script>
- v-model:select
<div id="app">
<!-- 1 多个选择一个 -->
<select name="abc" v-model="fluit">
<option value="苹果">苹果</option>
<option value="香蕉">香蕉</option>
<option value="西瓜">西瓜</option>
<option value="桃子">桃子</option>
</select>
<h2>您选择的水果是:{{fluit}}</h2> <!-- 字符串类型 -->
<!-- 2 选择多个 -->
<select name="abc" v-model="fluits" multiple> <!-- multiple:下拉框多选 -->
<option value="苹果">苹果</option>
<option value="香蕉">香蕉</option>
<option value="西瓜">西瓜</option>
<option value="桃子">桃子</option>
</select>
<h2>您选择的水果是:{{fluits}}</h2> <!-- 数组类型 -->
</div>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el:"#app",
data:{
message:'哈哈哈',
fluit:'香蕉',
fluits:[]
}
})
</script>
- input中的值绑定
之前的案例中input的值都是写死的,但是实际上开发中input的值可能是从网络获取或者定义在data中的,我们可以通过v-bind:value动态地给value绑定值。
<div>
<!-- value值的动态绑定 -->
<label v-for="item in originHobbies">
<input type="checkbox" :value="item" v-model="hobbies">{{item}}
</label>
</div>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el:"#app",
data:{
message:'哈哈哈',
isAgree:false,
hobbies:[],
originHobbies:['篮球','足球','兵乓球','排球','高尔夫球']
}
})
</script>
- v-model修饰符的使用
- lazy修饰符:
v-model默认是在input事件中同步输入框的数据的,也就是说一旦有数据发生变化,对应的data中的数据就会发生变化,lazy修饰符可以让数据在失去焦点或者回车时才会更新。 - number:
默认情况下,在输入框中无论我们输入的是字母还是数字,都会被当成字符串进行处理,但是如果我们希望处理的是数组类型,那么最好直接将内容当中数组处理。
number修饰符可以让在输入框中的内容自动转换成为数字类型。 - trim修饰符:
如果输入的内容首尾有很多空格,通常我们需要将其去除,trim修饰符可以过滤内容左右两边的空格。
<div id="app">
<!-- 1 修饰符:lazy 当失去焦点或者按下回车时才进行绑定-->
<input type="text" v-model.lazy="message">
<h2>{{message}}</h2>
<!-- 2 修饰符:number 处理数字类型-->
<input type="number" v-model.number="age"> <!-- v-model默认绑定过去的类型都是string -->
<h2>{{age}}-{{typeof age}}</h2>
<!-- 3 修饰符:trim 过滤内容左右两边的空格 -->
<input type="text" v-model.trim="name">
<h2>您输入的名字:{{name}}</h2>
</div>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el:"#app",
data:{
message:'哈哈哈',
age:0, //number --> '111' string
name:''
}
})
</script>
3.组件化开发
- vue组件化思想
它提供了一种抽象,让我们可以开发出一个个独立可复用的小组件来构造我们的应用。
任何应用都会被抽象成一颗组件树。 - 注册组件的基本步骤
* 创建组件构造器
* 注册组件
* 使用组件
<div id="app">
<!-- 组件可以使代码复用 -->
<!-- 3 使用组件 -->
<my-cpn></my-cpn>
</div>
<script src="../js/vue.js"></script>
<script>
/*
ES6:``波浪线小按键那里,使用``定义字符串,及时换行也可以看成一个整体,不需要+连接
原先:
const s = 'abcd'+
'sds'
ES6:
const s = `abcs
ds`
*/
//1 创建组件构造器对象
const cpnC = Vue.extend({
template:`
<div>
<h2>我是标题</h2>
<p>我是内容,哈哈哈哈</p>
<p>我是内容,呵呵呵呵</p>
</div>`
})
//2 注册组件
// Vue.component('组件标签名',组件构造器)
Vue.component('my-cpn',cpnC)
const app = new Vue({
el:"#app",
data:{
message:'哈哈哈',
}
})
</script>
- 全局组件和局部组件
<div id="app">
<cpn></cpn>
<cpn></cpn>
<cpn></cpn>
</div>
<div id="app2">
<cpn></cpn>
</div>
<script src="../js/vue.js"></script>
<script>
//1 创建组件构造器
const cpnC = Vue.extend({
template:`
<div>
<h2>我是标题</h2>
<p>我是内容哈哈哈</p>
</div>`
})
//2 注册组件(全局组件,可以在多个vue的实例下使用)
Vue.component('cpn',cpnC)
//疑问:怎么注册的组件才是局部组件?
const app = new Vue({
el:"#app",
data:{
message:'哈哈哈',
},
components:{ //3 局部组件
//cpn:使用组件时的标签名
cpn:cpnC,
}
})
//一般只有一个vue实例,但是也可以定义多个
const app2 = new Vue({
el:"#app2",
})
</script>
- 父组件和子组件
- 父子组件的错误用法:
当子组件注册到父组件的components时,Vue会编译号父组件的模块,该模板的内容已经决定父组件将要渲染的HTML(相当于父组件中已经有了子组件的内容了)
<cpn-child></cpn-child>中的内容是只能在父组件中被识别的,如果未注册就使用,浏览器不识别,会报错。
<div id="app">
<cpn2></cpn2>
<!-- <cpn1></cpn1> 组件的使用要么是全局组件,要么得在它的components中注册过,否则使用报错
会优先在自己的components中找,如果找不到再找全局组件
-->
</div>
<script src="../vue.js"></script>
<script>
//第一个组件构造器(子组件)
const cpnC1 = Vue.extend({
template:`
<div>
<h2>我是标题1</h2>
<P>我是内容哈哈哈</P>
</div>
`
})
//第二个组件构造器(父组件)
const cpnC2 = Vue.extend({
template:`
<div>
<h2>我是标题2</h2>
<P>我是内容呵呵呵</P>
<cpn1></cpn1>
</div>
`,
//写在构造器中的组件(在某一个组件中注册另一个组件 -- 可以在组件的模板中使用注册过的另一个组件)
components:{
cpn1:cpnC1, //注册(既不是全局组件也不是局部组件)
}
})
//Vue实例也可以看成是最顶层的组件 --- root
let app = new Vue({
el: '#app',
data: {
msg: '你好',
},
//注册局部组件
components:{
cpn2:cpnC2, /* 虽然cpnC2模板中有cpnC1,但是对于vue实例它是不知道cpnC1存在的*/
}
})
</script>
- 注册组件的语法糖写法
Vue简化了注册组件的过程,省去了调用Vue.extend()的步骤,直接使用一个对象来代替。
<div id="app">
<cpn1></cpn1> <!-- 全局 -->
<cpn2></cpn2> <!-- 局部 -->
</div>
<script src="../js/vue.js"></script>
<script>
//1 全局组件注册的语法糖
//1 创建组件构造器
// const Cpn1 = Vue.extend()
//2 注册组件
//(全局组件)
Vue.component('cpn1',{ //语法糖,直接把构造器放里面,内部会传给extend
template:`
<div>
<h2>我是标题1</h2>
<p>我是内容哈哈哈</p>
</div>`
})
const app = new Vue({
el:"#app",
data:{
message:'哈哈哈',
},
components:{ //局部组件
'cpn2':{
template:`
<div>
<h2>我是标题2</h2>
<p>我是内容嘿嘿嘿</p>
</div>`
}
}
})
</script>
- 组件模板抽离的写法
<div id="app">
<cpn></cpn>
</div>
<!-- 1 这样写打标签比较方便,使用script标签,类型必须是text/x-template-->
<script type="text/x-template" id="cpn1">
<div>
<h2>我是标题1</h2>
<p>我是内容,哈哈哈</p>
</div>
</script>
<!-- 2 template标签 -->
<template id="cpn2">
<div>
<h2>我是标题2</h2>
<p>我是内容,哈哈哈</p>
</div>
</template>
<script src="../js/vue.js"></script>
<script>
//1 注册一个全局组件
Vue.component('cpn',{
template:'#cpn1' //分离模板到外边
})
const app = new Vue({
el:"#app",
})
</script>
- 为什么组件data必须是函数
- 组件是一个单独功能模块的封装:这个模块有属于自己的HTML模板,也应该有属性自己的数据data,组件是不能直接访问vue实例中的data的。
- 组件对象也有一个data属性,而且这个data属性必须是一个函数,函数返回一个对象,对象内部保存着数据。
<script type="text/x-template" id="cpn1">
<div>
<h2>{{title}}</h2>
<p>我是内容,哈哈哈</p>
</div>
</script>
Vue.component('cpn',{
template:'#cpn1', //分离模板到外边
data(){
return{ //返回一个实例对象
title:'abc',
}
}
})
- 为什么data必须是函数?
如果不是函数,组件之间数据会造成影响。
<!-- 组件实例对象 -->
<div id="app">
<cpn></cpn>
<cpn></cpn>
<cpn></cpn>
</div>
<template id="cpn">
<div>
<h2>当前计数:{{counter}}</h2>
<button @click="increment">+</button>
<button @click="decrement">-</button>
</div>
</template>
<script src="../js/vue.js"></script>
<script>
//1 注册组件
/* const obj = {
counter:0
} */
Vue.component('cpn',{
template:'#cpn',
//如果是data{...},那么组件实例调用的都想同一个对象,会导致数据一起改变,互相影响
data(){ //函数,每次都返回一个新的对象
return{
counter:0
}
// return obj; //如果这么写那么每次返回的还是同一个对象,数据还是互相影响
},
methods:{
increment(){
this.counter++;
},
decrement(){
this.counter--;
}
}
})
const app = new Vue({
el:"#app",
data:{
message:'哈哈哈',
}
})
</script>
4.父子组件的通信
子组件是不能引用父组件或者vue实例的数据的,在开发中,往往一些数据确实需要从上层传递到下层,需要子组件来进行展示。这个时候,并不会让子组件再次发送一个网络请求,而是直接让大组件(父组件)将数据传递给小组件(子组件)。
- 父子组件间的通信:
通过props向子组件传递数据
通过事件向父组件发送消息
01. 父组件向子组件传递数据
- props的值有两种方式:
方式一:字符串数组,数组中的字符串就是传递时的名称
方式二:对象,对象可以设置传递时的类型,也可以设置默认值等
<div id="app">
<!--<cpn v-bind:cmovices='movices'></cpn> 记住要v-bind,否则内容会直接当做字符串传递给子组件 -->
<cpn :cmessage='message' :cmovices="movices"></cpn>
</div>
<template id="cpn">
<div>
<ul>
<li v-for="item in cmovices">{{item}}</li>
</ul>
<p>{{cmovices}}</p>
<h2>{{cmessage}}</h2>
</div>
</template>
<script src="../js/vue.js"></script>
<script>
//父传子:props
const cpn = {
template:'#cpn',
// ---- 1.传递数组:可以将数组中的字符串看成变量 -----
// props:['cmovices','cmessage'],
//----- 2.传递对象 -->可以进行类型限制 --------------
props:{
//01 指定类型
// cmovices:Array,
// cmessage:String
//02 提供一些默认值,以及必传值
cmessage:{
type:String,
default:'aaaaa',
required:true //必须传值
},
//03 类型是对象或者数组时,默认值必须是一个函数
cmovices:{
type:Array,
// default:[] //vue2.5.17以下,现在会报错
default(){
return [] //写成函数就不会报错
}
}
},
data(){
return {}
},
methods:{
}
}
//vue实例可以看成父组件
const app = new Vue({
el:'#app',
data:{
message:'哈哈哈',
movices:['海王','海贼王','海尔兄弟'] //将数据传递给子组件显示
},
components:{ //注册局部组件(子组件)
cpn
}
})
</script>
- props驼峰标识
<div id="app">
<!-- c-bind不支持驼峰命名,CInfo是不能够识别的,如果要写驼峰标识,格式应该为C-info -->
<cpn :C-info='info' :child-my-message='message'></cpn>
</div>
<template id="cpn">
<!-- 组件的模板如果包含多标签,外层需要有一个根把内容包起来 -->
<div>
<h2>{{CInfo}}</h2>
<h2>{{childMyMessage}}</h2>
</div>
</template>
<script src="../js/vue.js"></script>
<script>
const cpn = {
template:'#cpn',
props:{
CInfo:{
type:Object,
default(){
return {} //对象的默认值必须是一个函数
}
},
childMyMessage:{
type:String,
default:''
}
}
}
const app = new Vue({
el:"#app",
data:{
info:{
name:'why',
age:18,
height:1.88
},
message:'aaa'
},
components:{
cpn
}
})
</script>
02. 子传父(自定义事件)
以下写法中要注意驼峰命名,可能会报错,识别不了,需要将命名转换一下。但是在脚手架中是可以直接驼峰命名的。
<!-- 父组件模板 -->
<div id="app">
<cpn @itemclick="cpnClick"></cpn>
</div>
<!-- 子组件模板 -->
<template id="cpn">
<div>
<!-- 父组件根据子组件点击的item去请求新的数据 -->
<button v-for="item in categories" @click="btnClick(item)">{{item.name}}</button>
</div>
</template>
<script src="../js/vue.js"></script>
<script>
//1 子组件
const cpn = {
template:'#cpn',
data(){
return {
categories:[
{id:'aaa',name:'热门推荐'},
{id:'bbb',name:'手机数码'},
{id:'ccc',name:'家用家电'},
{id:'ddd',name:'电脑办公'},
]
}
},
methods:{
btnClick(item){ //父传子 --- 自定义事件
//发射事件
this.$emit('itemclick',item) /* 'itemClick'事件名称 */
}
}
}
//2 父组件
const app = new Vue({
el:"#app",
data:{
message:'哈哈哈',
},
components:{
cpn
},
methods:{
cpnClick(item){
console.log("cpnClick",item);
}
}
})
</script>
03. 父子组件通信(结合双向绑定)
(非常绕的代码,要多听几次课理解)
<div id="app">
<!-- :number1='num1' :实现将父组件数据传递给子组件
@num1change="num1change" :实现对子组件传递的数据进行处理,重新给父组件的num赋值
-->
<cpn :number1='num1'
:number2='num2'
@num1change="num1change" @num2change="num2change"
/>
</div>
<template id="cpn">
<div>
<!----------++++ 需求1: 输入框输入可以改变h2中的number1,并且vue实例中的num1也发生改变 ++++-------->
<h2>props:{{number1}}</h2>
<h2>data:{{dnumber1}}</h2>
<!-- <input type="text" v-model="number1">
01 绑定到组件的props中,这样绑定虽然数值会发生改变,但是浏览器报错
props中的属性一般是父组件进行修改的,我们不可以用子组件来修改props中的属性,官方不推荐,我们要避免直接改变里面的值
-->
<!-- <input type="text" v-model="dnumber1">
04 将v-model换成下面等价的方式:也可以实现双向绑定
-->
<input type="text" :value="dnumber1" @input="num1input">
<h2>props:{{number2}}</h2>
<h2>data:{{dnumber2}}</h2> <!-- 03 当前input绑定的是data中的数据,不要直接将数据绑定到props中 -->
<input type="text" :value="dnumber2" @input="num2input">
</div>
</template>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el:"#app",
data:{
num1:1,
num2:0
},
methods:{ //06 接受从子组件传来的数据,进行处理
num1change(value){
this.num1 = parseFloat(value); //这里实现了将子组件传来的数据赋值给父组件原本的数据
},
num2change(value){
this.num2 = parseFloat(value);
},
},
components:{
cpn:{
template:'#cpn',
props:{ //父传子
number1:Number,
number2:Number,
},
data(){ //用data或者计算属性
return {
dnumber1:this.number1, //02 根据props中的number1来初始化data里的dnumber1
dnumber2:this.number2,
}
},
methods:{
num1input(event){
//1将input中的value赋值到dnumber中
this.dnumber1 = event.target.value;
//2 为了让父组件可以修改值,发出一个事件
this.$emit('num1change',this.dnumber1); //05 子传父--自定义方法
/* ====== 需求2 :下面的data值永远是上面的100倍 ======= */
//3 同时修改dnumber2的值 和 num2的值
this.dnumber2 = this.dnumber1 * 100;
this.$emit('num2change',this.dnumber2)
},
num2input(event){
this.dnumber2 = event.target.value,
this.$emit('num2change',this.dnumber2);
this.dnumber1 = this.dnumber2 / 100;
this.$emit('num1change',this.dnumber1)
}
}
}
}
})
</script>
04. 父子组件的访问方式
是通过对象直接访问的,而不是信息的传递那么简单,可能需要在父组件中直接操作子组件的属性或者方法。
- 父组件访问子组件:使用$children或者$refs
- 子组件访问父组件:使用$parent
父访问子-children-refs
<div id="app">
<cpn></cpn>
<cpn></cpn>
<cpn ref='aaa'></cpn> <!-- ref相当于一个key,有key则能获取相应的组件 -->
<button @click='btnClick'>按钮</button>
</div>
<template id="cpn">
<div>我是子组件</div>
</template>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el:"#app",
data:{
message:'哈哈哈',
},
methods:{
btnClick(){
//1 $children --- 当我们需要获取所有子组件的时候,会使用这个
// console.log(this.$children); //this.$children直接获取子组件,调用子组件的方法
// for(let c of this.$children){
// c.showMessage();
// console.log(c.name);
// }
// console.log(this.$children[3].name); 根据下标获取元素不方便,开发子组件不是一成不变的
//2 $refs --- 多用
//必须在组件上加属性ref='...',aaa类似组件的名字,还可以进一步获取具体数据
console.log(this.$refs.aaa.name); //$refs => 对象类型,默认是一个空对象
}
},
components:{
cpn:{
template:'#cpn',
data(){
return {
name:'我是子组件的name',
}
},
methods: {
showMessage(){
console.log('showMessage');
}
},
}
}
})
</script>
子访问父-parent-root
<div id="app">
<cpn></cpn>
</div>
<template id="cpn">
<div>
<h2>我是cpn组件</h2>
<ccpn></ccpn> <!-- 使用子组件 -->
</div>
</template>
<template id="ccpn">
<div>
<h2>我是子组件</h2>
<button @click="btnClick">按钮</button>
</div>
</template>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el:"#app",
data:{
message:'哈哈哈',
},
components:{ //子组件
cpn:{
template:'#cpn',
data() {
return {
name:'我是cpn的组件的name'
}
},
components:{ //子子组件
ccpn:{
template:'#ccpn',
methods: {
btnClick(){
//1 访问父组件 $parent -- 用得少
console.log(this.$parent);
console.log(this.$parent.name);
//2 访问根组件
console.log(this.$root); //访问到vue实例
console.log(this.$root.message);
}
},
},
}
},
}
})
</script>
5. slot 插槽
- 为什么使用插槽:组件的插槽是为了让我们封装的组件更加具有扩展性。
- 插槽的基本使用
<body>
<!--
1 插槽的基本使用:<slot></slot>
2 插槽的默认值:<slot><button>按钮</button></slot>
3 如果有多个值同时放入到组件中进行替换,会一起作为替换元素
-->
<div id="app">
<cpn><button>按钮</button></cpn> <!-- 2 根据插槽显示不同的内容 -->
<cpn><span>哈哈哈</span></cpn>
<cpn>
<i>呵呵呵</i>
<div>我是div</div> <!-- 4 插槽中多个标签,会全部替换 -->
</cpn>
<cpn></cpn> <!-- 3 不指定则显示默认设置的值 -->
</div>
<template id='cpn'>
<div>
<h2>我是组件</h2>
<p>我是组件,哈哈哈</p>
<slot><button>按钮</button></slot> <!-- 1 预备插槽,可以设置默认值 -->
</div>
</template>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el:"#app",
data:{
message:'哈哈哈',
},
components:{
cpn:{
template:'#cpn',
}
}
})
</script>
</body>
- 具名插槽的使用
例如购物商城的导航栏,不同页面的导航栏类似但又有些不同,就可以使用插槽替换内容,给插槽指定名称,就可以控制替换具体的插槽了。
<body>
<div id="app">
<cpn>
<span>哈哈哈</span> <!-- 替换没有名字的插槽 -->
<span slot="center">标题</span> <!-- 替换指定名字的插槽 -->
</cpn>
<cpn><button slot='left'>按钮</button></cpn>
</div>
<template id='cpn'>
<div>
<slot name="left"><span>左边</span></slot>
<slot name="center"><span>中间</span></slot>
<slot name="right"><span>右边</span></slot>
<slot></slot>
</div>
</template>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el:"#app",
data:{
message:'哈哈哈',
},
components:{
cpn:{
template:'#cpn',
}
}
})
</script>
</body>
编译作用域
父组件模板的所有东西都会在父级作用域内编译,子组件模板的所有东西都会在子级作用域内编译。
<div id="app"> <!-- 1 在使用的变量的时候都会先看模板,这里是属于vue实例的模板 -->
<cpn v-show="isShow"></cpn> <!-- 使用的是实例中的isShow -->
</div>
<template id="cpn">
<div>
<h2>我是子组件</h2>
<p>我是内容,哈哈哈</p>
<button v-show="isShow">按钮</button> <!-- 2 组件也有自己的作用域 -->
</div>
</template>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el:"#app",
data:{
message:'哈哈哈',
isShow:true,
},
components:{
cpn:{
template:'#cpn',
data() {
return {
isShow:false,
}
},
}
}
})
</script>
作用域插槽
-
其实就是父组件对子组件里面展示的数据不满意,想要以另一种方式进行展示的时候,就需要从子组件中获取数据,自己设置展示。
-
父组件替换插槽的标签,但是内容由子组件来提供
<div id="app">
<cpn></cpn> <!-- 默认显示 -->
<cpn>
<!-- 父组件想要拿到子组件的数据展示,但是因为作用域问题,不能直接遍历子组件的数据 -->
<!-- 目的是获取子组件中的PLanguages 2.5.x以下需要使用template模板-->
<!-- 2 引用插槽对象 ,使用slot.data即可获取 -->
<template slot-scope="slot">
<!-- <span v-for="item in slot.data">{{item}} - </span> -->
<span>{{slot.data.join(' - ')}}</span>
<!-- join()可以把数组转换为字符串,并且多个数组元素之间可以设置一个字符连接 -->
</template>
</cpn>
<cpn>
<template slot-scope="slot">
<!-- <span v-for="item in slot.data">{{item}} * </span> -->
<span>{{slot.data.join(' * ')}}</span>
</template>
</cpn>
</div>
<template id="cpn">
<div>
<slot :data="PLanguages"> <!-- 1 data是自定义名 -->
<ul>
<li v-for="item in PLanguages">{{item}}</li>
</ul>
</slot>
</div>
</template>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el:"#app",
data:{
message:'哈哈哈',
},
components:{
cpn:{
template:'#cpn',
data() {
return {
PLanguages:['java','c#','python','c++','go','Swift']
}
}
}
}
})
</script>