今天,我们来初步认识并使用一下Vue。Vue是什么?官方文档对它的定义是:
是一款用于构建用户界面的 JavaScript 框架。它基于标准 HTML、CSS 和 JavaScript 构建,并提供了一套声明式的、组件化的编程模型,帮助你高效地开发用户界面。无论是简单还是复杂的界面,Vue 都可以胜任。
它能帮我们做什么呢?举个简单的例子来说:我们要写一个网站,要写一个完整的项目。一般来说一个网站都会有几十个页面,如果我们用传统的开发方式,就得写几十份html文件,并且在一些页面中,有很多相似的结构,比如头部和尾部,那我们就得在每一个html文件中都写上重复的代码。如果我们使用了Vue框架,就能解决这些问题。它是支持组件化开发的,能很大程度上提升我们的开发效率。
那让我们一起来好好认识一下它。
初识Vue
我们先创建一个html文件,放上一个id为app的盒子。Vue框架的理念就是不再需要我们多写一行html代码了,全部由JS生成。如果是传统开发的话,就需要我们写原生JS代码去操控dom元素,而我们现在使用了Vue框架,它提供了很多非常好用的方法给我们使用。
我们先使用CDN引入一下Vue。再创建一个script标签。
<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
<body>
<div id="app"></div>
<script></script>
</body>
如果我们想往app中放一些标签应该怎么放呢?我们这样写,先来认识一下它的语法:
<body>
<div id="app"></div>
<script>
const app = Vue.createApp({
template: '<h2>hello world</h2>'
})
app.mount('#app')
</script>
</body>
Vue是一个对象,这个对象上有一个方法createApp,它要求我们传一个对象进去。createApp就会对我们传进去的对象进行操作,我们创建一个变量app接收它的结果。如果我们想往app中添加一个h2标签,就要在template里面写,并用引号引起来。这显然是一个字符串,createApp读到template中的字符串后,它就能将它转换成dom结构。最后我们写app.mount('#app'),它就能自动找到id为app的容器为它添加这个dom结构。
我们去浏览器中看看结果。
我们发现页面上确实出现了hello world,并且在app容器中出现了h2标签。
这样我们可以不使用原生JS代码去写,Vue框架提供了更加便利的方法给我们使用。
我们再来多认识一下它,我们来写一个计数器,点‘+1’按钮计数器就加1,点‘-1’按钮计数器就减1。
<body>
<div id="app"></div>
<template id="#demo">
<div>
<h2></h2>
<h3></h3>
<button>-1</button>
<button>+1</button>
</div>
</template>
<script>
const app = Vue.createApp({
template: '#demo'
})
app.mount('#app')
</script>
</body>
我们先搭建一下结构。我们可以将template的内容拿到script标签外面来写,用template标签包裹起来,给它加一个id为demo,然后在createApp的template引入就行。然后我们要在这个对象里写第二个参数,setup,是一个函数,我们在这个函数里面去写js代码。
<body>
<div id="app"></div>
<template id="#demo">
<div>
<h2></h2>
<h3></h3>
<button>-1</button>
<button>+1</button>
</div>
</template>
<script>
const app = Vue.createApp({
template: '#demo',
setup() {
}
})
app.mount('#app')
</script>
</body>
我们先来个简单点的,我们在setup函数中定义一个对象state,里面有一个title值为'hello world'。我们可以直接在h2标签中引入这个state.title,用两个大括号括起来。最后我们要return这个对象state。
<body>
<div id="app"></div>
<template id="#demo">
<div>
<h2>{{state.title}}</h2>
<h3></h3>
<button>-1</button>
<button>+1</button>
</div>
</template>
<script>
const app = Vue.createApp({
template: '#demo',
setup() {
let state = {
title: 'hello world'
}
return {
state
}
}
})
app.mount('#app')
</script>
</body>
我们来看一下页面中有没有:
确实出现了我们想要的效果,是不是比我们直接写原生js方便多了。
那接下来就来完成我们的计数器的效果。我们在state对象里添加一个count,值为0。我们想让它出现在h3标签中,可以直接在h3中引入,用双括号括起。
<body>
<div id="app"></div>
<template id="demo">
<div>
<h2>{{state.title}}</h2>
<h3>{{state.count}}</h3>
<button>-1</button>
<button>+1</button>
</div>
</template>
<script>
const app = Vue.createApp({
template: '#demo',
setup() {
let state = {
title: 'Hello world',
count: 0
}
return {
state
}
},
})
app.mount('#app')
</script>
</body>
0就出现了。现在我们希望点击‘-1’按钮count减1,点击‘+1’按钮count加1。传统的写法就是获取h3的dom结构,给它绑定一个点击事件,然后写接下来的操作。而现在,我们再也不需要去获取dom结构了。
我们直接在button标签里写@click="decrement",decrement是我们随便取得名字。这就相当于给button绑定了一个点击事件。然后我们将decrement拿到steup函数中写成一个函数,函数的功能就是让count减1。最后再将decrement return 出来。
<body>
<div id="app"></div>
<template id="demo">
<div>
<h2>{{state.title}}</h2>
<h3>{{state.count}}</h3>
<button @click="decrement">-1</button>
<button>+1</button>
</div>
</template>
<script>
const app = Vue.createApp({
template: '#demo',
setup() {
let state = {
title: 'Hello world',
count: 0
}
const decrement = () => {
state.count--
}
return {
state,
decrement
}
},
})
app.mount('#app')
</script>
</body>
此时我们的逻辑已经写完了,但我们现在去点‘-1’按钮页面上的count并不会减1。难道我们哪里写错了吗?并没有,其实当点了‘-1’按钮时,count的值确实减1了。但它并没有被重新渲染出来。也就是说这份页面一打开被渲染好的就是count为0,之后你再去修改count的值我也不会去渲染。所以我们要将state对象定义成响应式,当我们去修改对象里的值时,页面要跟着重新渲染。
用reactive方法。我们需要先从Vue中引入。然后将那个对象作为实参传给reactive。
<body>
<div id="app"></div>
<template id="demo">
<div>
<h2>{{state.title}}</h2>
<h3>{{state.count}}</h3>
<button @click="decrement">-1</button>
<button>+1</button>
</div>
</template>
<script>
const { reactive } = Vue
const app = Vue.createApp({
template: '#demo',
setup() {
let state = reactive({
title: 'Hello world',
count: 0
})
const decrement = () => {
state.count--
}
return {
state,
decrement
}
},
})
app.mount('#app')
</script>
</body>
const { reactive } = Vue是对象的解构,我们从Vue对象中解构出来了reactive方法,createApp方法也能这样解构出来。现在我们再去页面中看一看有没有效果。
当我们点击了‘-1’按钮,这个计数器确实在减1。
那‘+1’操作你现在应该也会写了,代码应该差不多。先给‘+1’按钮绑定一个点击事件,‘add’,再把‘add’拿到setup函数中写成一个函数,功能是让count加1,最后记得将add返回。
<body>
<div id="app"></div>
<template id="demo">
<div>
<h2>{{state.title}}</h2>
<h3>{{state.count}}</h3>
<button @click="decrement">-1</button>
<button @click="add">+1</button>
</div>
</template>
<script>
const { reactive } = Vue
const app = Vue.createApp({
template: '#demo',
setup() {
let state = reactive({
title: 'Hello world',
count: 0
})
const decrement = () => {
state.count--
}
const add = () => {
state.count++
}
return {
state,
decrement,
add
}
},
})
app.mount('#app')
</script>
</body>
这样我们就简单认识了一下Vue。这样写代码我们有一个好处,以前写网站几十个页面可能要几十份htm文件,而现在用Vue进行开发,我们只需要准备一个html文件,我们可以把每个页面的html文件写在template标签里。当要展示这个页面时,就将它添加到app容器中。我们也可以将每个页面中的公共部分单独提取出来写成一个代码块,当某一个页面需要时,就将它展示到app容器中去。可以大大提高我们的开发效率。
所以对于Vue:
是一个js 框架,将dom 以字符串的方式读取,并解析,得到真实的 dom添加到页面上,对 dom 结构的操作就变成了对数据的操作,因为变量可以声明响应式,就再也不需要人为操作 dom 了
单页应用,永远只有一个 html 文件,所有的页面本质上都是一个代码块,只需要切换不同的代码块来显示
vite
我们再来认识一下vite。它不是一个框架,而是辅助Vue使用的一个小工具 。它可以直接帮我们创建一个项目开发所需要的目录结构,就不用全部挤在一个文件里面。
我们来简单使用一下vite。
我们可以看看官方文档对它的定义:
Vite(法语意为 "快速的",发音
/vit/,发音同 "veet")是一种新型前端构建工具,能够显著提升前端开发体验。它主要由两部分组成:
- 一个开发服务器,它基于 原生 ES 模块 提供了 丰富的内建功能,如速度快到惊人的 模块热更新(HMR)。
- 一套构建指令,它使用 Rollup 打包你的代码,并且它是预配置的,可输出用于生产环境的高度优化过的静态资源。
Vite 意在提供开箱即用的配置,同时它的 插件 API 和 JavaScript API 带来了高度的可扩展性,并有完整的类型支持。
我们在终端中输入npm create vite@latest就能创建一个项目,然后会问你项目的名称,然后跟着它的提示去选就行了。
然后你会发现你的目录里多了这么一些文件,这就是开发一个项目所需要的目录结构:
整个目录里面只有一个html文件,里面放了一个id为app的容器,我们要写代码就在src文件夹下的vue后缀的文件中写。
然后它会提示让你输入这三行指令:
第一个进入这个项目中,第二个我们在node那篇文章中讲过,是去下载缺少的包,第三个就是帮你把这个项目跑起来。
我们按顺序输入这三行指令,它就会帮你把项目在5173端口上跑起来。我们Ctrl单击点击一下。
这个项目就被跑起来了。
我们来用vite实现一下我们刚刚写的计数器的效果。我们来到src文件夹下的App.vue文件,我们就是在这里面写js代码。里面已经写好了一些,就是上面所展示的页面的代码。我们可以删除这些写好的,我们自己来写。
我们可以把计数器的代码转移到vue文件中:
<script setup>
import { reactive } from 'vue'
let state = reactive({
title: 'hello, Vue.js',
count: 0,
})
const increment = () => {
state.count--
}
</script>
<template>
<div>
<h2>{{ state.title }}</h2>
<h3>{{ state.count }}</h3>
<button @click="increment">-1</button>
<button>+1</button>
</div>
</template>
<style scoped>
</style>
在这里我们可以不用return,它会自动帮我们return掉。这就是我们刚刚计数器的代码,它到时候就会被引入到html文件中的app容器里。如果我们还需要另外写一个页面,就可以创建另外一个vue文件去写,到时候引入到唯一的那个html文件中就行,就实现了组件化开发。
我们来使用一些vite的一些指令。我们为我们的计数器再添加一个功能,当计数器的值小于-5时,让它变成红色。
那我们就得给h3标签添加一个样式,但这个样式不是直接添加在h3标签上,而是要动态添加,当count的值小于-5时,就将这个样式添加到h3标签上。
vite为我们提供了一个非常好用的指令:v-bind。它可以动态添加一个类名。我们可以先写好一个样式为红色,然后给它动态添加这个类名。我们定义一个isActive初始值为false,当count小于-5时就将它改为true,就为h3标签添加这个类名。
<script setup>
import { reactive } from 'vue'
let state = reactive({
title: 'hello, Vue.js',
count: 0,
isActive: false,
})
const increment = () => {
state.count--
if (state.count < -5) {
state.isActive = true
} else {
state.isActive = false
}
}
</script>
<template>
<div>
<h2>{{ state.title }}</h2>
<h3 v-bind:class="{ 'red': state.isActive }">{{ state.count }}</h3>
<button @click="increment">-1</button>
<button>+1</button>
</div>
</template>
<style scoped>
.red {
color: red;
}
</style>
我们来看一下有没有这个效果。
确实可以,当count小于-5时,才给h3标签添加这个类名。
其实我们还见过一个指令:v-on。@click="increment",我们用这段代码给button绑定了一个点击事件,其实这个@就是v-on,它还可以写成v-on:click="increment"。
我们再来使用一个好用的指令。我们想把一个数组中的数据展示到页面中去,我们就需要去遍历这个数组。而vite也提供了可以进行遍历的指令:v-for。
我们准备一个ul容器,到时候就将数组中的数据添加到ul中的li里面去。
我们直接这样写:
<script setup>
import { reactive } from 'vue'
let state = reactive({
title: 'hello, Vue.js',
count: 0,
isActive: false,
arr: ['html', 'css', 'js', 'vue']
})
const increment = () => {
state.count--
if (state.count < -5) {
state.isActive = true
} else {
state.isActive = false
}
}
</script>
<template>
<div>
<h2>{{ state.title }}</h2>
<h3 v-bind:class="{ 'red': state.isActive }">{{ state.count }}</h3>
<button @click="increment">-1</button>
<button>+1</button>
</div>
<ul>
<li v-for="(item, index) in state.arr">{{ item }}</li>
</ul>
</template>
<style scoped>
.red {
color: red;
}
</style>
v-for接收两个参数,item表示数组中的每一项,index表示下标,要用in去指明是哪个数组,然后我们将item放到li中去。这就写完了,其实这就是一个for循环,比我们写原生JS舒服太多了。
成功展示出来了数组中的数据。
总结
本篇文章我们一起简单学习了一下Vue,它是一个JS框架,能提升我们的开发效率。还简单认识了一下vite这个小工具,它可以直接帮我们搭建一个项目开发所需要的目录,实现组件化开发。
之后我们再去深入学习一下Vue的其它语法,如果文章对你有帮助的话,不妨点个赞吧。