1.什么是组件化

人面对复杂问题的处理方式:

  1. 任何一个人处理信息的逻辑能力都是有限的

  2. 所以,当面对一个非常复杂的问题时,我们不太可能一次性搞定一大堆的内容。

  3. 但是,我们人有一种天生的能力,就是将问题进行拆解。

  4. 如果将一个复杂的问题,拆分成很多个可以处理的小问题,再将其放在整体当中,你会发现大的问题也会迎刃而解。

组件化也是类似的思想:

如果我们将一个页面中所有的处理逻辑全部放在一起,处理起来就会变得非常复杂,而且不利于后续的管理以及扩展。但如果,我们讲一个页面拆分成一个个小的功能块,每个功能块完成属于自己这部分独立的功能,那么之后整个页面的管理和维护就变得非常容易了。

2.vue组件化思想

组件化是Vue.js中的重要思想

  • 它提供了一种抽象,让我们可以开发出一个个独立可复用的小组件来构造我们的应用。

  • 任何的应用都会被抽象成一颗组件树。

组件化思想的应用:

有了组件化的思想,我们在之后的开发中就要充分的利用它。尽可能的将页面拆分成一个个小的、可复用的组件。这样让我们的代码更加方便组织和管理,并且扩展性也更强。

3.注册组件

3.1案例引入

组件的使用分成三个步骤:

  • 创建组件构造器

  • 注册组件

  • 使用组件

下面我们通过代码来看看如何注册组件

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script src="../js/vue.js"></script>
</head>
<body>
<div id="app">
<!-- 使用组件-->
<my-cpn></my-cpn>
</div>
</body>
<script type="text/javascript"> //1、创建组件构造器
const myComponent = Vue.extend({
template:`
<div>
<h2>组件标题</h2>
<p>我是组件中的一个段落</p>
</div
`
}) //2、注册组件,并定义组件标签的名称
Vue.component('my-cpn',myComponent) let app=new Vue({
el: '#app',
data: {
message: '你好呀'
}
})
</script>
</html>

3.2注册组件步骤解析

上面我们通过代码使用了组件,那么这段代码表示什么含义呢?

1.Vue.extend():

调用Vue.extend()创建的是一个组件构造器。 通常在创建组件构造器时,传入template代表我们自定义组件的模板。该模板就是在使用到组件的地方,要显示的HTML代码。事实上,这种写法在Vue2.x的文档中几乎已经看不到了,它会直接使用下面我们会讲到的语法糖,但是在很多资料还是会提到这种方式,而且这种方式是学习后面方式的基础。

2.Vue.component():

  • 调用Vue.component()是将刚才的组件构造器注册为一个组件,并且给它起一个组件的标签名称。

  • 所以需要传递两个参数:1、注册组件的标签名 2、组件构造器

3.组件必须挂载在某个Vue实例下,否则它不会生效。

4.全局父子组件

4.1全局组件和局部组件

当我们通过Vue.component()注册组件时,组件的注册是全局的,这意味着该组件可以在任意Vue实例下使用。

如果我们注册的组件是挂载在某个实例中, 那么就是一个局部组件

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script src="../js/vue.js"></script>
</head>
<body>
<div id="app">
<my-cpn></my-cpn>
</div> <div id="app2">
<my-cpn></my-cpn>
</div>
</body>
<script type="text/javascript">
//1、创建组件构造器
const myComponent = Vue.extend({
template: `
<div>
<h2>组件标题</h2>
<p>我是组件中的一个段落</p>
</div
`
}) let app = new Vue({
el: '#app',
components: {
'my-cpn': myComponent
}
}) let app2 = new Vue({
el: '#app2'
})
</script>
</html>

从页面显示结果我们可以看出app2中的组件没有显示出来,因为这段代码注册的是局部组件,只能在app中使用

4.2父子组件

在前面我们看到了组件树,组件和组件之间存在层级关系,而其中一种非常重要的关系就是父子组件的关系。我们来看通过代码如何组成的这种层级关系:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script src="../js/vue.js"></script>
</head>
<body>
<div id="app">
<!-- 使用组件-->
<parent-cpn></parent-cpn>
</div>
</body>
<script type="text/javascript">
//1 创建一个子组件构造器 注意template的最外层必须用div包裹起来
const childComponent = Vue.extend({
template: `
<div>我是子组件的内容,我是child哦</div>
`
}) //2 创建一个父组件构造器 注意template的最外层必须用div包裹起来
const parentComponet = Vue.extend({
template: `
<div>
<p>我是父组件的内容,我是parent哦</p>
<h2>我是父组件的标题</h2>
<child-cpn></child-cpn>
</div>
`,
components: {
'child-cpn': childComponent
}
}) let app = new Vue({
el: '#app',
components: {
'parent-cpn': parentComponet
}
})
</script>
</html>

注意:

这里不能直接在Vue实例中使用,这样使用浏览器不识别

因为当子组件注册到父组件的components时,Vue会编译好父组件的模块,该模板的内容已经决定了父组件将要渲染的HTML(相当于父组件中已经有了子组件中的内容了),是只能在父组件中被识别的。类似这种用法,是会被浏览器忽略的。

注册组件的语法糖

上面的注册组件的方式有点繁琐,Vue为了简化注册组件的过程,提供了注册组件的语法糖

4.3模板的分离写法

刚才,我们通过语法糖简化了Vue组件的注册过程,另外还有一个地方的写法比较麻烦,就是template模块写法。如果我们能将其中的HTML分离出来写,然后挂载到对应的组件上,必然结构会变得非常清晰。Vue提供了两种方案来定义HTML模块内容:

  • 使用标签

  • 使用标签

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script src="../js/vue.js"></script>
</head>
<body>
<div id="app">
<!-- 使用组件-->
<my-cpn></my-cpn>
</div>
</body> <!-- 使用template标签 -->
<template id="myCpn">
<div>
<h2>组件标题</h2>
<p>我是组件中的一个段落</p>
</div>
</template>
<script type="text/javascript"> let app=new Vue({
el: '#app',
components: {
'my-cpn': {
template: '#myCpn'
}
}
})
</script>
</html>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script src="../js/vue.js"></script>
</head>
<body>
<div id="app">
<!-- 使用组件-->
<my-cpn></my-cpn>
</div>
</body> <!-- 使用script标签 -->
<script type="text/x-template" id="myCpn">
<div>
<h2>组件标题</h2>
<p>我是组件中的一个段落</p>
</div>
</script>
<script type="text/javascript"> let app=new Vue({
el: '#app',
components: {
'my-cpn': {
template: '#myCpn'
}
}
})
</script>
</html>

5.组件数据

上面我们介绍了如何使用Vue组件,但是爱思考的同学就产生问题了,Vue组件中可以访问Vue实例数据吗?

组件是一个单独功能模块的封装,这个模块有属于自己的HTML模板,也应该有属性自己的数据data。

组件中的数据是保存在哪里呢?顶层的Vue实例中吗?我们先来测试一下,组件中能不能直接访问Vue实例中的data

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script src="../js/vue.js"></script>
</head>
<body>
<div id="app">
<my-cpn></my-cpn>
</div>
</body>
<template id="myCpn">
<div>
消息:{{message}}
</div>
</template>
<script type="text/javascript">
let app=new Vue({
el: '#app',
data: {
message: '你好呀'
},
components: {
'my-cpn': {
template: '#myCpn'
}
}
})
</script>
</html>

从页面效果可以看出,组件时访问不到message的。那么组件中的数据该存放在哪里呢

5.1组件数据存放

组件对象也有一个data属性(也可以有methods等属性,下面我们有用到),只是这个data属性必须是一个函数,而且这个函数返回一个对象,对象内部保存着数据。

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script src="../js/vue.js"></script>
</head>
<body>
<div id="app">
<my-cpn></my-cpn>
</div>
</body>
<template id="myCpn">
<div>
消息:{{message}}
</div>
</template>
<script type="text/javascript">
let app=new Vue({
el: '#app',
components: {
'my-cpn': {
template: '#myCpn',
// 存放组件数据的地方
data() {
return {
message: '我是组件的数据'
}
}
}
}
})
</script>
</html>

我们可以看到data()是一个函数,为什么data是一个函数呢?可不可以是对象或者数组呢?答案是不可以,data必须是函数。

  • 首先,如果不是一个函数,Vue直接就会报错。

  • 其次,原因是在于Vue让每个组件对象都返回一个新的对象,因为如果是同一个对象的,组件在多次使用后会相互影响。

下面我们通过一个案例来看data如果每次都返回一个新对象会有什么效果

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script src="../js/vue.js"></script>
</head>
<body>
<div id="app">
<my-cpn></my-cpn>
<my-cpn></my-cpn>
<my-cpn></my-cpn>
<my-cpn></my-cpn>
</div>
</body>
<template id="myCpn">
<div>
<button type="button" @click="btnClick">点击按钮</button>
<span>当前数量:{{count}}</span>
</div>
</template>
<script type="text/javascript">
const obj = {
count: 0
} let app = new Vue({
el: '#app',
components: {
'my-cpn': {
template: '#myCpn',
// 存放组件数据的地方
data() {
return obj;
},
methods: {
btnClick() {
this.count++
}
}
}
}
})
</script>
</html>

6.组件间通信

在上一个小节中,我们提到了子组件是不能引用父组件或者Vue实例的数据的。但是,在开发中,往往一些数据确实需要从上层传递到下层。比如在一个页面中,我们从服务器请求到了很多的数据。其中一部分数据,并非是我们整个页面的大组件来展示的,而是需要下面的子组件进行展示。这个时候,并不会让子组件再次发送一个网络请求,而是直接让大组件(父组件)将数据传递给小组件(子组件)。

Vue官方提供了两种方式用于组件间的通信

  • 通过props向子组件传递数据
  • 通过事件向父组件发送消息

6.1父级向子级传递

在组件中,使用选项props来声明需要从父级接收到的数据。props的值有两种方式:

  • 方式一:字符串数组,数组中的字符串就是传递时的名称。

  • 方式二:对象,对象可以设置传递时的类型,也可以设置默认值等。

我们先来看一个最简单的props传递:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script src="../js/vue.js"></script>
</head>
<body>
<div id="app">
<!-- 3 通过:message="message"将data中的数据传递给了props -->
<child-cpn :message='message'></child-cpn>
</div>
</body> <template id="childCpn">
<div>
显示的信息:{{message}}
</div>
</template>
<script type="text/javascript">
let app=new Vue({
el: '#app',
data: {
message: '我是父组件的内容' //1 Vue实例中的data
},
components: {
'child-cpn': {
template: '#childCpn',
props: ['message'] // 2 组件中的props }
}
})
</script>
</html>

在上面的案例中,我们的props选项是使用一个数组。除了数组props还可以使用对象的方式。我们来看一下具体如何使用。

6.2子级向父级传递数据

props用于父组件向子组件传递数据,还有一种比较常见的是子组件传递数据或事件到父组件中。我们应该如何处理呢?这个时候,我们需要使用自定义事件来完成。

什么时候需要自定义事件呢?当子组件需要向父组件传递数据时,就要用到自定义事件了。我们之前学习的v-on不仅仅可以用于监听DOM事件,也可以用于组件间的自定义事件。

自定义事件的流程:

  1. 在子组件中,通过$emit()来触发事件。

  2. 在父组件中,通过v-on来监听子组件事件。

我们来看一个简单的例子:

我们之前做过一个两个按钮+1和-1,点击后修改counter。我们整个操作的过程还是在子组件中完成,但是之后的展示交给父组件。这样,我们就需要将子组件中的counter,传给父组件的某个属性,比如total。

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script src="../js/vue.js"></script>
</head>
<body>
<div id="app">
<!-- 通过@increment和@decrement监听事件 -->
<child-cpn @increment="changeTotal" @decrement="changeTotal"></child-cpn>
<h2>count: {{total}}</h2>
</div>
</body>
<template id="childCpn">
<div>
<button type="button" @click="increment">+1</button>
<button type="button" @click="decrement">-1</button>
</div>
</template>
<script type="text/javascript">
let app=new Vue({
el: '#app',
data: {
total: 0
},
methods: {
changeTotal(counter){
this.total = counter
}
},
components: {
'child-cpn': {
template: '#childCpn',
data() {
return {
counter: 0
}
},
methods: {
increment() {
this.counter++;
this.$emit('increment',this.counter)
},
decrement() {
this.counter--;
this.$emit('decrement',this.counter)
}
} }
}
})
</script>
</html>

6.3父子组件的访问

有时候我们需要父组件直接访问子组件,子组件直接访问父组件,或者是子组件访问根组件。父组件访问子组件:使用$children或$refs子组件访问父组件:使用$parent

6.3.1$children

我们先来看下$children的访问,this.$children是一个数组类型,它包含所有子组件对象。我们这里通过一个遍历,取出所有子组件的message内容。

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script src="../js/vue.js"></script>
</head>
<body>
<div id="app">
<!-- 在Vue实例中使用父组件 -->
<parent-cpn></parent-cpn>
</div>
</body> <!-- 父组件 -->
<template id="parentCpn">
<div>
<!-- 在父组件中使用子组件 -->
<child-cpn1></child-cpn1>
<child-cpn2></child-cpn2>
<button type="button" @click="showChildCpn()">显示所有子组件的信息</button>
</div>
</template> <!-- 第一个子组件 -->
<template id="childCpn1">
<div>
<h2>我是子组件1,哈哈哈</h2>
</div>
</template>
<!-- 第二个子组件 -->
<template id="childCpn2">
<div>
<h2>我是子组件2,啊啊啊</h2>
</div>
</template> <script type="text/javascript"> // 注册父组件
Vue.component('parent-cpn',{
template: '#parentCpn',
methods: {
showChildCpn() {
for(let i=0; i<this.$children.length;i++){
console.log(this.$children[i].message);
}
}
},
//注册子组件
components: {
'child-cpn1': {
template: '#childCpn1',
data() {
return {
message: '我是子组件1'
}
}
},
'child-cpn2': {
template: '#childCpn2',
data() {
return {
message: '我是子组件2'
}
}
} }
}); let app=new Vue({
el: '#app' })
</script>
</html>

6.3.2$refs

$children的缺陷:

通过$children访问子组件时,是一个数组类型,访问其中的子组件必须通过索引值。但是当子组件过多,我们需要拿到其中一个时,往往不能确定它的索引值,甚至还可能会发生变化。有时候,我们想明确获取其中一个特定的组件,这个时候就可以使用$refs

$refs的使用:

$refs和ref指令通常是一起使用的。首先,我们通过ref给某一个子组件绑定一个特定的ID。其次,通过this.$refs.ID就可以访问到该组件了。

将上面的代码修改成

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script src="../js/vue.js"></script>
</head>
<body>
<div id="app">
<!-- 在Vue实例中使用父组件 -->
<parent-cpn></parent-cpn>
</div>
</body> <!-- 父组件 -->
<template id="parentCpn">
<div>
<!-- 在父组件中使用子组件 -->
<child-cpn1 ref="child1"></child-cpn1>
<child-cpn2 ref="child2"></child-cpn2>
<button type="button" @click="showChildCpn()">显示所有子组件的信息</button>
</div>
</template> <!-- 第一个子组件 -->
<template id="childCpn1">
<div>
<h2>我是子组件1,哈哈哈</h2>
</div>
</template>
<!-- 第二个子组件 -->
<template id="childCpn2">
<div>
<h2>我是子组件2,啊啊啊</h2>
</div>
</template> <script type="text/javascript"> // 注册父组件
Vue.component('parent-cpn',{
template: '#parentCpn',
methods: {
showChildCpn() {
// 这里通过child1 child2来访问子组件
console.log("refs"+this.$refs.child1.message);
console.log("refs"+this.$refs.child2.message);
}
},
//注册子组件
components: {
'child-cpn1': {
template: '#childCpn1',
data() {
return {
message: '我是子组件1'
}
}
},
'child-cpn2': {
template: '#childCpn2',
data() {
return {
message: '我是子组件2'
}
}
} }
}); let app=new Vue({
el: '#app' })
</script>
</html>

6.3.3$parent

如果我们想在子组件中直接访问父组件,可以通过$parent

注意事项:

尽管在Vue开发中,我们允许通过$parent来访问父组件,但是在真实开发中尽量不要这样做。子组件应该尽量避免直接访问父组件的数据,因为这样耦合度太高了。如果我们将子组件放在另外一个组件之内,很可能该父组件没有对应的属性,往往会引起问题。另外,更不好做的是通过$parent直接修改父组件的状态,那么父组件中的状态将变得飘忽不定,很不利于我的调试和维护。

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script src="../js/vue.js"></script>
</head>
<body>
<div id="app">
<!-- 在Vue实例中使用父组件 -->
<parent-cpn></parent-cpn>
</div>
</body> <!-- 父组件 -->
<template id="parentCpn">
<div>
<!-- 在父组件中使用子组件 -->
<child-cpn></child-cpn>
</div>
</template> <!-- 子组件 -->
<template id="childCpn">
<div>
<h2>我是子组件,哈哈哈</h2>
<button type="button" @click="showParent">显示父组件的信息</button>
</div>
</template> <script type="text/javascript"> // 注册父组件
Vue.component('parent-cpn',{
template: '#parentCpn',
data() {
return {
message: '我是父组件'
}
},
//注册子组件
components: {
'child-cpn': {
template: '#childCpn',
methods: {
showParent() {
console.log(this.$parent.message)
}
}
} }
}); let app=new Vue({
el: '#app' })
</script>
</html>

6.3.4非父子组件通信

刚才我们讨论的都是父子组件间的通信,那如果是非父子关系呢?非父子组件关系包括多个层级的组件,也包括兄弟组件的关系。在Vue1.x的时候,可以通过$dispatch和$broadcast完成。$dispatch用于向上级派发事件,$broadcast用于向下级广播事件。但是在Vue2.x都被取消了,在Vue2.x中,有一种方案是通过中央事件总线,也就是一个中介来完成。但是这种方案和直接使用Vuex的状态管理方案还是逊色很多。并且Vuex提供了更多好用的功能,所以这里我们暂且不讨论这种方案,后续我们专门学习Vuex的状态管理。

7.插槽slot

7.1编译作用域

在真正学习插槽之前,我们需要先理解一个概念:编译作用域。官方对于编译的作用域解析比较简单,我们自己来通过一个例子来理解这个概念:我们来考虑下面的代码是否最终是可以渲染出来的:

<my-cpn v-show="isShow"></my-cpn>这段代码中,我们使用了isShow属性。isShow属性包含在组件中,也包含在Vue实例中。

答案:最终可以渲染出来,也就是使用的是Vue实例的属性。为什么呢?

官方给出了一条准则:父组件模板的所有东西都会在父级作用域内编译;子组件模板的所有东西都会在子级作用域内编译。而我们在使用<my-cpn v-show="isShow"></my-cpn>的时候,整个组件的使用过程是相当于在父组件中出现的。那么他的作用域就是父组件,使用的属性也是属于父组件的属性。因此,isShow使用的是Vue实例中的属性,而不是子组件的属性。

7.2为什么使用插槽(slot)

slot翻译为插槽,在生活中很多地方都有插槽,电脑的USB插槽,插板当中的电源插槽。插槽的目的是让我们原来的设备具备更多的扩展性。比如电脑的USB我们可以插入U盘、硬盘、手机、音响、键盘、鼠标等等。

组件的插槽:

组件的插槽也是为了让我们封装的组件更加具有扩展性。让使用者可以决定组件内部的一些内容到底展示什么。

栗子:移动网站中的导航栏

移动开发中,几乎每个页面都有导航栏。导航栏我们必然会封装成一个插件,比如nav-bar组件。一旦有了这个组件,我们就可以在多个页面中复用了。例如京东的导航

7.3如何使用slot

如何去封装这类的组件呢?

它们也很多区别,但是也有很多共性。如果,我们每一个单独去封装一个组件,显然不合适:比如每个页面都返回,这部分内容我们就要重复去封装。但是,如果我们封装成一个,好像也不合理:有些左侧是菜单,有些是返回,有些中间是搜索,有些是文字,等等。

如何封装合适呢?抽取共性,保留不同

最好的封装方式就是将共性抽取到组件中,将不同暴露为插槽。一旦我们预留了插槽,就可以让使用者根据自己的需求,决定插槽中插入什么内容。是搜索框,还是文字,还是菜单。由调用者自己来决定。这就是为什么我们要学习组件中的插槽slot的原因

7.4slot基本使用

了解了为什么用slot,我们再来谈谈如何使用slot?在子组件中,使用特殊的元素<slot>就可以为子组件开启一个插槽。该插槽插入什么内容取决于父组件如何使用。

我们通过一个简单的例子,来给子组件定义一个插槽:<slot>中的内容表示,如果没有在该组件中插入任何其他内容,就默认显示该内容

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script src="../js/vue.js"></script>
</head>
<body>
<div id="app">
<!-- 如果组件中没有替换,则使用默认显示内容 -->
<child-cpn></child-cpn>
<br/>
<child-cpn>
<!-- 使用自己的内容替换插槽的内容 -->
<h2>我是插槽的替换内容1</h2>
<p>我是插槽的替换内容2</p>
</child-cpn>
</div>
</body> <template id="childCpn">
<div>
<!-- 定义一个插槽 里面有默认内容 -->
<slot>我是一个插槽中的默认内容</slot>
</div>
</template> <script type="text/javascript"> let app=new Vue({
el: '#app',
components: {
'child-cpn': {
template: '#childCpn'
}
}
})
</script>
</html>

7.5具名插槽slot

当子组件的功能复杂时,子组件的插槽可能并非是一个。比如我们封装一个导航栏的子组件,可能就需要三个插槽,分别代表左边、中间、右边。那么,外面在给插槽插入内容时,如何区分插入的是哪一个呢?这个时候,我们就需要给插槽起一个名字

如何使用具名插槽呢?非常简单,只要给slot元素一个name属性即可<slot name='myslot'></slot>

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script src="../js/vue.js"></script>
</head>
<body>
<div id="app">
<!-- 没有传入任何内容 -->
<child-cpn></child-cpn>
<br/>
<!-- 传入某一个内容 -->
<child-cpn>
<span slot="left">我是返回</span>
</child-cpn>
<br/>
<!-- 传入所有内容 -->
<child-cpn>
<span slot="left">我是返回</span>
<span slot="center">我是标题</span>
<span slot="right">我是菜单</span>
</child-cpn>
</div>
</body> <template id="childCpn">
<div>
<slot name="left">左边</slot>
<slot name="center">中间</slot>
<slot name="right">右边</slot>
</div>
</template> <script type="text/javascript"> let app=new Vue({
el: '#app',
components: {
'child-cpn': {
template: '#childCpn'
}
}
})
</script>
</html>

7.6作用域插槽

作用域插槽是slot一个比较难理解的点,而且官方文档说的又有点不清晰。这里,我们用一句话对其做一个总结,然后我们在后续的案例中来体会:父组件替换插槽的标签,但是内容由子组件来提供

我们先提一个需求:

子组件中包括一组数据,比如:pLanguages: ['JavaScript', 'Python', 'Swift', 'Go', 'C++'],需要在多个界面进行展示。某些界面是以水平方向一一展示的,某些界面是以列表形式展示的,某些界面直接展示一个数组。内容在子组件,希望父组件告诉我们如何展示,怎么办呢?利用slot作用域插槽就可以了。

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script src="../js/vue.js"></script>
</head>
<body>
<div id="app">
<my-cpn>
<!-- 通过<template slot-scope="slotProps">获取到slotProps属性 -->
<template slot-scope="slotProps">
<!-- 列表展示 -->
<ul>
<!-- 通过slotProps.data就可以获取到刚才我们传入的data -->
<li v-for="info in slotProps.data">{{info}}</li>
</ul>
</template>
</my-cpn> <my-cpn>
<template slot-scope="slotProps">
<!-- 水平展示 -->
<span v-for="info in slotProps.data">{{info}} </span>
</template>
</my-cpn>
</div>
</body> <template id="myCpn">
<div>
<slot :data="pLanguages"></slot>
</div>
</template> <script type="text/javascript"> let app=new Vue({
el: '#app',
components: {
'my-cpn': {
template: '#myCpn',
data() {
return {
pLanguages: [
'JavaScript', 'Python', 'Swift', 'Go', 'C++'
]
}
}
}
}
})
</script>
</html>

详解Vue大护法——组件的更多相关文章

  1. 详解Vue 非父子组件通信方法(非Vuex)

    假设 bb 组件里面有个按钮,点击按钮,把 123 传递给 aa 组件 // 根组件(this.$root) new Vue({ el: '#app', router, render: h => ...

  2. 详解Vue中的computed和watch

    作者:小土豆 博客园:https://www.cnblogs.com/HouJiao/ 掘金:https://juejin.cn/user/2436173500265335 1. 前言 作为一名Vue ...

  3. 详解Vue.js 技术

    本文主要从8个章节详解vue技术揭秘,小编觉得挺有用的,分享给大家. 为了把 Vue.js 的源码讲明白,课程设计成由浅入深,分为核心.编译.扩展.生态四个方面去讲,并拆成了八个章节,如下: 准备工作 ...

  4. 详解vue的数据binding原理

    自从angular火了以后,各种mv*框架喷涌而出,angular虽然比较火,但是他的坑还是蛮多的,还有许多性能问题被人们吐槽.比如坑爹的脏检查机制,数据binding是受人喜爱的,脏检查就有点…性能 ...

  5. 【转载】NeurIPS 2018 | 腾讯AI Lab详解3大热点:模型压缩、机器学习及最优化算法

    原文:NeurIPS 2018 | 腾讯AI Lab详解3大热点:模型压缩.机器学习及最优化算法 导读 AI领域顶会NeurIPS正在加拿大蒙特利尔举办.本文针对实验室关注的几个研究热点,模型压缩.自 ...

  6. 详解Vue 方法与事件处理器

      本篇文章主要介绍了详解Vue 方法与事件处理器 ,小编觉得挺不错的,现在分享给大家,也给大家做个参考.一起跟随小编过来看看吧 方法与事件处理器 方法处理器 可以用 v-on 指令监听 DOM 事件 ...

  7. 详解Kafka: 大数据开发最火的核心技术

    详解Kafka: 大数据开发最火的核心技术   架构师技术联盟 2019-06-10 09:23:51 本文共3268个字,预计阅读需要9分钟. 广告 大数据时代来临,如果你还不知道Kafka那你就真 ...

  8. 详解vue 路由跳转四种方式 (带参数)

    详解vue 路由跳转四种方式 (带参数):https://www.jb51.net/article/160401.htm 1.  router-link ? 1 2 3 4 5 6 7 8 9 10 ...

  9. 详解Vue 如何监听Array的变化

    详解Vue 如何监听Array的变化:https://www.jb51.net/article/162584.htm

随机推荐

  1. Python 简明教程 --- 17,Python 模块与包

    微信公众号:码农充电站pro 个人主页:https://codeshellme.github.io 正确的判断来源于经验,然而经验来源于错误的判断. -- Fred Brooks 目录 我们已经知道函 ...

  2. 【思考】URI和URL的区别?以及URL的结构

    URI = Universal Resource Identifier URL = Universal Resource Locator 在学习中,我们难免会遇到 URI 和 URL,有时候都傻傻分不 ...

  3. 入门大数据---Spark_Streaming整合Flume

    一.简介 Apache Flume 是一个分布式,高可用的数据收集系统,可以从不同的数据源收集数据,经过聚合后发送到分布式计算框架或者存储系统中.Spark Straming 提供了以下两种方式用于 ...

  4. vim 常用指令-持续更新

    1. 查询文件夹file1内文件数量:ls file1 | wc -l 2. 生成文件夹file1内的文件列表:find file1 -type f > list.txt 3. git管理文件, ...

  5. 打开指定大小的新窗口和window.open参数

    用法: <SCRIPT LANGUAGE="javascript">   window.open ('要打开的路径', '窗口名称', '参数列表');</SCR ...

  6. codeforce 796C - Bank Hacking(无根树+思维)

    题目 Although Inzane successfully found his beloved bone, Zane, his owner, has yet to return. To searc ...

  7. Nginx 从入门到放弃(一)

    Nginx nginx的使用场景 静态资源服务 通过本地文件系统提供服务 反向代理服务 nginx的强大性能 缓存 负载均衡 API服务 OpenResty nginx优点 高并发.高性能 可扩展性好 ...

  8. 高可用服务注册中心(Eureka-Cluster)

    在实际生产中,我们需要高可用的集群方案,本章就是基于SpringBoot1.5.4 Cloud(Dalston.SR2) 的高可用Eureka Cluster,以及生产中需要注意的事项… - Eure ...

  9. Python3笔记018 - 4.3 元组

    第4章 序列的应用 python的数据类型分为:空类型.布尔类型.数字类型.字节类型.字符串类型.元组类型.列表类型.字典类型.集合类型 在python中序列是一块用于存放多个值的连续内存空间. py ...

  10. docker容器化python服务部署(supervisor-gunicorn-flask)

    docker容器化python服务部署(supervisor-gunicorn-flask) 本文系作者原创,转载请注明出处: https://www.cnblogs.com/further-furt ...