手写v-if 和 v-show(1)-代码结构

385 阅读4分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第7天,点击查看活动详情

一、前言

我毕业的时候就接触了 vue 项目了.当时 JQ 都没怎么了解过.公司上来就给我来 Vue. 本身的 JS 基础也是垃圾.原型和原型链更是没有听说过. 当时会的技术难度最高的,应该就是使用原生 JS 来进行菜单栏的点击,然后显示出对应菜单的内容, 就是控制displayblacknone属性

很少人比我更菜了. 所以直接上手 vue 的时候,感觉又在重新学新一门新的语言,和 JS 没有产生一点关联. 四年过去了,是时候总结思考一下,为何当初会产生 Vue 和 JS 没有一点关系的感觉,Vue 明明是 JS 的 UI 库.

  1. 没有JS 基础
  2. 和JS长得非常的不像

没有 JS 基础这个是根本的原因. 第二个人觉得也是一个非常重要的一个原因. 就是,一上来从 js、html、css 直接改成了.vue为后缀的文件, 对于初学者的我而言,很难不懵逼.

所以我认为想要学习 Vue, 不应该一上来就使用脚手架, 而是使用 <script src='' /> 的模式来进行学习.

而对于这一点,其实vue 官网一开始就有表明. 可惜当初我使用 vue 的时候, 靠的是百度,而不是文档.

虽然是科班出身,但是可以是说辍学了四年.

二、Vue 中 v-if 和 v-show 的表现

2.1 引入 vue 的库地址

<body>
  <div id="app"></div>

  <script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
  <script type="module" src="./src/main.js"></script>
</body>

type='module 表示让它原生支持ES module 语法. 而无需借助webpackvite这种打包工具

2.2 v-if 和 v-show

// main.js
const App = {
  data() {
    return {
      isShowText1: true,
      isShowText2: false,
    };
  },
  template: `
      <div>
        <div v-if="isShowText1">橘子哥哥</div>
        <div v-show="isShowText2">茉莉花开</div>
        <div>
          <button @click="showText1">
            显示1
          </button>
          <button @click="showText2">
            显示2
          </button>
        </div>
      </div>
    `,
  methods: {
    showText1() {
      this.isShowText1 = !this.isShowText1;
    },
    showText2() {
      this.isShowText2 = !this.isShowText2;
    },
  },
};

const vm = new Vue({
  render: (h) => h(App),
}).$mount("#app");
  1. 很明显, 这是一个 js 的文件,里面的内容都是 JS. vue是一个构造函数. 而我们平时在写业务的时候,就是在写对象里面的属性内容.
  2. 随后将这个App对象传给new Vue()构造函数
  3. new Vue构造函数对传进去的对象进行处理之后, 再通过$mount方法把对象里面的所有内容都放在<div id='app'></div> 这个节点当中 从开发阶段就能够明显的看出来,Vue 为什么是单页面的,因为只有一个html. 而不需要npm run build之后查看dist文件才能够体会到.

2.3 v-if 和 v-show 的实现原理

打开控制台.通过点击v-if的按钮可以观察到. v-if是 通过替换 注释标签来达到显示的目的的. 隐藏的话, 就使用注释标签给替换 DOM

截屏2022-04-30 18.03.31.png

v-show的话, 是通过控制display的属性

<div style="">show 2</div>
=>
<div style="display: none">show 2</div>

三、我们来实现自己的一个 v-if 和 v-show

创建三个文件. index.htmlvue.jsmain.js

// index.html
<body>
  <div id="app"></div>
  <script type="module" src="./main.js"></script>
</body>

main.js文件

import Vue from "./vue.js";

const App = {
  el: "#app",
  data() {
    return {
      isShowText1: true,
      isShowText2: false,
    };
  },
  template: `
  <div>
    <div v-if="isShowText1">wuyucun1</div>
    <div v-show="isShowText2">moliy2</div>
    <div>
      <button @click="showText1">
        显示1
      </button>
      <button @click="showText2">
        显示2
      </button>
    </div>
  </div>
`,
  methods: {
    showText1() {
      this.isShowText1 = !this.isShowText1;
    },
    showText2() {
      this.isShowText2 = !this.isShowText2;
    },
  },
};

再把 App 这个对象传入自己构造的vue函数当中

const vm = new Vue(App);

拆解一下这个对象终端的属性: eldatatemplatemethods . 一共四个属性:

el表示我们当前内容要挂载到哪个 dom 上面

data: 我们需要响应式的数据

template: 浏览器需要渲染的模版

methods: 处理事件的集合

由此可以推断出, 在我们自己的vue框架中, 我们需要做三件事:

  1. data中的数据响应式化
  2. data中的数据和template中的对应上
  3. methods中的方法和template中的对应上  由此可以得出下面这样的一个代码结构
  const Vue = ;(function() {
    function Vue() {
      this._init()
    }

    Vue.prorotype._init = function() {
      initData()
      initPool()
      bindEvent()
      render()
    }

    // 1. 数据响应式
    function initData() {}
    // 2. template模版处理
    function initPool() {}
    // 3. 事件绑定
    function bindEvent() {}
    // 4. 界面渲染
    function render() {}

    return Vue
  })

  export default Vue
  1. 观察main.js的文件而知道. 我们在里面获取data的数据,或者调用方法.都是通过this加上点,然后加上对应的数据或者方法的变量名的. 想要调用方法的时候, 不是通过this.methods.showText1来实现的. 调用响应式数据的时候,也不是通过this.data.show1来实现的.

所以说,我们第一步要确定的就是数据和方法都是通过他们的父属性,直接挂载到new Vue实例上面的.由此就确定了this._init()的第一个形参 , this.

  1. 其次,template肯定是要用到的.所以第二个形参数就是options.template

  2. 最后,需要用到方法和template相对应.自然就需要第三个形参, options.methods.

加上在全局需要使用到使用到的datael.

最终在function Vue() {} 中初始化的参数和形参如下:

function Vue() {
  this.$el = document.querySelector(options.el)
  this.$data = options.data()

  this._init(this, options.template, options.methods)
}

至于为什么不直接把options挂在实例上,这是为了控制变量,减少变数,妨碍引起异常.

由此,整个Vue 的基础代码结构就设计完成