一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第7天,点击查看活动详情。
一、前言
我毕业的时候就接触了 vue 项目了.当时 JQ 都没怎么了解过.公司上来就给我来 Vue. 本身的 JS 基础也是垃圾.原型和原型链更是没有听说过. 当时会的技术难度最高的,应该就是使用原生 JS 来进行菜单栏的点击,然后显示出对应菜单的内容, 就是控制display的black和none属性
很少人比我更菜了. 所以直接上手 vue 的时候,感觉又在重新学新一门新的语言,和 JS 没有产生一点关联. 四年过去了,是时候总结思考一下,为何当初会产生 Vue 和 JS 没有一点关系的感觉,Vue 明明是 JS 的 UI 库.
- 没有JS 基础
- 和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 语法. 而无需借助webpack、vite这种打包工具
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");
- 很明显, 这是一个 js 的文件,里面的内容都是 JS.
vue是一个构造函数. 而我们平时在写业务的时候,就是在写对象里面的属性内容. - 随后将这个
App对象传给new Vue()构造函数 new Vue构造函数对传进去的对象进行处理之后, 再通过$mount方法把对象里面的所有内容都放在<div id='app'></div>这个节点当中 从开发阶段就能够明显的看出来,Vue 为什么是单页面的,因为只有一个html. 而不需要npm run build之后查看dist文件才能够体会到.
2.3 v-if 和 v-show 的实现原理
打开控制台.通过点击v-if的按钮可以观察到. v-if是 通过替换 注释标签来达到显示的目的的. 隐藏的话, 就使用注释标签给替换 DOM
v-show的话, 是通过控制display的属性
<div style="">show 2</div>
=>
<div style="display: none">show 2</div>
三、我们来实现自己的一个 v-if 和 v-show
创建三个文件. index.html、vue.js、main.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);
拆解一下这个对象终端的属性: el、data、template、methods . 一共四个属性:
el表示我们当前内容要挂载到哪个 dom 上面
data: 我们需要响应式的数据
template: 浏览器需要渲染的模版
methods: 处理事件的集合
由此可以推断出, 在我们自己的vue框架中, 我们需要做三件事:
- 将
data中的数据响应式化 - 把
data中的数据和template中的对应上 - 把
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
- 观察
main.js的文件而知道. 我们在里面获取data的数据,或者调用方法.都是通过this加上点,然后加上对应的数据或者方法的变量名的. 想要调用方法的时候, 不是通过this.methods.showText1来实现的. 调用响应式数据的时候,也不是通过this.data.show1来实现的.
所以说,我们第一步要确定的就是数据和方法都是通过他们的父属性,直接挂载到new Vue实例上面的.由此就确定了this._init()的第一个形参 , this.
-
其次,template肯定是要用到的.所以第二个形参数就是
options.template -
最后,需要用到方法和
template相对应.自然就需要第三个形参,options.methods.
加上在全局需要使用到使用到的data和el.
最终在function Vue() {} 中初始化的参数和形参如下:
function Vue() {
this.$el = document.querySelector(options.el)
this.$data = options.data()
this._init(this, options.template, options.methods)
}
至于为什么不直接把options挂在实例上,这是为了控制变量,减少变数,妨碍引起异常.
由此,整个Vue 的基础代码结构就设计完成