JavaScript之实现一个简单的Vue

vue的使用相信大家都很熟练了,使用起来简单。但是大部分人不知道其内部的原理是怎么样的,今天我们就来一起实现一个简单的vue。

Object.defineProperty()

实现之前我们得先看一下Object.defineProperty的实现,因为vue主要是通过数据劫持来实现的,通过get、set来完成数据的读取和更新。

var obj = {name:‘wclimb‘}
var age = 24
Object.defineProperty(obj,‘age‘,{
enumerable: true, // 可枚举
configurable: false, // 不能再define
get () {
return age
},
set (newVal) {
console.log(‘我改变了‘,age +‘ -> ‘+newVal);
age = newVal
}
})

> obj.age
> 24

> obj.age = 25;
> 我改变了 24 -> 25
> 25
从上面可以看到通过get获取数据,通过set监听到数据变化执行相应操作,还是不明白的话可以去看看Object.defineProperty文档。

流程图

图片描述(最多50字)

html代码结构

<div id="wrap">
<p v-html="test"></p>
<input type="text" v-model="form">
<input type="text" v-model="form">
<button @click="changeValue">改变值</button>
{{form}}
</div>
js调用

JavaScript
new Vue({
el: ‘#wrap‘,
data:{
form: ‘这是form的值‘,
test: ‘<strong>我是粗体</strong>‘,
},
methods:{
changeValue(){
console.log(this.form)
this.form = ‘值被我改变了,气不气?‘
}
}
})
Vue结构

class Vue{
    constructor(){}
    proxyData(){}
    observer(){}
    compile(){}
    compileText(){}
}
class Watcher{
    constructor(){}
    update(){}
}

Vue constructor 构造函数主要是数据的初始化
proxyData 数据代理
observer 劫持监听所有数据
compile 解析dom
compileText 解析dom里处理纯双花括号的操作
Watcher 更新视图操作
Vue constructor 初始化

class Vue{
    constructor(options = {}){
        this.$el = document.querySelector(options.el);
        let data = this.data = options.data;
        // 代理data,使其能直接this.xxx的方式访问data,正常的话需要this.data.xxx
        Object.keys(data).forEach((key)=&gt; {
            this.proxyData(key);
        });
        this.methods = obj.methods // 事件方法
        this.watcherTask = {}; // 需要监听的任务列表
        this.observer(data); // 初始化劫持监听所有数据
        this.compile(this.$el); // 解析dom
    }
}

上面主要是初始化操作,针对传过来的数据进行处理

proxyData 代理data

class Vue{
constructor(options = {}){
......
}
proxyData(key){
let that = this;
Object.defineProperty(that, key, {
configurable: false,
enumerable: true,
get () {
return that.data[key];
},
set (newVal) {
that.data[key] = newVal;
}
});
}
}

上面主要是代理data到最上层,this.xxx的方式直接访问data

observer 劫持监听

class Vue{
constructor(options = {}){
......
}
proxyData(key){
......
}
observer(data){
let that = this
Object.keys(data).forEach(key=>{
let value = data[key]
this.watcherTask[key] = []
Object.defineProperty(data,key,{
configurable: false,
enumerable: true,
get(){
return value
},
set(newValue){
if(newValue !== value){
value = newValue
that.watcherTask[key].forEach(task => {
task.update()
})
}
}
})
})
}
}
同样是使用Object.defineProperty来监听数据,初始化需要订阅的数据。

把需要订阅的数据到push到watcherTask里,等到时候需要更新的时候就可以批量更新数据了。

原文地址:http://blog.51cto.com/13917525/2176164

时间: 2024-10-28 10:00:08

JavaScript之实现一个简单的Vue的相关文章

理解vue实现原理,实现一个简单的Vue框架

参考: 剖析Vue实现原理 - 如何实现双向绑定mvvm Vue.js源码(1):Hello World的背后 Vue.js官方工程 本文所有代码可以在git上找到. 其实对JS我研究不是太深,用过很多次,但只是实现功能就算了.最近JS实在是太火,从前端到后端,应用越来越广泛,各种框架层出不穷,忍不住也想赶一下潮流. Vue是近年出的一个前端构建数据驱动的web界面的库,主要的特色是响应式的数据绑定,区别于以往的命令式用法.也就是在var a=1;的过程中,拦截'='的过程,从而实现更新数据,w

原生javascript实现的一个简单动画

本文章向大家介绍一个javascript实现的动画.点击开始按钮div会往右移动,点击停止后,div停止移动,再点击则继续移动.请看下面代码. <!DOCTYPE html> <html> <head> <meta charset=" utf-8"> <head> <title>javascript实现的简单动画</title> <style type="text/css"&g

教你撸一个简单的Vue自定义动态组件

components下创建 toast 文件夹, 文件夹里面创建 toast.vue 和 index.js toast.vue: <template> <div id="toastWrap" :class="[className,showAnimation ?'fadein':'fadeout',appointId==''?'fixed':'absolute']" v-if="show"> <span :class=

一个简单的vue小例子之倒计时

<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <script src="http://g.tbcdn.cn/mtb/lib-flexible/0.3.4/??flexible_css.js,flexible.js"></script> <title>测试</title> <

命令行创建一个简单的vue项目过程

//计算机已安装好node和git环境 sudo npm install -g cnpm --registry=https://registry.npm.taobao.org //Mac环境下全局安装cnpm cnpm -v //查看cnmp版本号 ls //查看当前目录 cd //进入根目录 cd git //进入git文件夹 cd VUE //进入VUE文件夹 ls //查看当前目录,显示为VUE文件夹内容 vue init webpack vue-project //在当前目录下创建名为v

记录一个简单的vue页面实现

<template> <div class="userView"> <!-- 页眉颜色统一 --> <div class="buttonTop"></div> <div class="main"> <!--工具栏--> <div class="center" style="overflow: hidden;">

初学javascript,写一个简单的阶乘算法当作练习

代码如下: <script> var a = prompt("请输入值"); function mul(a){ if(a==1){ return 1; } return a*mul(a-1); } document.write(mul(a)); </script> 执行: 原文地址:https://www.cnblogs.com/raonet/p/10339704.html

写一个简单vue 中间件,$emit、$on

前言 使用过vue的同学大多数都知道$emit 与$on的使用.我们仅仅知道使用,有时候是完全不够的.现在我就带领大家写一个简单类似于vue空实例的中间件. 非父子组件的通信 非父子组件的通信vue官网给出这样的解决方案. 有时候,非父子关系的两个组件之间也需要通信.在简单的场景下,可以使用一个空的 Vue 实例作为事件总线: var bus = new Vue() // 触发组件 A 中的事件 bus.$emit('id-selected', 1) // 在组件 B 创建的钩子中监听事件 bu

使用VSCode配置简单的vue项目

由于最近要使用的项目框架为前后端分离的,采用的是vue.js+webAPI的形式进行开发的.因为之前我没有接触过vue.js,也只是通过视频文档做了一些简单的练习.今天技术主管说让大家熟悉下VSCode开发vue,所以自己摸索了好久,才算是把简单的项目配置成功了.后续还得自己多了解这方面的知识.想着怕时间长了自己会忘记,所以写下来也供有需要的人一起学习. 一.配置环境 1.1 下载VSCode,官网直接下载就行. 1.2 汉化VSCode Ctrl+Shift+P 输入 "configure d