当前位置: 首页 > 软件库 > Web应用开发 > Vue 组件 >

vue-toy

200 行左右代码模拟 vue 实现
授权协议 MIT
开发语言 TypeScript
所属分类 Web应用开发、 Vue 组件
软件类型 开源软件
地区 国产
投 递 者 澹台鸿熙
操作系统 跨平台
开源组织
适用人群 未知
 软件概览

vue-toy

npm install --save vue-toy

200行左右代码模拟vue实现。

Vue(options)

interface Options {
    el: HTMLElement | string;
	propsData?: Record<string, any>;
	props?: string[];
	name?: string;
	data?: () => Record<string, any>;
	methods?: Record<string, (e: Event) => void>;
	computed?: Record<string, () => any>;
	watch?: Record<string, (newValue: any, oldValue: any) => any>;
	render: (h: typeof React.createElement) => React.ReactNode;
	renderError?: (h: typeof React.createElement, error: Error) => React.ReactNode;
	mounted?: () => void;
	updated?: () => void;
	destroyed?: () => void;
	errorCaptured?: (e: Error, vm: React.ReactInstance) => void;
}

示例:

import Vue from "vue-toy";

new Vue({
  el: document.getElementById("root"),
  data() {
    return {
      msg: "hello vue toy"
    };
  },
  render(h) {
    return h("h1", null, this.msg);
  }
});

注1vue-toy不包含template的编译实现,因为vue的template最终是编译成类似代码:

render(h) {
    with(this){
        return h("h1", null, msg);
    }
}

本教程中使用了严格模式无法使用with,所以在render里无法省略this

注2vue-toy的视图渲染使用的react,所以render方法的使用同react#render,如:

import Vue from "vue-toy";
import React from "react";

new Vue({
  el: document.getElementById("root"),
  data() {
    return {
      msg: "hello vue toy"
    };
  },
  render() {
    return <h1>{this.msg}</h1>
  }
});

全局 API

Vue.component(ComponentOptions)

interface ComponentOptions {
	props?: string[];
	name?: string;
	data?: () => Record<string, any>;
	methods?: Record<string, (e: Event) => void>;
	computed?: Record<string, () => any>;
	watch?: Record<string, (newValue: any, oldValue: any) => any>;
	render: (h: typeof React.createElement) => React.ReactNode;
	renderError?: (h: typeof React.createElement, error: Error) => React.ReactNode;
	mounted?: () => void;
	updated?: () => void;
	destroyed?: () => void;
	errorCaptured?: (e: Error, vm: React.ReactInstance) => void;
}

示例:

const Hello = Vue.component({
    props: ["msg"],
    render(h){
        return h('div', null, this.msg);
    }
});
export default Hello;

基本原理

// 创建观察对象
// 观察对象主要使用的是Object.defineProperty或Proxy来实现,
// 也可使用类似angular.js的脏检测(不过需要额外的检测调用),
// 如果不在意写法也可以参考knockout或 setXXX getXXX的方式
const data = observable({
    name: 'vue-toy',
});

// 渲染模版
const render = function(){
    return <h1>{data.name}</h1>
}

// 计算render的依赖属性,
// 依赖属性改变时,会重新计算computedFn,并执行监控函数watchFn,
// 属性依赖计算使用栈及可以了。
// watch(computedFn, watchFn);
watch(render, function(newVNode, oldVNode){
    update(newVNode, mountNode);
});

//初始渲染
mount(render(), mountNode);

// 改变观察对象属性,如果render依赖了该属性,则会重新渲染
data.name = 'hello vue toy';

视图渲染部分(既render)使用的是vdom技术,vue2+使用Snabbdom库,vue-toy使用的是react来进行渲染,所以在render函数里你可以直接使用React的JSX语法,不过别忘记import React from 'react',当然也可以使用preact inferno 等 vdom库。

由于vue的template的最终也是解析并生成render函数,模版的解析可用htmleParser库来生成AST,剩下就是解析指令并生产代码,由于工作量大,这里就不具体实现,直接使用jsx。

  • 一、相关资源 vue-i18n官网,csdn上一个可以练手的项目,这里是github地址,还有博客园上一个写的不错的文章。不过看这两篇文章最后先学过element-ui。 vue-i18n是一个前端国际化的工具,github地址。 兼容vue2.00+。 二、实现国际化 1、安装 $ npm i vue-i18n -D 2、在main.js中将vue-i18n注入到vue实例中 import Vu

  • vue-router 默认 hash 模式 —— 使用 URL 的 hash 来模拟一个完整的 URL,于是当 URL 改变时,页面不会重新加载。 如果不想要很丑的 hash,我们可以用路由的 history 模式,这种模式充分利用 history.pushState API 来完成 URL 跳转而无须重新加载页面。 const router = new VueRouter({ mode: '

  • 可以使用以下步骤来实现一个简单的 Vue 应用: 在 HTML 中引入 Vue 的脚本文件,如: <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>

  • draw 项目地址:github 个人博客:smilestation.info 类似drawio效果,本项目采用前后端分离模式开发 前台采用 vue + element 后端采用 nodejs 数据库采用 MySQL 文件夹说明 server 后端文件夹 client 前端文件夹 主要内容说明: 实线箭头 drawArrow (Object) ctx: context对象 fromX: 开始点x坐

  • 目录 一、简介 二、引入 三、使用 四、嵌套(多级)路由 五、命名路由(name属性) 六、路由传递参数 1、路由传参数(query参数) 2、路由传参数(params参数) 七、路由的props配置 1、路由中props第一种写法(对象类型):(没啥用) 2、路由中的props第二中写法(布尔类型):(配合params参数,path中不用再标识params参数占位符) 3、路由中的第三种写法(函

  • Vue学习--------router和router懒加载 首先在router文件夹下面的index.js中导入vue-router import { createRouter, createWebHistory } from 'vue-router' 之后创建router const router = createRouter({ history: createWebHistory(p

  • 代码根目录 .env文件打包时会被读取 其中允许的值有三种 // .env NODE_ENV=不推荐修改,vue-cli打包时会根据运行serve还是build修改这个值为development还是production BASE_URL=/ 默认值是"/",会根据vue.config.js中配置的publicPath中配置的值而改变 VUE_APP_*="*"可以是任何字符,前缀VUE_APP_不

 相关资料
  • 本文向大家介绍vue中实现拖动调整左右两侧div的宽度的示例代码,包括了vue中实现拖动调整左右两侧div的宽度的示例代码的使用技巧和注意事项,需要的朋友参考一下 写在最前 最近在使用vue的时候,遇到一个需求,实现左右div可通过中间部分拖拽调整宽度,类似于这样 这是我最终的实现效果 还是老话,因为我不是专业的前端工程师,只是兼职写一些简单的前端,所以这个功能的实现得益于以下博客,《vue 拖动

  • 本文向大家介绍vue+swiper实现左右滑动的测试题功能,包括了vue+swiper实现左右滑动的测试题功能的使用技巧和注意事项,需要的朋友参考一下 最近在做一个测试题,前后可以切换题目,点击按钮选择答案,选择答案的同时改变按钮的背景色,如下图所示: 初始代码 我用了vue和swiper。所有的题目是一个对象数组,通过v-for渲染: 一开始我把每道题目的answer存放在对象里面,点击的按钮时

  • 本文向大家介绍Vue实战之vue登录验证的实现代码,包括了Vue实战之vue登录验证的实现代码的使用技巧和注意事项,需要的朋友参考一下 最近一直在撸一个给大学生新生用的产品,在撸的时候有时候会发现自己力不从心,是不是我的能力下降,是不是我该放弃我的最热爱的事业了?这对我的心灵造成了巨大的伤害,所以我决定向苍老师起誓一定练好我这双手——好好写代码(想多的同学赶紧去面壁5秒钟再过来往下看)~~~ 我做

  • 问题内容: 我正在使用Selenium编写一些UI测试,并且使用Dojo工具箱具有一个JavaScript Tree控件。 我已经使用Dojo提供的示例为树的每个节点实现了一个上下文菜单,但是我需要Selenium测试来“调用”树节点上的右键,但是我无法使其正常工作。这些测试根本不会通过JavaScript模拟右键单击事件,并且不会显示上下文菜单。 是否有人在使用Dojo和Selenium调用上下

  • 本文向大家介绍Vue表单实例代码,包括了Vue表单实例代码的使用技巧和注意事项,需要的朋友参考一下 什么是 Vue.js? Vue.js 是用于构建交互式的 Web 界面的库。 Vue.js 提供了 MVVM 数据绑定和一个可组合的组件系统,具有简单、灵活的 API。 Vue.js 特点 简洁: HTML 模板 + JSON 数据,再创建一个 Vue 实例,就这么简单。 数据驱动: 自动追踪依赖的

  • 本文向大家介绍Vue数据驱动模拟实现1,包括了Vue数据驱动模拟实现1的使用技巧和注意事项,需要的朋友参考一下 一、前言 Vue有一核心就是数据驱动(Data Driven),允许我们采用简洁的模板语法来声明式的将数据渲染进DOM,且数据与DOM是绑定在一起的,这样当我们改变Vue实例的数据时,对应的DOM元素也就会改变了。 如下: 当我们在chrome控制台,更改vm.name时,页面中的数据也

  • 本文向大家介绍Vue数据驱动模拟实现3,包括了Vue数据驱动模拟实现3的使用技巧和注意事项,需要的朋友参考一下 一、前言 在"模拟Vue之数据驱动2"中,我们实现了个Observer构造函数,通过它可以达到监听已有数据data中的所有属性。 但,倘若我们想在某个对象中,新增某个属性呢? 如下: 那么岂不是,新增的infor属性,以及它的对象属性,没有得到监听。 此时,应该怎么处理呢? 通过走读Vu

  • 本文向大家介绍Vue数据驱动模拟实现4,包括了Vue数据驱动模拟实现4的使用技巧和注意事项,需要的朋友参考一下 一、前言 在"模拟Vue之数据驱动3"中,我们实现了为每个对象扩展一个$set方法,用于新增属性使用,这样就可以监听新增的属性了。 当然,数组也是对象,也可以通过$set方法实现新增属性。 但是,对于数组而言,通常我们是通过push之类的方法吧。 PS:Vue中明确指出push、pop、