前端笔记之vue3 之 render函数和createVNode函数使用

初学vue3的时候倒是扒了一点点源码,似是而非,而且一直做的工作都是很简单的功能,怎么说呢,ui框架也几乎让我很容易的就可以写出一个成型的页面,有时就忘了初学的时候的一些心得。
本内容只说createVNode函数的用法,不做源码探究

1.简单使用-创建一个组件

<template>
<RenderTest></RenderTest>
</template>
<script setup>
import { defineComponent, createVNode } from "vue";

const RenderTest = defineComponent({
  render(){
  // 参数1:元素名字符串; 参数2:元素属性; 元素子节点,支持createVNode嵌套
    return createVNode("div", {class: "text"}, "render-text")
  }
});
</script>

效果图:
在这里插入图片描述

2.简单使用-渲染组件

虽然在日常中这么写特别鸡肋,甚至有些傻逼,但是别急,慢慢来。
先写一个简单要引用的子组件

<template>
  <div>{{title}}</div>
</template>

<script setup lang="ts" name="SimpleTemplate">
import {defineProps} from "vue";
defineProps<{title: string}>();
</script>

父组件

<template>
  <SimpleTemplateCopy />
</template>

<script setup>
import { defineComponent, createVNode } from "vue";
import SimpleTemplate from "./SimpleTemplate/index.vue";

const SimpleTemplateCopy = defineComponent({
  render(){
    return createVNode(SimpleTemplate, {title: "twoB"})
  }
})
</script>

3.日常使用-我用到它们的地方

element-plus说实话很不错,但是太常使用它有些审美疲劳,但是它的一些组件确实很好用,特别是那些提示弹窗之类,发现了吗,它们都是在函数去调用的,那么如何在纯js中去使用一个已经封装好了的组件呢?反正我是用它们。
简单的实现一下吧。
手写先写一个confirm的组件

<template>
<div class="small-window">
  <div class="upper-tip">
    <span>{{ title }}</span>
  </div>
  <div class="message-content">
    {{ message }}
  </div>
  <div class="button-area">

    <div class="my-button" style="background-color: #11a9ea" @click="submitCallBack">{{ submitText }}</div>
    <div class="my-button" style="background-color: #cecece" @click="cancelCallBack">{{ cancelText }}</div>
  </div>
</div>
</template>

<script setup lang="ts" name="Confirm">
import {defineProps} from "vue";
defineProps<{
  title: {type: string, default: "提示"},
  message: string,
  submitText: string,
  cancelText: string,
  cancelCallBack: () => void,
  submitCallBack: () => void,

}>()
</script>

<style scoped lang="less">
.small-window{
  width: 500px;
  height: 350px;
  background-color: white;
  border: 1px solid rgba(169, 169, 169, 0.92);
  border-radius: 15px;
  display: flex;
  flex-direction: column;

  .upper-tip{
    font-size: 18px;
    height: 45px;
    width: 100%;
    font-weight: 700;
  }
  .message-content{
    width: calc(100% - 40px);
    padding: 15px 20px 15px 20px;
    height: 150px;
    text-indent: 32px;
    display: flex;
    justify-content: center;
    font-size: 16px;
  }
  .button-area{
    display: flex;
    justify-content: end;
    width: calc(100% - 40px);
    padding: 15px 20px 15px 20px;

    .my-button{
      width: 68px;
      margin-left: 20px;
      height: 50px;
      cursor: pointer;
    }
  }
}
</style>

然后给这个组件找个挂载点以及render到dom上

import {createVNode, render} from "vue";
import Confirm from "./Confirm.vue";


export default ({title, message, submitText, cancelText}) => {

    const mask = document.createElement('div');
   	mask.setAttribute('style', 'position: fixed; background-color: rgba(0, 0, 0, 0.5); width: 100vw; height: 100%; display: flex; justify-content: center; align-items: center');
	mask.setAttribute('key', Date.now().toString());
    document.body.appendChild(mask);
    return new Promise((reslove, reject) => {

        // 封装组件属性方法
        const submitCallBack = () => {
            console.log(456)
            //调用完毕后应该清空节点
            render(null, mask)
            mask.remove();
            reslove(true)
        }

        // 封装组件属性方法
        const cancelCallBack= () => {
            console.log(456)
            //清空节点
            render(null, mask);
            mask.remove();
            reject()
        };

        // 在此处才创建节点并挂载属性
        const VNode = createVNode(Confirm, {
            title,
            message,
            submitText,
            cancelText,
            cancelCallBack,
            submitCallBack
        })
        render(VNode, mask);
    });
};

然后使用它

<template>

  <button @click="openMyConfirm">12313213</button>
</template>

<script setup>


import myConfirm from "./Confirm/index.js"


const openMyConfirm = () => {
  myConfirm({title: "提示", message: "你好呀", submitText: "你好", cancelText: "我不好"}).then(() => {
    console.log('点击确认事件处理')
  }).catch(e => {
    console.log('点击取消事件处理')
  })
}
</script>

效果图:很丑,但是起码他是个成熟的confirm了
在这里插入图片描述

4.生产中的正常使用

贴一个简单的tsx的代码,说实话tsx搭配createVNode简直舒服极了

import {createVNode, defineComponent, render} from "vue";
import styles from "./errordatacord.module.less";
interface A {
  unusualField: string,
  resultValue: string,
  healthRecordNo: string,
  name: string,
}
interface Prop extends A{
  cancelCallBack: () => void
}

const errorDataCord = defineComponent<Prop>({
  name: "ErrorDataCord",
  setup(props, {attrs}){
    return ()=> <>
      <div class={styles["error-data-cord"]}>
        <div class={styles["upper-sidebar"]}>
          <span>异常结果值</span>
          <div
            class={styles["close-icon"]}
            onClick = { attrs.cancelCallBack as () => void }
          >×</div>
        </div>
        <div class={styles["main-content"]}>
          <div>
            <span>异常字段:{attrs.unusualField}</span>
            <span>异常结果值:{attrs.resultValue}</span>
          </div>
          <div>
            <svg viewBox="0 0 1024 1024" version="1.1"
                 xmlns="http://www.w3.org/2000/svg" p-id="1486" width="48" height="48">
              <path
                d="M511.903244 0.000096a511.903244 511.903244 0 0 1 335.957502 898.350359l-9.598786 8.638907A511.999232 511.999232 0 1 1 511.903244 0.000096z m0 742.274102A281.436398 281.436398 0 0 0 272.605515 875.409357a433.289189 433.289189 0 0 0 225.283502 71.510954h14.014227a433.097213 433.097213 0 0 0 239.393717-71.510954 281.628374 281.628374 0 0 0-239.393717-133.135159z m0-665.483816a435.112958 435.112958 0 0 0-299.674091 750.625046 358.322672 358.322672 0 0 1 599.44417 0A435.112958 435.112958 0 0 0 511.903244 76.790382z m0 127.951814A204.838088 204.838088 0 1 1 307.161144 409.484296a204.7421 204.7421 0 0 1 204.7421-204.7421z m0 76.790286a128.047802 128.047802 0 0 0 0 255.999616 128.047802 128.047802 0 0 0 0-255.999616z"
                p-id="1487" fill="#cdcdcd"></path>
            </svg>
            <span>{attrs.name}</span>
            <span>{attrs.healthRecordNo}</span>
          </div>
        </div>
      </div>
    </>;
  }
});

export default (option: A, htmlElement: HTMLElement) => {
  return new Promise((resolve) => {
    const cancelCallBack = () => {
      render(null, htmlElement);
    };
    const VNode = createVNode(errorDataCord,  {
      ...option,
      cancelCallBack
    });
    render(VNode, htmlElement);
    resolve(true);
  });
};

  • 8
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
以下是使用Vue3和Ant Design Vue进行表单验证的示例: ```vue <template> <a-form :form="form" @finish="handleSubmit"> <a-form-item label="名称" name="name" :rules="nameRules"> <a-input v-model="form.name" /> </a-form-item> <a-form-item label="对比项" name="compare" :rules="compareRules"> <a-input v-model="form.compare" /> </a-form-item> <a-form-item label="备注" name="remark" :rules="remarkRules"> <a-input v-model="form.remark" /> </a-form-item> <a-button type="primary" html-type="submit">提交</a-button> </a-form> </template> <script> import { defineComponent, ref } from 'vue'; import { Form, Input, Button } from 'ant-design-vue'; export default defineComponent({ components: { 'a-form': Form, 'a-form-item': Form.Item, 'a-input': Input, 'a-button': Button, }, setup() { const form = ref(null); const nameRules = [ { required: true, message: '名称不能为空' }, ]; const compareRules = [ { required: true, message: '对比项不能为空' }, ]; const remarkRules = [ { required: true, message: '备注不能为空' }, ]; const handleSubmit = () => { form.value.validate((valid) => { if (valid) { // 表单验证通过,执行提交操作 console.log('表单验证通过'); } else { console.log('表单验证失败'); } }); }; return { form, nameRules, compareRules, remarkRules, handleSubmit, }; }, }); </script> ``` 这个示例中,我们使用Vue3的`defineComponent`和`ref`函数来定义组件和创建响应式数据。我们还引入了Ant Design Vue的表单组件,包括`Form`、`FormItem`、`Input`和`Button`。 在模板中,我们使用`a-form`组件来创建表单,并将表单对象绑定到`form`变量上。每个表单项都使用`a-form-item`组件包裹,并设置相应的`name`和`rules`属性来进行验证。当点击提交按钮时,我们调用`handleSubmit`方法来进行表单验证,如果验证通过,则执行提交操作。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值