前言
最近遇到一个项目,是对element-ui进行了二次封装,做了一些自己的组件库,其中很多实现都是render函数配合template模板实现的,还有就是表单这块是一块比较复杂的业务逻辑,里面用到了jsx语法,我也抽时间研究了jsx在vue中怎么使用,所以记录下自己写的demo,后面好进行查漏补缺。
demo的主要结构如下
# Hello.vue
<script>
export default {
name: "Hello",
data() {
return {
str: "hello组件",
};
},
props: {
address: {
type: String,
default() {
return "这是地址";
},
},
},
render() {
return (
<div>
<span>{this.str}</span>
<h1>具名插槽</h1>
{/* 相当于声明了一个test的具名插槽 */}
{this.$slots.test}
<h1>作用域插槽</h1>
{/* 相当于声明了一个person的具名插槽,并传值,即作用域插槽 */}
{this.$scopedSlots.person({ name: 'john', age: 65 })}
</div>
);
},
};
</script>
<style scoped></style>
复制代码
# world.js
export default {
data() {
return {
msg: "world组件",
detail: {
address: "杭州",
salary: "10k",
},
};
},
/* eslint-disable */
render() {
return (
<div>
<div>{this.msg}</div>
<div>{this.$slots.demo}</div>
<div>{this.$scopedSlots.data(this.detail)}</div>
</div>
);
},
};
复制代码
# demo.js
export default {
props: {
value: {
type: Object,
default() {
return {};
},
},
},
data() {
return {
msg: "demo2",
};
},
render() {
const { msg, value } = this;
return (
<div>
<input type="text" v-model={msg} />
<input type="text" v-model={value.name} />
<input type="text" v-model={value.address} />
</div>
);
},
};
复制代码
<!--<template>
<div id="app">
<div>{{ myProp }}</div>
<slot>默认插槽</slot>
<slot name="otherSlot" v-bind:msg="msg">其他插槽</slot>
<div ref="hahaha" v-if="isShow">{{ msg }}</div>
<div>
<button @click="change">点击</button>
</div>
<Hello>
<template v-slot:test>
<div>插槽</div>
<div>插槽</div>
</template>
<template v-slot:person="{ name, age }">
我叫{{ name }},今年{{ age }}岁
</template>
</Hello>
<world>
<template v-slot:demo> 这是world中的demo </template>
<template v-slot:data="detail">
{{ detail.address }}
{{ detail.salary }}
</template>
</world>
</div>
</template>-->
<script>
import Hello from "./components/Hello";
import World from "./components/world";
import Demo from "./components/demo";
export default {
name: "App",
components: { Hello, World, Demo },
props: {
myProp: {
type: String,
},
},
data() {
return {
isShow: false,
msg: "what this is",
$str: "这是以$符开头的key",
demo2: {
name: "demo",
address: "demo2 address",
},
};
},
created() {},
methods: {
test() {
console.log("this is test method");
},
change() {
this.isShow = true;
this.msg = "值被我改变了";
},
},
render() {
const { msg, isShow, demo2 } = this;
return (
<div id="app">
<div>{msg}</div> <br />
<slot>默认插槽</slot>
<slot name="otherSlot" msg={msg}>
其他插槽
</slot>
{/* jsx中没有v-if和v-for,但是可以通过三元表达式和map实现,具体可以看vue文档 */}
{isShow ? <div>{msg}</div> : <div>show false</div>}
<div>
{/* 如果没有从this中结构出来,就必须指定this */}
<button onClick={this.change}>点击</button>
</div>
{/* 子组件中如果声明了插槽,在jsx中必须这么使用 */}
<Hello
slots={{
test: () => {
return <div>test插槽</div>;
},
}}
scopedSlots={{
person: (props) => {
return (
<div>
我叫{props.name},今年{props.age}岁
</div>
);
},
}}
/>
<world
slots={{
demo: () => {
return <div>这是world中的demo</div>;
},
}}
// 这里也可以结构赋值使用,具体可以看vue文档
scopedSlots={{
data: ({ address, salary }) => {
return (
<div>
{address}
{salary}
</div>
);
},
}}
/>
{/* 测试v-mode双向绑定 */}
<demo v-model={demo2} />
</div>
);
},
};
</script>
<style>
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
</style>
复制代码
注意点:
例子:
# ES6
render() {
return (
<div>
<div>{this.msg}</div>
<div>{this.$slots.demo}</div>
<div>{this.$scopedSlots.data(this.detail)}</div>
</div>
);
},
# ES5
render: function(h) {
return (
<div>
<div>{this.msg}</div>
<div>{this.$slots.demo}</div>
<div>{this.$scopedSlots.data(this.detail)}</div>
</div>
);
},
# 或者
render: function() {
const h = this.$createElement
return (
<div>
<div>{this.msg}</div>
<div>{this.$slots.demo}</div>
<div>{this.$scopedSlots.data(this.detail)}</div>
</div>
);
},
复制代码
本文系转载,前往查看
如有侵权,请联系 cloudcommunity@tencent.com 删除。
本文系转载,前往查看
如有侵权,请联系 cloudcommunity@tencent.com 删除。