插槽传值
小程序:循环的插槽中不允许访问页面数据
什么意思呢,比如有一个页面A,引入了一个组件B,B中有一个循环出来的插槽,A中使用组件B,在A中定义的数据是无法直接在插槽中使用的。
举例:
组件inner.vue
:
<template lang="pug">
view
view 外面的
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">
view
view {{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">
view
view 外面的
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">
view
view {{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">
view
view 外面的
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">
view
view {{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">
view
view {{'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">
view
view {{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">
view
view {{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:小程序:循环的插槽中不允许访问页面数据