Vue2源码学习笔记 - 1.前置准备

本文档介绍了如何配置一个基于Vue.js 2.6.14的UMD完整版学习环境,包括通过Nginx设置本地服务器,从GitHub克隆Vue源码并创建一个简单的HTML页面来引入Vue.js。主要关注Vue目录结构中的src和dist目录,以及了解Flow类型检查工具的基础知识,为深入源码学习做准备。
摘要由CSDN通过智能技术生成

本笔记系列文章,我主要以 UMD 完整版的 Vue为主来学习,UMD 版可以通过 <script> 标签直接用在浏览器中,而完整版是同时包含编译器和运行时的版本,这样就便于我们直接修改代码打印一些调试信息和编译模板。

Vue版本:2.6.14

1.配置demo环境

为了便于学习与调试,我们新建一个简单的 demo 项目。

mkdir demo
cd demo

web 服务器使用 Nginx,并给 Nginx 配置一个 vhost 以便可以通过浏览器访问页面,我这里配置 URL 为:http://localhost/demo/index.html

访问 Vue 的 GitHub:https://github.com/vuejs/vue,在 demo 目录下 Git 拉取 Vue 的源码

git clone https://github.com/vuejs/vue.git

这样 Vue 的整个源码就放在了 demo/vue 下。然后在 demo 根目录新建一个 html 静态文件 index.html,其中直接动态引入 /vue/dist/vue.js 文件。

index.html:

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no,  maximum-scale=1">
  <title>Vue demo</title>
  <style type="text/css">
    body {margin: 0;background-color: #c8e4f1;padding: 10px;}
    #app {width: 560px;min-height: 600px;background-color: #ffffff;padding: 20px;box-sizing: border-box;box-shadow: 5px 5px 8px #adadad;position: relative;}
    .blog {position: absolute;top: 0;right: 0;margin: 5px;padding: 0;font-size: 12px;color: #aaa;}
    .cmpt-test {background-color: #dfdfdf;padding: 5px;}
    .cmpt-hello {background-color: #aaaaaa;padding: 5px;}
    .btns {margin: 20px 0 0;}
    .btns button {padding: 5px 15px;background-color: #81cff3;outline: none;border: 0;cursor: pointer;}
    .btns button:hover{background-color: #779f62;}
  </style>
  <script type="text/javascript">
    window.log = console.log;
    var js = document.createElement('script');
    js.type = 'text/javascript';
    js.src = './vue/dist/vue.js?v='+String(Date.now()).slice(6);

    js.onload = function() {
      Vue.component('Hello', {
        name: 'hello',
        template: `<div class="cmpt-hello">
        <p>Hello component</p>
        Hello: {{name}}; {{dclnet}} - code: {{code}}
        </div>`,
        data: function() {
          return {
            name: 'deng_'
          }
        },
        props: {code: String},
        computed: {
          dclnet: function() {
            return `fav: ${this.name}, you like [js,php,java,c/c++...]`;
          }
        },
        watch: {
          code: function(newVal, oldVal) {
            log(`code is change ${oldVal} => ${newVal}`);
          }
        }
      })

      Vue.component('Test', {
        name: 'test',
        template: `<div class="cmpt-test">
            <p>Test component</p>
            <Hello :code="inputText"></Hello>
            <p>my input: {{inputText}}</p>
            <input type="text" v-model="inputText"/>
          </div>`,
        data: function() {
          return {
            inputText: ''
          }
        },
        watch: {
          inputText: function(newVal, oldVal) {
            log(`inputText change ${oldVal} => ${newVal}`);
          }
        }
      })
      window.app = new Vue({
        el: '#app',
        data: {
          id: 1,
          dclnet: true,
          items: ['item1', 'item2', 'item3', 'item4', 'item5'],
          name: '',
          obj: {
            uid: 888,
            lang: 'java',
            platform: 'windows'
          }
        },
        computed: {
          fullname: function() {
            return `[${this.name}-deng_]`;
          }
        },
        watch: {
          name: function(nval, oval) {
            log('name changed: => ', nval)
          }
        },
        methods: {
          toggleShow: function() {
            this.id += 1;
            this.dclnet = !this.dclnet;
          },
          updateList: function() {
            if (this.items.length == 5) {
              this.items = ['newHead1', 'newHead2'].concat(this.items.slice(2, 4).concat(['tail1', 'tail2']))
            } else {
              this.items = ['item1', 'item2', 'item3', 'item4', 'item5'];
            }
          },
          editName: function() {
            log(this.name)
            this.name = 'new_name';
          }
        },
        beforeCreate: function() {
          log("app component beforeCreate.");
        },
        created: function() {
          log("app component created.", this.name);
        },
        beforeMount: function() {
          log("app component beforeMount.");
        },
        mounted: function() {
          log("app component mounted.");
          this.$set(this.obj, 'child1', 111);
        },
        beforeUpdate: function() {
          log("app component beforeUpdate.");
        },
        updated: function() {
          log("app component updated.");
        },
        beforeDestroy: function() {
          log("app component beforeDestroy.");
        },
        destroyed: function() {
          log("app component destroyed.");
        }
      });
    }
  </script>
</head>
<body>
  <script type="text/javascript">
    document.body.appendChild(js);
  </script>

  <div id="app">
    <h3 class="stext">Vue demo static text</h3>
    <input type="text" id="ginput" v-model="name" autocomplete="off">

    <p v-if="!dclnet" data-vid="89bc" class="tip">test v-if</p>
    <p v-show="!dclnet">test v-show.</p>

    <p key="tipkey" :class="id>1 ? 'tc': 'fc'" alt data-vid="a0bcf" id="tip" class="tip">name:{{name}} - id:{{id}} - fullname:{{fullname}}</p>

    <ul :class="'test>-'+id" class="ullist">
      <!--这是注释-->
      <li v-for="(item,index) in items" :key="index">{{item}}</li>
    </ul>

    <Test></Test>

    <div class="btns">
      <button @click="toggleShow"> test-if-show </button>
      <button @click="updateList"> update list </button>
      <button @click="editName"> edit name </button>
    </div>

    <p class="blog">https://blog.csdn.net/dclnet</p>
  </div>

</body>
</html>

2.Vue目录结构

新建好项目后,我们看到 /demo/vue 目录是如图这样的,其中我们主要是关注 src 和 dist 目录,其他目录我们可以暂时忽略。dist 目录中是已经生成好的不同功能版本的 Vue,为了便于调试与分析,我们后续章节直接在html中引用 vue.js 来学习。src 目录为 Vue 的源码目录,结构如下。

src
├── compiler        # 编译相关 
├── core            # 核心代码 
├── platforms       # 不同平台的支持
├── server          # 服务端渲染
├── sfc             # .vue 文件解析
├── shared          # 共享代码

 

compiler 为编译相关的代码;

core 包含了 Vue 的核心代码,我们后续学习的重点;

platforms 主要是平台相关的,这里我们主要关注其中的 web 平台即可;

server 服务的相关的,因为这里我们主要学习 web 相关的 Vue,服务端的一般跳过;

sfc 为解析单文件组件的功能;

shared 包含了一些全局基本的功能函数等;

3.类型检查

Vue2 没有使用 TypeScript,源码直接就是 JavaScript 代码。为了便于开发与测试,Vue 使用了 Flow 这个 Facebook 贡献的类型检查工具。它的具体使用可自行查阅其官网学习 Flow: A Static Type Checker for JavaScript。这里我们只需要简单的了解一些相关知识即可。

使用 Flow 可以在各种需要定义变量的地方声明变量的类型以便 Flow 做检查,如:

var count: number = 0;   // 定义为数字类型
var name: string = '';   // 定义为字符串类型

// 定义为数组类型 其中元素为数字类型
var arr: Array<number> = [1, 2, 3];
var arr: number[] = [1, 2, 3]; // 简写形式,实际同上

// 可选类型的数组
let arr1: ?number[] = null;   // Works!
let arr2: ?number[] = [1, 2]; // Works!
let arr3: ?number[] = [null]; // Error!

// 元素 为可选类型 的数组
let arr1: (?number)[] = null;   // Error!
let arr2: (?number)[] = [1, 2]; // Works!
let arr3: (?number)[] = [null]; // Works!

var obj: { foo?: boolean } = {};  // 定义对象的 可选属性

// 定义可选类型 vaule 可以为 number, null, or undefined
function acceptsMaybeNumber(value: ?number) {
  // ...
}

// 不使用类型检查 可以声明为 any
function add(one: any, two: any): number {
  return one + two;
}

// 传参可以为 string 或 number
function stringifyBasicValue(value: string | number) {
  return '' + value;
}

// 定义函数入参类型 和 返回值类型
function concat(a: string, b: string): string {
  return a + b;
}

// 函数返回值类型 与 传参类型 相同
function identity<T>(value: T): T {
  return value;
}

Flow 还有很多知识可以学习,但是目前知道这些就可以阅读源码了。做好这些准备工作,我们就可以继续接下来的源码学习了。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Vue2使用vue-socket.io可以实现与Socket.io的集成,实现实时聊天等功能。首先,需要在项目中引入vue-socket.io扩展,可以通过npm安装vue-socket.io并引入。 在Vue实例中,使用Vue.use()来注册并使用Vue-socket.io。在注册时,需要传入相应的配置参数,包括debug、connection、vuex等。其中,debug用于调试,可以选择关闭;connection用于指定Socket.io的连接地址;vuex用于在Vuex中使用Socket.io的事件监听。 具体实现步骤如下: 1. 首先,安装vue-socket.io扩展:npm install vue-socket.io 2. 在Vue实例中引入VueVueSocketIO,并配置相应的参数。 3. 创建Vuex store,并在配置参数中指定vuex为store的实例。 4. 在Vue实例中使用Vue.use()注册Vue-socket.io,并传入配置参数。 这样,Vue2就可以使用vue-socket.io扩展来实现与Socket.io的集成了。可以使用Vue-socket.io提供的方法来监听Socket事件,并实现相应的功能。 总结一下,Vue2使用vue-socket.io扩展可以实现与Socket.io的集成,通过注册Vue-socket.io并传入相应的配置参数,可以在Vue实例中实现Socket事件的监听和处理。这样就可以实现实时聊天等功能了。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [Vue 使用 Vue-socket.io 实现即时聊天应用(vuex管理)](https://blog.csdn.net/weixin_47746452/article/details/121330186)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 33.333333333333336%"] - *2* [vue-socket.io-extended:Vue.js和Vuex的Socket.io绑定(受Vue-Socket.io启发)](https://download.csdn.net/download/weixin_42160425/18170249)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 33.333333333333336%"] - *3* [Vue 使用 Vue-socket.io 实现即时聊天应用(实战篇 一)](https://blog.csdn.net/weixin_47746452/article/details/121359940)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 33.333333333333336%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值