插槽传值
小程序:循环的插槽中不允许访问页面数据
什么意思呢,比如有一个页面A,引入了一个组件B,B中有一个循环出来的插槽,A中使用组件B,在A中定义的数据是无法直接在插槽中使用的。
举例:
组件inner.vue:
<template lang="pug">viewview 外面的view(v-for="(item, index) in list" :key="index")slot(v-bind:item="item")</template><script>export default {name: 'inner',props: {list: {type: Array,default() {return []}}}}</script>
页面中引入此组件:
<template lang="pug">viewview {{obj.name}}inner(:list="list" v-slot='{ item }')view {{obj.name}}view {{item}}</template><script>import inner from './inner.vue'export default {components: { inner },data() {return {obj: {name: 'hello'},list: [1,2,3,4,5]}},}</script>
在H5中渲染正常:
在小程序中:
可以看出,在小程序中,放到循环插槽中,是不能获取到父页面中的值的。
对此,只能采取一个折中的解决方案:将需要的值传入子组件之中,再暴露给父页面。
具体修改如下:
组件inner.vue:
<template lang="pug">viewview 外面的view(v-for="(item, index) in list" :key="index")slot(v-bind:item="item" v-bind:data="extraData")</template><script>export default {name: 'inner',props: {list: {type: Array,default() {return []}},extraData: {type: Object,default() {return {}}}}}</script>
用一个props(extraData)接收父页面传入的数据,再使用v-bind将其暴露。
页面中:
<template lang="pug">viewview {{obj.name}}inner(:list="list" :extraData="obj" v-slot='{ item, data }')view {{data.name}}view {{item}}</template><script>import inner from './inner.vue'export default {components: { inner },data() {return {obj: {name: 'hello'},list: [1,2,3,4,5]}},}</script>
通过 v-slot将其解构,获取数据。
在小程序中:
写法有点挫,但没办法,只能这样搞定。
一个包含计算属性的示例:
<template lang="pug">Layout(:type='2', title='测试', :showFooter='false')view {{computedName}}inner(:list="list" :extraData="computedName" v-slot='{ item, data }')view {{data}}view {{item}}</template><script>import inner from './inner.vue'export default {components: { inner },data() {return {obj: {name: 'hello'},list: [1,2,3,4,5]}},computed: {computedName() {return this.obj.name + ' world'}}}</script>
如果计算属性是vuex的值,最好是直接放到组件中。
举例:
组件inner.vue:
<template lang="pug">viewview 外面的view(v-for="(item, index) in list" :key="index")slot(v-bind:item="item" v-bind:data="skin")</template><script>import { mapGetters } from 'vuex'export default {name: 'inner',props: {list: {type: Array,default() {return []}},},computed: {...mapGetters({skin: 'skin'})},}</script>
页面中引入:
<template lang="pug">viewview {{obj.name}}inner(:list="list" v-slot='{ item, data }')view(:class="data.tc1") {{item}}</template><script>import inner from './inner.vue'export default {components: { inner },data() {return {obj: {name: 'hello'},list: [1,2,3,4,5]}},}</script>
之前试过将vuex的计算属性传入,但是会得到不可预期的效果,不知道原因。
小程序:循环的插槽中不允许使用过滤器
这点比较头疼,小程序不支持在循环插槽中Vue中的过滤器语法。
比如有如下过滤器:
Vue.filter('date', (value, len = 10) => {if (!value) return ''value = value.slice(0, len)return value})
组件还是同上面 小程序:循环的插槽中不允许数据穿透 的一样。
在页面中调用:
<template lang="pug">viewview {{'2021-01-01 12:00:00' | date}}inner(:list="list" v-slot='{ item }')view {{'2021-01-01 12:00:00' | date}}</template>
小程序端编译出来仍然是无效的。
浏览器:
小程序:
小程序:循环的插槽中不允许使用页面方法
其实看懂了上面两点,这一点也是一样的。说白了,其实就是:
在小程序中,循环插槽不允许使用页面中的方法、过滤器、数据。
示例:
<template lang="pug">viewview {{parseTime('2021-01-01 12:00:00')}}inner(:list="list" v-slot='{ item }')view {{parseTime('2021-01-01 12:00:00')}}</template><script>import inner from './inner.vue'export default {components: { inner },data() {return {list: [1,2,3,4,5]}},methods: {parseTime(time) {return time.slice(0, 10)}}}</script>
或者使用计算属性:
<template lang="pug">viewview {{parseTime('2021-01-01 12:00:00')}}inner(:list="list" v-slot='{ item }')view {{parseTime('2021-01-01 12:00:00')}}</template><script>import inner from './inner.vue'export default {components: { inner },data() {return {list: [1,2,3,4,5]}},computed: {parseTime() {return time => time.slice(0, 10)}},}</script>
可以看到,在H5端正常,小程序端仍然是不能渲染。
解决方案:暂未找到什么好的解决方案。
针对这个问题,我向uniapp提了一个issue:小程序:循环的插槽中不允许访问页面数据
