vue的函数组件(function)-文章来自问我社区
什么是函数式组件函数组件是使组件无状态(没有data)和无实例(没有this上下文)。也没有生命周期方法,它只是一个接受一些 prop 的函数,他们用一个简单的 render 函数返回虚拟节点使它们渲染的代价更小。函数组件的多种形式(1)、只关注样式函数组件,可以借助template实现单文件组件function.vue<template functional><ul>&l
什么是函数式组件
函数组件是使组件无状态(没有data)和无实例(没有this上下文)。也没有生命周期方法,它只是一个接受一些 prop 的函数,他们用一个简单的 render 函数返回虚拟节点使它们渲染的代价更小。
函数组件的多种形式
(1)、只关注样式函数组件,可以借助template实现
单文件组件function.vue
<template functional>
<ul>
<slot/>
<li v-for="item in props.list" :key="item.id" @click="props.itemClick(item)">{{item}}</li>
</ul>
</template>
父组件使用函数组件
<BookList :list='list' :itemClick="bookSelect"><li>书籍列表</li></BookList>
slot
是默认插槽,显示组件间的标签内容;这里需要知道,向组件中传递不带 v-slot 指令的子节点时,
比如 BookList 中的 <li>书籍列表</li>
,这些子节点被存储在$slots.default中。
functional
template的functional是函数组件的关键
(2)、函数的类组件(h)写法
声明function.js的文件,创建对象标明functional: true
加上render function
的形式就是函数组件,此时要省略template
的语法
<script>
export default {
//标记为函数式组件
functional: true,
// props: {
// list: {
// type: Array,
// required: true
// }
// },
//render函数 或 function (createElement, context) {}
render: function (h, {props, listeners, children, data}) { // context 结构出来的属性
return(<ul>
{children}
{props.list.map(i => <li style="color:blue" οnclick={(event,i)=> data.attrs.itemClick(event.target.textContent)}>{i}</li>)}
</ul>)
},
}
</script>
函数类组件需要有一个render函数编译模板,接收两个参数;h默认编译, context提供上下文参数;详情参考文档
带有h的编译函数可以看成类似react
的render
函数内写样式的规则去写样式,不需关心vdom的编写规则;
3、类写函数组件编译(createElement)
Vdom的直接实现,需要关注vdom的编写规则
通过一个展示书籍列表的完整案列来说明各个属性的使用
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AV3scj0w-1647146964346)(/media/editor/vdom编译_20220301193903540753.png “效果分析展示”)]
export default {
props: {
list: {
type: Array,
required: true
}
},
//标记为函数式组件
functional: true,
// 内部功能方法
hoverli: function(e, i) {
console.log(e, i)
},
//render函数 (createElement, context)
render: function(createElement, { props, listeners, children, data }) {
// 若不理解可以打印出来context来看看里面都有些什么东西
// B: 规定组件的渲染规则
function appropriateListComp() {
//获取父组件传来的数据
var list = props.list;
//若空,则返回前面定义的emptylist
if (list.length === 0) return { template: '<p>Empty list</p>' };
//若为对象
if (typeof list[0] === 'object') return 'ul';
//其他
return 'ul'
}
// C:
function getChlidren() {
let i = 0,
books = [];
while (i < props.list.length) {
let index = i;
books.push(createElement('li', {
attrs: {
class: 'li-name'
},
style: {
fontSize: '20px'
},
on: {
click: () => data.attrs.itemClick(props.list[index]),
// mouseover: (e)=> console.log(props.list[index])
}
},
[createElement('span', { attrs: { class: 'li-span' } }, [createElement('i', { style: { marginRight: '20px' } }, props.list[i]), createElement('strong', '金庸')])] // 第三个参数如果是Vdom那必须是数组的形式
));
i++;
}
books.unshift(children) // 追加slot元素位置
return books;
}
// A: 生成模板
/**
* 1.标签名
* 2.标签属性配置
* 3.标签子集,可以是数组或单个 Vdom
*/
return createElement(
// 模板标记为渲染规则函数返回值
appropriateListComp(), {
attrs: {
id: 'book-ul'
},
'class': {
foo: true,
bar: false
},
},
// 模板子元素,返回一个数组
getChlidren(),
)
},
}
- render函数要返回一个编译的Vdom,
return createElement(父类标签,父类样式以及属性、子类标签以及内容文本)
参数简介 - 以上案列可以看出,第三个参数如有使用必须是数组形式的数组且元素是符合
createElement
函数返回的Vdom;
注册组件
Vue.component('function-list', 函数组件)
使用组件
<function-list :list='list' :itemClick="booklog"><li>书籍列表 <span>class createElement编译</span> </li></function-list>
原文信息
原文转载自:问我学院,问我社区
原文链接:http://www.wenwoha.com/blog_detail-1376.html
开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!
更多推荐
所有评论(0)