阅读完本篇文章你可收获如下知识点
抓重点讲吧,最开始可追溯的版本号是0.6.0这个,但是正式对外发布的版本是在2014年1月24日发布的0.8.0。后面就是两个打头的里程碑,一个是1.x.x,一个是2.x.x。注意到目前为止笔者写这篇文章(2020.03.23)的时候,是没有vue3.0正式版本的,目前是正在用Typescript开发中,2019年10月5号发布的是vue3.0的预览版源码(vue-next),到可以生产使用还有点路,而vue cli3.0这个说法是有的,他们不是一个概念这里先提及一下不要混淆,vue cli 是vue的脚手架工具。其中1.x.x中的1.0.0版本是在2015年10月27号笔者刚上大学的那年发布的,这个时候你写指令可以缩写了,有意思的是,那年发布的蛮多vue的插件的,比如管路由的vue-router、全局状态Vuex以及脚手架vue-cli等等。2.x.x中的2.0.0是在次年的国庆节发布的,它做的比较大的改动相对于1.x.x来讲的话就是,以前呢是把模板交给浏览器去解析渲染的,现在用的是Virtual DOM。
前面我们提到了一些关于Vue的版本号,那么我们这里来看下版本号代表的意思吧。
字母 | 版本号 | 说明 |
---|---|---|
x | 主版本号 | 一般是大改动,不保证兼容的,脱胎换骨那种 |
y | 次版本号 | 有些新加的功能,能够保证兼容的 |
z | 修订号 | 修复一些小的bug |
注意事项:
话不多说,直接上图
从上面的star、watch、fork以及使用数可以看到,前端届当之无愧的网红,学它至少能够找到一个前端的饭碗对吧,这里笔者单独拎出来这张图,其实还是想介绍下怎么去选择一个库。我们知道剩下两位React和Angular分别有FB和Google的支持,而Vue最开始是一个个人项目最后发展成为组织,原则上我们更倾向于有组织或者社区维护的库用于生产环境,这样子遇到问题解决的概率会大一点,还有个就是从可性度考虑,最直白的方式你看它用的人多不多,多的话你就放心用,对应这里的Userd by.
MVVM即Model-VIew-VIewModel。说得通俗点它做了一件事就是将数据和视图进行双向绑定,你操作数据视图改变了,你改变了视图数据也跟着改变了,你很少需要手动进行DOM操作。谈起如何实现,大致思路是第一个把一些指令啊表达式能够解析成浏览器能够听得懂的,第二个就是对数据对象的所有属性进行监听(Object.defineProperty()),第三个就是把他们关联起来。
指令的意义在于提供了更好地操作更新数据的方法,在没有这些指令之前,例如我们想更新p标签的内容,我们需要用js获取它的属性,然后通过innerText或者textContent去改变我们想要改变的内容,而有了v-text指令后,我们只需要在Vue实例中的data属性中操作我们需要更改的数据,同理可以类推出其他指令。
罗列了下常用的指令如下:
楼上的备注(vx.x.x+)表示在某个版本及以上支持,这里笔者未全部测试,仅作了解。下面我们综合下楼上的指令做次实践。
我们做这样一件事,在Vue实例的data属性中放入如下数据,然后在页面上去展示:
data: {
text: 'hello world!',
html: "<span>我是一个span标签包裹的html</span>",
}
<p>v-text指令:</p>
<p v-text="text"></p>
<p v-text="html"></p>
<p>{{text}}</p>
<p>v-html 指令:</p>
<p v-html="text"></p>
<p v-html="html"></p>
<p>{{html}}</p>
在页面显示部分我们分别用v-text和v-html指令去解析楼上的数据,最后一条都用Moustache语法,得到的效果如图。
从中我们可以看到Moustache语法是直接解析成文本的,v-text它是不解析标签的,而v-html会去解析标签。
偷懒一点,我们还是延用楼上的数据,只不过html部分改了下,这里我们故意<p v-html="html">试试</p>
这么写
<p>v-once:</p>
<p v-once>{{html}}</p>
<p>v-pre:</p>
<p v-pre>{{html}}</p>
<p>v-html:</p>
<p v-html="html">试试</p>
之后我们打开网页进行操作一波
可以看到v-pre是不做解析的,v-once只按文本解析一次,而且默认写在标签的文字会被替换。
今天刚好是2020年3月22日嘛,那么我们创建一个数组arr: [2, 0, 2, 0, 0, 3, 2, 2]
放在Vue实例的data里面,并且在methods里面写个判断偶数的函数
isEven(v) {
return v % 2 === 0;
}
网页上做如下处理,这段话的意思就是先遍历数组,然后找是偶数的,这里我们分别用v-if和v-show:
<hr/>
<span v-for="(v,k) in arr" v-if="isEven(v)"> {{k}}:{{v}} </span>
<hr/>
<hr/>
<span v-for="(v,k) in arr" v-show="isEven(v)"> {{k}}:{{v}} </span>
<hr/>
具体的效果如图所示:
可以看到v-if如果条件为false的话是不解析的,而v-show如果条件为false,元素还是在的只不过display属性设置成了none。
我们把楼上的例子升级一下,就是如果不是偶数就爆红,然后再演示下遍历对象。在Vue实例的data属性中加入了一个obj对象
obj: {
year: 2020,
month: 03,
day: 22
}
对应html的修改如下:
<p v-for="(v,k) in arr" v-if="isEven(v)"> {{k}}:{{v}} </p>
<p v-else style="color:red"> {{k}}:{{v}} </p>
<p v-for="(v,k) in obj"> {{k}}:{{v}} </p>
具体的展示效果如下:
我们做这样一个例子点击按钮字符串反转,然后显示的颜色变红字体变大。
定义样式文件部分代码
.red {
color: red;
}
.big {
font-size: 20px;
}
定义html标签部分代码
<input type="text" v-model="text"/>
<p v-text="text" v-bind:class="{'red': isRed, 'big': isBig}"></p>
<button v-on:click="change">反转变红</button>
实例化Vue相关属性部分代码
data: {
text: 'hello world!',
isRed: false,
isBig: false
},
methods: {
change() {
this.isRed = !this.isRed;
this.isBig = !this.isBig;
this.text = [...this.text].reverse().join('');
}
},
具体的效果如下:
整理了下一个完整的Vue生命周期,
目前笔者用的比较多的是created和mounted,它们长得很像,所以这里我们区分一下这两位选手。
created 是指完成了完成了数据、方法、属性、事件的初始化,你可以调用它们,但是$el属性并没有显示出来
mounted 是指el被新创建的的vm.$el替换了并且已经挂载到实例了,编译好的内容已经替换了el属性指向的DOM对象,所以在这个时候你去进行ajax交互是比较好的。
我们来看这样一个例子,我们实例化一个Vue对象,然后通过在data里面分别放了5个属性abcde,在created和mounted函数里面分别获取data的a的值,调用methods方法,以及获取网页的元素的值。
html部分代码如下:
<p>{{a}}</p>
<p>{{b}}</p>
<p>{{c}}</p>
<p>{{d}}</p>
<p>{{e}}</p>
Vue实例部分代码如下:
data: {
a: 'aaaaa',
b: 'bbbbb',
c: 'ccccc',
d: 'ddddd',
e: 'eeeee'
},
created() {
console.log('created start ....')
console.log('get data a: ', this.a);
console.log('call function hello: ', this.hello());
let pArr = document.getElementsByTagName('p');
for(let i = 0; i < pArr.length; i++) {
console.log(`${i}: ${pArr[i].textContent}`)
}
console.log('created end ....')
},
mounted() {
console.log('mounted start....')
console.log('get data a: ', this.a);
console.log('call function hello: ', this.hello());
let pArr = document.getElementsByTagName('p');
for(let i = 0; i < pArr.length; i++) {
console.log(`${i}: ${pArr[i].textContent}`)
}
console.log('mounted end....');
},
methods: {
hello() {
return 'hello world';
}
}
显示的效果如下:
可以看到,在created钩子中,确实初始化了相关事件方法属性,但是网页并未挂载到页面上,只有mounted之后,页面上显示了我们data里面的数据。
这里我觉得官网讲的很详细了,就提及一下吧。
通常我们不期望在template里面暴露过多的判断逻辑,我们可以选择计算属性,实现一个方法但是暴露出去是一个值,我们只需要在合适的地方v-if="计算属性"
,这样就比较好维护了,计算属性有get和set方法,然后计算属性可以记录新旧值变化。
顾名思义,就是监听数据变化然后触发相应操作,笔者目前用的比较多的是监听全局状态改变,然后各个分组件进行相关操作。
简单地说,组件就是把网页肢解成一个个小模块去实现,特定场景可复用,直接上图吧。
从楼上这张图,我们不难发现,头部可以写个组件,底部可以写个组件,而且它们是通用组件,就是你换个页面也能用的,类似的还有弹框啊,按钮啊之类的。然后items也可以封装成一个个组件,一个专题一个。
遥想上古时代网页编程,写个几十个页面,你写着写着发现a页面有个头部有个尾部还有若干链接按钮啥的,等你去写b页面又是它们,你去写c页面怎么还是它们,你的内心不崩溃吗?而当你写成组件的时候,下次你直接引用就好了,还比较好维护,放到以前那个做法就是CTRL+C&&CTRL+V
,与此同时带来的一个问题就是组件间的通信了,例如父子组件传值,兄弟组件传值等等。
组件不是我们今天的重点,所以这里提及一下。
最开始我们写页面,本地的时候可能会创建一个文件夹叫assets
,然后再新建一个js
文件夹引入一堆jQuery之类的库。线上的话我们可能会用cdn去引入。放到上古时代,我们每次都要打开浏览器去下载它,然后去解压,然后贴到我们的项目目录对吧。有了bower以后,你就可以不用关心这些了,直接命令行一把梭,但话说回来,bower现在在前端工程化项目用的并不多,笔者是很喜欢在演示项目的时候用它,因为比较方便,好的下面我们一起来看下吧。
$ npm install -g bower #全局安装bower
$ bower init #会创建一个bower.json配置文件
$ bower install pkg #安装pkg, 例如 bower install jquery, 默认安装在bower_components下
$ bower search pkg #搜索pkg
$ bower info pkg # 查看pkg信息,这个命令也会去下载的
$ bower list # 列出已安装的包
默认bower安装都是放在bower_components下面的,我们有的时候想自己定义,那么新建一个文件叫.bowerrc
{
"directory": "assets/libs",
"timeout": 120000,
"registry": "https://registry.bower.io"
}
那么它下次就会安装在assets下面的libs目录下
这里以vue0.6.0为例命令是bower install vue#0.6.0
bower vue#0.6.0 not-cached https://github.com/vuejs/vue.git#0.6.0
bower vue#0.6.0 resolve https://github.com/vuejs/vue.git#0.6.0
bower vue#0.6.0 download https://github.com/vuejs/vue/archive/0.6.0.tar.gz
bower vue#0.6.0 progress received 0.1MB
bower vue#0.6.0 progress received 0.1MB
bower vue#0.6.0 progress received 0.1MB
bower vue#0.6.0 extract archive.tar.gz
bower vue#0.6.0 resolved https://github.com/vuejs/vue.git#0.6.0
bower vue#0.6.0 install vue#0.6.0
vue#0.6.0 assets\libs\vue
很有意思,同学们发现了吗,首先他会去看下本地有没有缓存,没用的话就去远程下载,然后下载完解压到指定目录。
vue cli 2.0的安装方式
npm i vue-cli -g
vue cli 2.0 创建项目
vue init vue project
vue cli 3.0的安装方式
npm i @vue/cli -g
vue cli 3.0 创建项目
vue create project
vue cli 2.0创建的项目有一大堆配置文件,所以学习成本就上去了,vue cli 3.0相比之下少了很多,集成了webpack和webpack-dev-server
2.0时代有config、build、static文件夹,其中config和build里面又有dev、prod等配置文件,而3.0取而代之的是vue.config.js,并且砍掉了这些目录,改为public。
配置简单了,新增 .browserslistrc 文件可做浏览器兼容,新增 babel.config.js 替代原先的.babelrc,但作用是一样的,不仅有命令行还有ui界面了,输入vue ui
可以进行项目创建可视化配置。
<template>
//这里面写你的html标签元素
</template>
<script>
//写js逻辑
</script>
<style>
//写css样式
</style>
结合楼上的部分,我们实现一个低配版的弹框。
我们做这样一件事情,就是打开网页点击按钮,内容显示,再次点击按钮内容消失。
MsgBox.vue
这里MsgBox相当于Home的子组件,他们之间用props进行通信。
<template>
<div class="msgBox">
{{msg}}
</div>
</template>
<script>
export default {
name: 'MsgBox',
props: {
msg: String
}
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
.msgBox {
width: 500px;
height: 300px;
background: #ffffff;
border-radius: 8px;
box-shadow: 0px 0px 15px rgba(4,0,0,.4);
align-items: center;
justify-content: center;
display: flex;
font-size: 24px;
}
</style>
Home.vue
给按钮加个点击事件,点击的时候调用toShow方法,然后通过判断相关参数去决定显示与否
<template>
<div class="home">
<div class="header">
<button class="button" @click="toShow">{{message}}</button>
</div>
<div v-if="isShow" class="show">
<MsgBox msg="Hello World"/>
</div>
</div>
</template>
<script>
// @ is an alias to /src
import MsgBox from '@/components/MsgBox.vue'
export default {
name: 'Home',
data () {
return {
show: false,
message: '显示'
}
},
components: {
MsgBox
},
methods: {
toShow () {
this.show = !this.show
this.message = this.show ? '隐藏' : '显示'
}
},
computed: {
isShow () {
return this.show
}
}
}
</script>
<style>
.home {
display: flex;
flex-direction: column;
}
.header {
flex-basis: 100%;
display:flex;
}
.button {
background-color: #4CAF50; /* Green */
border: none;
color: white;
padding: 10px 20px;
text-align: center;
text-decoration: none;
display: inline-block;
font-size: 16px;
box-shadow: 0 8px 16px 0 rgba(0,0,0,0.2), 0 6px 20px 0 rgba(0,0,0,0.19);
}
.button:hover {
box-shadow: 0 12px 16px 0 rgba(0,0,0,0.24), 0 17px 50px 0 rgba(0,0,0,0.19);
}
.show {
flex-basis: 100%;
display:flex;
justify-content: center;
}
</style>>
这里笔者是比较粗暴地实现了,其实深究下去还是有很多问题,比如组件的健壮性,尽量可配置化程度高一点,然后点击的时候有个过渡效果可能会好一点,后续我们再继续完善吧,以上就是今天的全部内容。
bower文件配置:https://bower.io/docs/config/
bower包库搜索:https://bower.io/search/
vue cli: https://cli.vuejs.org/guide/