总论
- tsx setup里面定义了return dom 元素,则options api的 render函数不生效
- options 的render函数生效前提是setup里面不能return dom
- options 的render里面不能使用this,只能使用ctx,且setup得返回数据,ctx才能访问到相应数据
- tsx一般最好用defineComponent包裹,这样响应式才能生效
- tsx dom语法 使用{} 渲染变量, 使用onClick等直接触发事件,.value 访问ref数据
- tsx 放在setup return 则需要返回的是一个函数,函数里面放tsx
代码测试
- 父组件
<template>
<div class="component-name">
<child :render="render" :params1="abc" />
</div>
</template>
<script setup lang="ts">
import { ref, reactive, computed, onMounted, nextTick } from 'vue';
import child from './components/child';
import { ElInput } from 'element-plus';
const abc = ref('sdlfkjsdfj');
const render = (h) => {
const text = ref('');
return h('input', {
type: 'text',
modelValue: text.value, // 使用modelValue 而不是value传递输入框的值
onInput: (e) => {
text.value = e.target.value; // 更新 text.value
}
});
};
setTimeout(() => {
abc.value = '中文';
}, 3000);
</script>
<style lang="scss" scoped></style>
- 子组件使用方式1
import { defineComponent, PropType, h, computed } from 'vue';
export default defineComponent({
name: 'PageF',
props: {
render: Function as PropType<(...args: any) => any>,
params1: String as PropType<string>
},
setup(props) {
const { render } = props;
const param1 = computed(() => props.params1);
console.log(param1.value, 'param1');
return () => {
return render && render(h);
};
}
});
- 子组件使用方式2
import { defineComponent, PropType, h, computed } from 'vue';
export default defineComponent({
name: 'PageF',
props: {
render: Function as PropType<(...args: any) => any>,
params1: String as PropType<string>
},
setup(props) {
const { render } = props;
const param0 = computed(() => props.params1); //这样可以监听到props.params1 外面数据的变化
const param1 = ref(props.params1); //这样是内部单独建立一份ref,props外部改变,不影响该数据
console.log(param1, 'param1');
//不能监听到
watch(param1, () => {
console.log(param1.value, 'param1_change');
});
//可以监听到
watch(param0, () => {
console.log(param0.value, 'param0_change');
});
return () => {
return render && render(h);
};
}
});
- 使用方式3
import { defineComponent, PropType, h, computed } from 'vue';
export default defineComponent({
name: 'PageF',
props: {
render: Function as PropType<(...args: any) => any>,
params1: String as PropType<string>
},
setup(props) {
const { render } = props;
const param0 = computed(() => props.params1); //这样可以监听到props.params1 外面数据的变化
const param1 = ref(props.params1); //这样是内部单独建立一份ref,props外部改变,不影响该数据
console.log(param1, 'param1');
//不能监听到
watch(param1, () => {
console.log(param1.value, 'param1_change');
});
//可以监听到
watch(param0, () => {
console.log(param0.value, 'param0_change');
});
// return (<div>slkfsjfdksd</div>) 这样不能渲染dom,需要返回函数,函数里面再放dom
return () => <div>sdlfkjsfkjsd</div>;
}
});
- 使用方式4
import { defineComponent, PropType, h, computed } from 'vue';
export default defineComponent({
name: 'PageF',
props: {
render: Function as PropType<(...args: any) => any>,
params1: String as PropType<string>
},
setup(props) {
const { render } = props;
const param0 = computed(() => props.params1); //这样可以监听到props.params1 外面数据的变化
const param1 = ref(props.params1); //这样是内部单独建立一份ref,props外部改变,不影响该数据
console.log(param1, 'param1');
//不能监听到
watch(param1, () => {
console.log(param1.value, 'param1_change');
});
//可以监听到
watch(param0, () => {
console.log(param0.value, 'param0_change');
});
// return (<div>slkfsjfdksd</div>) 这样不能渲染dom,需要返回函数,函数里面再放dom
// return () => <div>sdlfkjsfkjsd</div>;
},
//这个render函数能够运行的前提是 setup里面不返回return dom
render: (ctx, no, props) => {
console.log(ctx, 'ctx');
console.log(no, 'nonsdjflsjdf');
console.log(props, 'props');
// return <div>23424342</div>;
return h('div', {}, 'sdlkfjsldfjsldfjsl');
}
});
- 使用方式4
import { defineComponent, PropType, h, computed } from 'vue';
export default {
name: 'PageF',
props: {
render: Function as PropType<(...args: any) => any>,
params1: String as PropType<string>
},
setup(props) {
const { render } = props;
const param0 = computed(() => props.params1); //这样可以监听到props.params1 外面数据的变化
const param1 = ref(props.params1); //这样是内部单独建立一份ref,props外部改变,不影响该数据
console.log(param1, 'param1');
//不能监听到
watch(param1, () => {
console.log(param1.value, 'param1_change');
});
//可以监听到
watch(param0, () => {
console.log(param0.value, 'param0_change');
});
// return (<div>slkfsjfdksd</div>) 这样不能渲染dom,需要返回函数,函数里面再放dom
// return () => <div>sdlfkjsfkjsd</div>;
},
//这个render函数能够运行的前提是 setup里面不返回return dom
render: (ctx, no, props) => {
console.log(ctx, 'ctx');
console.log(no, 'nonsdjflsjdf');
console.log(props, 'props');
// return <div>23424342</div>;
return h('div', {}, 'sdlkfjsldfjsldfjsl');
}
};
- 直接函数
import { defineComponent, PropType, h, computed } from 'vue';
// 不建议这样使用,测试发现.value 无法响应式,最好还是defineComponent 里面使用
export default (props) => {
console.log(props, 'sldjfslfkjsldfjslf');
const count = ref(232342342);
function handleClick() {
console.log('slfjsf');
count.value = 475945795;
}
return (
<>
{/* 响应式无效 */}
<div>{count.value}</div>
<button onClick={handleClick}>btn</button>
</>
);
};
- 使用方式n
import { defineComponent, PropType, h, computed } from 'vue';
export default defineComponent({
setup: (props) => {
console.log(props, 'sldjfslfkjsldfjslf');
const count = ref(232342342);
function handleClick() {
console.log('slfjsf');
count.value = 475945795;
}
return () => {
return (
<>
<div>{count.value}</div>
<button onClick={handleClick}>btn</button>
</>
);
};
}
});
- this是否访问的到?
import { defineComponent, PropType, h, computed } from 'vue';
export default defineComponent({
setup: (props) => {
console.log(props, 'sldjfslfkjsldfjslf');
const count = ref(232342342);
function handleClick() {
console.log('slfjsf');
count.value = 475945795;
}
// 需要renturn ,render函数 ctx才能有 相应数据
return {
handleClick,
count
};
},
render: (ctx) => {
console.log(this, 'sklfjslfjs'); //this 直接访问不了
console.log(ctx, 'ctx_sdlfjsdlfksj');
return <div>{ctx.count}</div>;
}
});
- defineComponent 定义Props ts类型的方式
import { defineComponent, PropType, h, computed } from 'vue';
// defineComponent 定义props类型的一种方式
interface Props {
render: (...args: any[]) => any;
params1: string;
}
export default defineComponent<Props>({
name: 'PageF',
setup(props) {
const { render } = props;
const param0 = computed(() => props.params1); //这样可以监听到props.params1 外面数据的变化
const param1 = ref(props.params1); //这样是内部单独建立一份ref,props外部改变,不影响该数据
console.log(param1, 'param1');
//不能监听到
watch(param1, () => {
console.log(param1.value, 'param1_change');
});
//可以监听到
watch(param0, () => {
console.log(param0.value, 'param0_change');
});
return () => {
return render && render(h);
};
}
});
- 定义props ts类型方式2,必须与否实现
import { defineComponent, PropType, h, computed, ref, watch } from 'vue';
export default defineComponent({
name: 'PageF',
props: {
render: {
type: Function as PropType<(...args: any[]) => any>,
required: true // required定义必须
},
params1: {
type: String as PropType<string>,
default: 'default value', // 设置默认值
required: true
}
},
setup(props) {
const { render } = props;
const param0 = computed(() => props.params1); // 监听 props.params1 的变化
const param1 = ref(props.params1); // 内部独立的 ref
console.log(param1, 'param1');
// 监听 param1 的变化
watch(param1, () => {
console.log(param1.value, 'param1_change');
});
// 监听 param0 的变化
watch(param0, () => {
console.log(param0.value, 'param0_change');
});
return () => {
return render && render(h);
};
}
});
前端工程师、程序员