34. VUE 的 编译作用域 以及 slot作用域插槽(获取组件作用域中的数据)
其实就是 如果有很多个组件 ,当你在组件 使用变量的时候 ,那么你变量的作用域其实就也是在他定义的代码中找,如果没找到,那么就报错,【这个很基础的 是人都看出的】
官方说:父组件模板的所有东西都会在父级作用域内编译;子 组件模板的所有东西都会在子级作用域内编译。
下面例子完美说明了:
作用域插槽是slot一个比较难理解的点这里需要细心理解:
我现在说下软件需求目标:
子组件中有一组数据:比如:pLanguages: ['JavaScript', 'Python', 'Swift', 'Go', 'C++'],我要他在子组件的插槽中 ,有的用列表显示,有的用 - 链接、有的用 * 链接。
先看源代码(未使用插槽,写死的,在这个代码中改写 使用插槽作用域):
源代码:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>购物车</title>
<script src="js/vue.js"></script>
</head>
<body>
<!-- 未使用插槽 下面模板是写死的 -->
<template id="cpn">
<div>
<ul>
<li v-for=" item in pLanguages">{{item}}</li>
</ul>
</div>
</template>
<div id="app">
<cpn></cpn>
</div>
<script>
const app = new Vue({
el: "#app",
components: {
'cpn': {
template: "#cpn",
data() {
return {
pLanguages: ['JavaScript', 'Python', 'Swift', 'Go', 'C++']
}
}
}
}
})
</script>
</body>
</html>
那么如果用插槽:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>购物车</title>
<script src="js/vue.js"></script>
</head>
<body>
<!-- 使用 了 插槽 且 下面设置了 插槽slot 默认值 -->
<template id="cpn">
<div>
<slot> <!-- 已改动 -->
<ul>
<li v-for=" item in pLanguages">{{item}}</li>
</ul>
</slot>
</div>
</template>
<div id="app">
<cpn></cpn> <!-- 使用默认值 列表的形式 -->
<cpn> <!-- 已改动 -->
<!-- 问题就在这里 我想要以 - 链接的方式展现cpn组件中data中的数据,我无法获取,
因为作用域,这里的作用域是Vue实例app的! 只能获取到Vue实例app的data!
所以 下面这句代码是错的!!! 所以怎么解决插槽代码获取子组件中的data呢?
-->
<span v-for="item in pLanguages">{{item + "-"}}</span>
</cpn>
</div>
<script>
const app = new Vue({
el: "#app",
components: {
'cpn': {
template: "#cpn",
data() {
return {
pLanguages: ['JavaScript', 'Python', 'Swift', 'Go', 'C++']
}
}
}
}
})
</script>
</body>
</html>
代码已经在里面很详细的说明了,问题也标注出来了,简而言之:
因为不在子组件的作用域 , 怎么解决插槽代码获取子组件中的data呢?
解决方案: 利用slot作用域插槽

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>购物车</title> <script src="js/vue.js"></script> </head> <body> <!-- 使用 了 插槽 且 下面设置了 插槽slot 默认值 --> <template id="cpn"> <div> <slot :data="pLanguages"> <!-- 已改动 slot添加值绑定,键随便你叫,这里叫data好了 方便. 值是 data中的pLanguages --> <ul> <li v-for=" item in pLanguages">{{item}}</li> </ul> </slot> </div> </template> <div id="app"> <cpn></cpn> <!-- 使用默认值 列表的形式 --> <cpn> <!-- 已改动 --> <!-- 已改动 一般这里写个template模板(VUE 2.5.x以下版本必须使用template模板),然后写上 spt-scope="slot" --> <!-- 这样的话 就会去找 cpn模板的 slot,然后slot.data,这个data就是cpn中“:data” 绑定的data了,这样实现插槽的作用域 --> <template slot-scope="slot"> <span>{{slot.data.join('-')}}</span> </template> </cpn> <!-- 下面演示一下 2.5x以上版本 不用template那种写法: --> <cpn > <div slot-scope="slot"> <span>{{slot.data.join('*')}}</span> </div> </cpn> </div> <script> const app = new Vue({ el: "#app", data:{ s1:"不断奋起!" }, components: { 'cpn': { template: "#cpn", data() { return { pLanguages: ['JavaScript', 'Python', 'Swift', 'Go', 'C++'] } } } } }) </script> </body> </html>
所以这里主要还是 :data="pLanguages" 先拿到 cpn中的 data 中的 pLanguages,因为哪里是 cpn组件的作用域,至于这个健 你叫什么都可以,例如::bihu="pLanguages" ,完全自定义
然后就是这个 <template slot-scope="slot"></template> , 他是写死的,版本允许可以不写 template这个标签的,然后他找到cpn的slot,然后 solt.data 找到 solt的data属性 那就是 pLanguages了!
下面写一个值绑定为 bihu 的:

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>购物车</title> <script src="js/vue.js"></script> </head> <body> <!-- 使用 了 插槽 且 下面设置了 插槽slot 默认值 --> <template id="cpn"> <div> <slot :bihu="pLanguages"> <ul> <li v-for=" item in pLanguages">{{item}}</li> </ul> </slot> </div> </template> <div id="app"> <cpn > <div slot-scope="slot"> <!-- 因为在cpn组件的插槽上绑定的是 bihu ,所以下面bihu就等于pLanguages --> <span>{{slot.bihu.join('*')}}</span> </div> </cpn> </div> <script> const app = new Vue({ el: "#app", data:{ s1:"不断奋起!" }, components: { 'cpn': { template: "#cpn", data() { return { pLanguages: ['JavaScript', 'Python', 'Swift', 'Go', 'C++'] } } } } }) </script> </body> </html>
其实这个不难,主要上面那几个代码你得反复对比你就懂了
画了个小图 逻辑也很清晰了 主要得搞明白问题是什么 为什么要这样解决?
2022年1月14日 20:20:29: 温故而知新:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>购物车</title> <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.3/vue.min.js"></script> </head> <body> <!-- 使用 了 插槽 且 下面设置了 插槽slot 默认值 --> <template id="cpn"> <div> <slot :data="pLanguages"> <!-- 已改动 --> <ul> <li v-for=" item in pLanguages">{{item}}</li> </ul> </slot> </div> </template> <div id="app"> <cpn></cpn> <!-- 使用默认值 列表的形式 --> <cpn> <div slot-scope="slot"> <span>{{slot}}</span> <!-- 可以看到 其实就是 { "data": [ "JavaScript", "Python", "Swift", "Go", "C++" ] }--> <span>{{slot.data}}</span> <!-- 可以看到 其实就是 [ "JavaScript", "Python", "Swift", "Go", "C++" ]--> </div> </cpn> </div> <script> const app = new Vue({ el: "#app", components: { 'cpn': { template: "#cpn", data() { return { pLanguages: ['JavaScript', 'Python', 'Swift', 'Go', 'C++'] } } } } }) </script> </body> </html>
温故而知新:
2022年1月14日 20:40:27

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>购物车</title> <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.3/vue.min.js"></script> </head> <body> <!-- 使用 了 插槽 且 下面设置了 插槽slot 默认值 --> <template id="cpn"> <div> <slot :aaa="pLanguages" name="aaa"> <ul> <li v-for=" item in pLanguages">{{item}}</li> </ul> </slot> <slot :bbb="pLanguages"> <ul> <li v-for=" item in pLanguages">{{item}}</li> </ul> </slot> </div> </template> <div id="app"> <cpn > <!-- 替换 具名插槽 --> <div slot-scope="slot" slot="aaa"> <span>{{slot.aaa.join(' a ')}}</span> </div> <!-- 替换默认插槽 --> <div slot-scope="randomName"> {{randomName}} <!-- { "bbb": [ "西瓜", "冬瓜", "南瓜", "傻瓜" ] } --> </div> </cpn> </div> <script> const app = new Vue({ el: "#app", data:{ s1:"不断奋起!" }, components: { 'cpn': { template: "#cpn", data() { return { pLanguages: ['西瓜', '冬瓜', '南瓜', '傻瓜'] } } } } }) </script> </body> </html>
本文来自博客园,作者:咸瑜,转载请注明原文链接:https://www.cnblogs.com/bi-hu/p/15060786.html