前言
终于写完了毕业论文,匆忙的一天突然空闲下来,终于有时间将前期学习的东西作为笔记搬上博客了。这个月发生了很多事,下面这些Vue的相关知识也是我在匆忙之中学习的,有错误的请见谅。
Vue是什么
简单来说就是一个JavaScript框架,但是他有个特点叫渐进式,即不需要一次性学会所有的内容,可以根据需要选择学习,是一个易学易用,性能出色,使用场景丰富的Web前端框架。相比于React,它关注于数据的流向,而不是数据的样式。
Vue.js - 渐进式 JavaScript 框架 | Vue.js (vuejs.org)
快速上手
和我们学其他前端一样,可以使用线上的CND链接,也可以下载后使用离线的版本。
1 2
| <script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
|
这里是非min的形式,也可以下载min的形式(本质就是将换行去除)
然后就可以开始创建Vue应用,都是固定的写法,最后的mount("#app")
别忘写,他确实容易让人忘记。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
| <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="./js/vue3.global.min.js"></script> </head> <body>
<div id="app"> {{ msg }}
<h1>{{web.title}}</h1> <h2>{{web.url}}</h2> </div>
<script>
Vue.createApp({ setup() {
const msg = Vue.ref("success")
const web = Vue.reactive({ title: "百度", url: "baidu.com" })
return { web: web, msg: msg } } }).mount("#app")
</script> </body> </html>
|
如果你熟悉ES6,那么还可以使用解构的写法,将createApp
, reactive
结构出来,这样就可以不用再写Vue这个前缀。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| const {createApp, reactive} = Vue createApp({ setup() { const web = reactive({ title: "gcnanmu", url: "gcnanmucode" })
return { msg: "success", web: web } } }).mount("#app")
|
这边出现了模版语法和响应式数据的知识,我们在后面会学习到,对于模版插值语法,使用过后端框架的人应该已经见过了。
模块化开发 import
上述创建vue应用的时候都是使用vue3.global.js
全局导入的,但是有时候我们并不需要使用它全部的模块,学过es6之后我们了解到相关模块可以使用import
按需导入。如果想要使用按需导入可以使用vue.esm-browser.js
这个js文件
1
| <script src="js/vue.esm-browser.js"></script>
|
打开文件划到最下面可以发现export
,导出了所有的模块
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <div id="app"> { { msg } } <h2>{{web.title}}</h2> <h2>{{web.url}}</h2> </div>
<script type="module"> import {createApp, reactive} from "./js/vue.esm-browser.js"
createApp({ setup() {
const web = reactive({ title: "百度", url: "www.baidu.com" })
return ({ msg: "success", web }) } }).mount("#app") </script> </body> </html>
|
插值表达式
又称模版语法,是一种用来在html标签中给数据占位的一种语法。在vue中常用的有三种
文本插值 { { } }
默认是纯文本的形式
1
| <span>Message: {{ msg }}</span>
|
纯文本数据 v-text 和{{}}
的用法很像
1
| <span v-text="xxx"></span>
|
原始HTML v-html 会将文本渲染为HTML
1
| <h3 v-html="web.url"></h3>
|
下面是一个例子:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
| <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <div id="app"> <h3>{{web.title}}</h3>
<h3 v-text="web.title"></h3>
<h3 v-html="web.url"></h3> </div>
<script type="module"> import {createApp, reactive} from "./js/vue.esm-browser.js"
createApp({ setup() {
const web = reactive({ title: "百度", url: "<i style='color:red;'>www.baidu.com</i>" })
return { web } } }).mount("#app") </script> </body> </html>
|
响应式数据 ref reactive
基本语法为:
1 2 3 4 5 6
| const number = ref(10)
const web = reactive({ title: "百度", url: "www.baidu.com" })
|
响应式数据顾名思义,通俗的理解就是源数据会顺应实时修改而变化,如果学过其他编程语言,我觉得可以理解成js封装好的特殊对象。
有两种形式:
- ref 用于存储基本的数据类型 这并不意味着ref只能存储单个数据,如果想要修改响应式数据的值,需要使用
value
属性。
- reactive 用于存储复杂的数据类型 可以直接修改其中的值。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52
| <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body>
<div id="app"> {{msg}}
<h2>{{web.title}}</h2> <h2>{{web.url}}</h2> <h2>{{number}}</h2> <h2>{{arr}}</h2> </div>
<script type="module"> import {createApp, reactive, ref} from "./js/vue.esm-browser.js"
createApp({ setup() {
const number = ref(10) number.value = 20
const arr = ref([1,2,3]) arr.value[1] = 4
const web = reactive({ title: "邓睿编程", url: "dengruicode.com" })
web.url = "www.baidu.com"
return { msg: "success", web, number, arr } } }).mount("#app") </script>
</body> </html>
|
动态属性绑定 v-bind
以input标签作为例子,指令书写的格式为:
1
| <input type="text" v-bind:value="web.url">
|
也可以缩写为:
,
1
| <input type="text" :value="web.url">
|
下面是一个例子:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61
| <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title>
<style> img { height: 100px; }
.textColor { color: lightblue; } </style> </head> <body> <div id="app"> <h3>dengruicode</h3> <input type="text" value="dengruicode.com">
<h3>v-bind:value="web.url"</h3> <input type="text" v-bind:value="web.url">
<h3>src="./img/二专.jpg"</h3> <img src="./img/二专.jpg" alt="">
<h3>v-bind:src="web.url"</h3> <img :src="web.img" alt="">
<h3>class="textColor"</h3> <b class="textColor">邓瑞编程</b>
<h3>:class="{textColor:web.fontStatus}"</h3> <b :class="{textColor:web.fontStatus}">邓瑞编程</b>
</div>
<script type="module"> import {createApp, reactive} from "./js/vue.esm-browser.js"
createApp({ setup() {
const web = reactive({ url: "wwww.dengruicode.com", img: "./img/二专.jpg", fontStatus: false })
return { web } } }).mount("#app") </script> </body> </html>
|
事件绑定 v-on
以button标签为例子,语法如下:
1 2 3 4
| <button v-on:click="edit"></button>
<button @click="edit">修改</button>
|
click
来监听DOM的点击事件的,本质就是使用了将js原生的一些方法绑定到Vue函数上,如果你的处理比较简单,还可以直接使用内联式,在html标签处就完成操作。
1
| <button @click="count++">Add 1</button>
|
如果还想要同时传入数据和原生DOM事件,可以使用$event
变量
1 2 3 4 5 6 7 8 9
| <button @click="warn('Form cannot be submitted yet.', $event)"> Submit </button>
<button @click="(event) => warn('Form cannot be submitted yet.', event)"> Submit </button>
|
1 2 3 4 5 6 7
| function warn(message, event) { if (event) { event.preventDefault() } alert(message) }
|
Vue甚至还提供了对键盘的监听,比较常见的有两种:
- keydown 按下键盘就触发
- keyup 按下后回弹才触发
在keydown
和keyup
后面可以添加键盘字符名,以下是一些常见的字符键盘:
别名 |
说明 |
.enter |
回车 |
.tab |
tab |
.delete |
delete和backspace |
.esc |
esc |
.space |
空格 |
.ctrl |
ctrl |
.alt |
alt |
.meta |
在 Mac 键盘上,meta 是 Command 键 (⌘)。在 Windows 键盘上,meta 键是 Windows 键 (⊞) |
以上的监听是非严格监听,意思是如果你按下其中某一个键,其余的键同时按下也会触发,如果想要严格监听,可以在末尾加上.exact
1 2 3 4 5 6 7 8
| <button @click.ctrl="onClick">A</button>
<button @click.ctrl.exact="onCtrlClick">A</button>
<button @click.exact="onClick">A</button>
|
看了上面的例子,你应该明白他也支持组合键监听
1
| <input type="text" @keyup.ctrl.enter="add(40, 60)"> <br>
|
下面是一个例子:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64
| <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <div id="app"> {{msg}}
<h2>{{web.url}}</h2> <h2>{{web.user}}</h2>
<button v-on:click="edit">修改</button> <br> <button @click="edit">@修改</button> <hr>
<input v-on:keyup.enter="add(40,60)" type="text"><br> 回车<input type="text" @keyup.enter="add(40,60)"><br> 空格 <input type="text" @keyup.space="add(20, 30)"> <br> Tab <input type="text" @keydown.tab="add(10, 20)"> <br> w <input type="text" @keyup.w="add(5, 10)"> <br>
Ctrl + Enter <input type="text" @keyup.ctrl.enter="add(40, 60)"> <br> Ctrl + A <input type="text" @keyup.ctrl.a="add(20, 30)"> </div>
<script type="module"> import {createApp, reactive} from "./js/vue.esm-browser.js"
createApp({ setup() {
const web = reactive({ url: "dengruicode.com", user: 0 })
const edit = () => { web.url = "www.baidu.com" }
const add = (a, b) => { web.user += a + b }
return { msg: "success", web, edit, add }
} }).mount("#app")
</script> </body> </html>
|
显示与隐藏 v-show
以input标签作为例子,语法为:
1
| <input type="text" v-show="web.show">
|
本质上是通过操作css属性中的display属性来控制标签的显示与否,需要传入一个布尔值,如果为true就显示,false即不显示。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
| <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body>
<div id="app"> {{web.show}} <p v-show="web.show">gcnanmu学Vue</p>
<hr>
<button @click="toggle">切换显示状态</button> </div>
<script type="module"> import {createApp, reactive} from "./js/vue.esm-browser.js"
createApp({ setup() {
const web = reactive({ show: true })
const toggle = () => { web.show = !web.show }
return { web, toggle } } }).mount("#app") </script> </body> </html>
|
条件渲染 v-if
以p标签作为例子,语法如下:
1 2 3
| <p v-if="web.user < 1000">新网站</p> <p v-else-if="web.user >= 1000 && web.user < 10000">优秀网站</p> <p v-else>资深网站</p>
|
这个语法和v-show
很像,如果不满足判断的条件就会不显示标签,但是这与v-show操作display属性不太一样,他会直接将标签删除,因此会造成很大的性能开销。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
| <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <div id="app"> {{web.show}} <hr> <p v-show="web.show">百度 baidu.com</p> <p v-if="web.show">github github.com</p>
<button @click="toggle">切换显示状态</button>
<p v-if="web.user < 1000">新网站</p> <p v-else-if="web.user >= 1000 && web.user < 10000">优秀网站</p> <p v-else>资深网站</p> </div>
<script type="module"> import {createApp, reactive} from "./js/vue.esm-browser.js"
createApp({ setup() {
const web = reactive({ show: true, user: 20000 })
const toggle = () => { web.show = !web.show }
return { web, toggle } } }).mount("#app") </script> </body> </html>
|
遍历 v-for
以li标签作为例子,语法如下:
对于数组对象,可以拿到index和value两个值
1 2 3 4 5
| <ul> <li v-for="(value,index) in data.number"> index:{{index}} value:{{value}} </li> </ul>
|
对于自定义对象,可以拿到index,key,index三个值
1 2 3 4 5
| <ul> <li v-for="(value,key,index) in data.user"> index:{{index}} key:{{key}} value:{{value}} </li> </ul>
|
下面是一个例子:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81
| <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body>
<div id="app"> <ul> <li v-for="value in data.number"> {{value}} </li> </ul>
<ul> <li v-for="(value,index) in data.number"> index:{{index}} value:{{value}} </li> </ul>
<ul> <li v-for="(value,key) in data.user"> key:{{key}} value:{{value}} </li> </ul>
<ul> <li v-for="(value,key,index) in data.user"> index:{{index}} key:{{key}} value:{{value}} </li> </ul>
<ul> <template v-for="(value,key,index) in data.user"> <li v-if="index == 1"> index:{{index}} key:{{key}} value:{{value}} </li> </template> </ul>
<ul> <template v-for="(value,index) in data.teacher"> <li :title="value.name" :key="value.id"> index:{{index}} id:{{value.id}} name:{{value.name}} web:{{value.web}} </li> </template> </ul> </div>
<script type="module"> import {createApp, reactive} from "./js/vue.esm-browser.js"
createApp({ setup() {
const data = reactive({ number: ["十", "十一", "十二"], user: { name: "gcnanmu", gender: "man" }, teacher: [ {id: 100, name: "百度", web: "baidu.com"}, {id: 101, name: "码云", web: "gitee.com"}, ]
})
return { data } } }).mount("#app") </script> </body> </html>
|
双向数据绑定 v-model
虽然ref
和reactive
确保了数据的响应式,但是它们本身并不实现自动收集用户输入并更新状态的逻辑。v-model
正是为了简化这个过程:它自动更新绑定的响应式变量,无需手动编写事件监听器和数据更新逻辑。这对于表单数据的绑定尤其有用,可以极大简化代码。
区别在于
- 单向数据绑定 当数据发生改变时, 视图会自动更新. 但用户手动更改 input 的值, 数据不会自动更新
- 双向数据绑定 当数据发生改变时, 视图会自动更新. 当用户手动更改 input 的值, 数据也会自动更新
以input标签作为例子,语法如下:
1
| <input type="text" v-model="data.radio">
|
下面是一个例子:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64
| <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body>
<div id="app"> <h3>文本框:{{data.text}}</h3> <h3>单选框:{{data.radio}}</h3> <h3>多选框:{{data.checkbox}}</h3> <h3>记住密码:{{data.remember}}</h3> <h3>下拉框:{{data.select}}</h3>
单项数据绑定:<input type="text" :value="data.text"> <hr> 双向数据绑定:<input type="text" v-model="data.text"> <hr> <input type="radio" v-model="data.radio" id="one" value="1"><label for="one">写作</label> <input type="radio" v-model="data.radio" id="two" value="2"><label for="two">画画</label>
<hr>
<input type="checkbox" value="1" v-model="data.checkbox">写作 <input type="checkbox" value="2" v-model="data.checkbox">画画 <input type="checkbox" value="3" v-model="data.checkbox">编程
<hr>
<input type="checkbox" v-model="data.remember">记住密码 <hr>
<select v-model="data.select"> <option value=""></option> <option value="A">写作</option> <option value="B">画画</option> <option value="C">运动</option> </select>
</div>
<script type="module"> import {createApp, reactive} from "./js/vue.esm-browser.js"
createApp({ setup() {
const data = reactive({ text: "dengruicode.com", radio: "", checkbox: [], remember: false, select: "" })
return { data } } }).mount("#app") </script> </body> </html>
|
计算属性 computed
computed
是Vue中一个新的数据类型,语法为:
1 2 3
| const sub = computed(() => { return data.x - data.y })
|
他作用是为计算添加本地缓存,相比无缓存的计算,如果出现相同的计算表达式,就不需要重复计算。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53
| <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <div id="app"> <h3>add:{{add()}}</h3> <h3>add:{{add()}}</h3> <h3>add:{{sub}}</h3> <h3>add:{{sub}}</h3>
x <input type="text" v-model.number="data.x"> <br> y <input type="text" v-model.number="data.y"> </div>
<script type="module"> import {createApp, reactive, computed} from "./js/vue.esm-browser.js"
createApp({ setup() {
const data = reactive({ x: 10, y: 20 })
let add = () => { console.log("add") return data.x + data.y }
const sub = computed(() => { console.log("sub") return data.x - data.y })
return { data, add, sub } } }).mount("#app") </script> </body> </html>
|
监听器 watch
watch
是Vue中一个特殊的函数,语法如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| watch(hobby, (newValue, oldValue) => { console.log("newValue", newValue, "oldValue", oldValue) })
watch(() => date.year, (newValue, oldValue) => { console.log("oldValue", oldValue, "newValue", newValue)
if (newValue === "2024") { console.log("2024") } })
|
它可以监听绑定变量的数据变化情况,需要自己手动安装指定要监听的变量或者数据,可以实时查看值是否发生变化。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96
| <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <div id="app"> <select v-model="hobby"> <option value="">请选择</option> <option value="1">写作</option> <option value="2">画画</option> <option value="3">运动</option> </select>
<hr>
年 <select v-model="date.year"> <option value="">请选择</option> <option value="2023">2023</option> <option value="2024">2024</option> <option value="2025">2025</option> </select>
月 <select v-model="date.month"> <option value="">请选择</option> <option value="10">10</option> <option value="11">11</option> <option value="12">12</option> </select> </div> <script type="module"> import {createApp, reactive, ref} from "./js/vue.esm-browser.js" import {watch} from "./js/vue.esm-browser.js";
createApp({ setup() {
const hobby = ref("") const date = reactive({ year: "2023", month: "10" })
watch(hobby, (newValue, oldValue) => { console.log("newValue", newValue, "oldValue", oldValue)
if (newValue === "2") { console.log("画画") } })
watch(date, (newValue, oldValue) => { console.log("newValue", newValue, "oldValue", oldValue)
if (newValue.year === "2025") { console.log(2025) }
if (newValue.month === "11") { console.log("11") } })
watch(() => date.year, (newValue, oldValue) => { console.log("oldValue", oldValue, "newValue", newValue)
if (newValue === "2024") { console.log("2024") } })
return { hobby, date } } }).mount("#app") </script> </body> </html>
|
自动监听器 watchEffect
它是相对于watch
模块需要手动监听的特点反过来提供一种自动监听的Vue函数,语法如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| watchEffect(() => { console.log("------ 监听开始")
if (hobby.value == "2") { console.log("画画") }
if (date.year == "2025") { console.log("2025") }
if (date.month == "11") { console.log("11") }
console.log("------ 监听结束") })
|
他会监听网站上的所有数据变化。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77
| <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <div id="app"> <select v-model="hobby"> <option value="">请选择</option> <option value="1">写作</option> <option value="2">画画</option> <option value="3">运动</option> </select>
<hr>
年 <select v-model="date.year"> <option value="">请选择</option> <option value="2023">2023</option> <option value="2024">2024</option> <option value="2025">2025</option> </select>
月 <select v-model="date.month"> <option value="">请选择</option> <option value="10">10</option> <option value="11">11</option> <option value="12">12</option> </select> </div> <script type="module"> import {createApp, reactive, ref, watchEffect} from "./js/vue.esm-browser.js"
createApp({ setup() {
const hobby = ref("") const date = reactive({ year: "2023", month: "10" })
watchEffect(() => { console.log("------ 监听开始")
if (hobby.value == "2") { console.log("画画") }
if (date.year == "2025") { console.log("2025") }
if (date.month == "11") { console.log("11") }
console.log("------ 监听结束") })
return { hobby, date } } }).mount("#app") </script> </body> </html>
|
Vue案例
学了很多知识后,为了方便融汇贯通最好还是要做点综合案例来检测自己的学习的知识是否牢固。
图片轮播图
在没有使用前端框架的时候,我们需要大段的js代码去修改图片的链接,但是有了Vue之后,代码就显得非常简单
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81
| <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <div id="app"> <h3 v-text="当前为num"></h3> <img :src=`./img/${num}.png` :alt="num" style="height: 200px;"> <hr>
<button @click="sub">上一张</button> <button @click="add">下一张</button>
<input type="text" @change="jump($event.target.value)" v-model.lazy="num">
<hr> <ul> <template v-for="(value,index) in 4"> <li> <a href="#" @click="jump(value)">{{value}}</a> </li> </template> </ul> </div>
<script type="module">
import {createApp, ref} from "./js/vue.esm-browser.js"
createApp({ setup() {
const num = ref(3)
const add = () => { if (num.value < 4) { num.value++ } else { num.value = 1 } }
const sub = () => { if (num.value >= 2) { num.value-- } else { num.value = 4 } }
const jump = (value) => { const numValue = parseInt(value); if (isNaN(numValue)) { return; } if (numValue > 4) { num.value = 4; } else if (numValue < 1) { num.value = 1; } else { num.value = numValue; } }
return { num, add, sub, jump } } }).mount("#app")
</script> </body> </html>
|
记事本
如果是在使用vue框架之前,如果想要完成一个todolist的效果,需要使用大量的js操作dom的函数,但是有了vue之后,我们只需要通过双向数据绑定操作原本的数据,再将数据通过v-for来展示在界面上即可。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61
| <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <div id="app"> <input type="text" v-model="data.content"> <button @click="add">添加</button>
<ul> <li v-for="(value,index) in data.list"> {{value}} <button @click="del(index)">删除</button> </li> </ul>
<span>{{data.list.length}} </span> <button @click="clear">清空</button> </div>
<script type="module"> import {createApp, reactive} from "./js/vue.esm-browser.js"
createApp({ setup() {
const data = reactive({ content: "邓瑞编程", list: ["baidu.net", "www.github.com"] })
const add = () => { data.list.push(data.content)
}
const del = (index) => { data.list.splice(index, 1) console.log(data.list) }
const clear = () => { data.list = [] }
return { data, add, del, clear } } }).mount("#app") </script> </body> </html>
|
购物车
这个案例就稍微复杂很多,加入了多选框之后要判断的情况会较多,但是依然能体会到vue框架的便捷之处。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169
| <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <style> table { width: 600px; color: #8f8e8e; text-align: center; border-collapse: collapse; }
table thead { background: #F5F5F5; }
table tr { height: 30px; line-height: 30px; border: 1px solid #ececec; } </style> </head> <body> <div id="app"> <table> <thead> <tr> <td><input type="checkbox" v-model="data.selected" @change="selectAll"></td> <td>商品</td> <td>单价</td> <td>库存</td> <td colspan="2">操作</td> </tr> </thead>
<tbody> <tr v-for="(value,index) in data.list"> <td><input type="checkbox" :value="value" v-model="data.checkboxList" @change="checkSelect"></td>
<td>{{value.name}}</td> <td>{{value.price}}</td> <td>{{value.stock}}</td> <td> <button @click="sub(value)">-</button> {{value.number}} <button @click="add(value)">+</button> </td> <td> <button @click="del(index,value.id)">删除</button> </td> </tr> </tbody> <tfoot> <tr> <td>总价{{totalPrice()}}</td> </tr> </tfoot> </table> </div>
<script type="module"> import {createApp, reactive} from "./js/vue.esm-browser.js"
createApp({
setup() {
const selectAll = () => { console.log(data.selected) if (data.selected) { data.checkboxList = data.list } else { data.checkboxList = [] } checkSelect() }
const checkSelect = () => { console.log(data.checkboxList) if (data.checkboxList.length === data.list.length && data.list.length !== 0) { data.selected = true } else { data.selected = false } }
const del = (index, id) => { data.list.splice(index, 1) }
const data = reactive({ selected: false, checkboxList: [], list: [ { id: 1, name: "铅笔", price: 10, number: 1, stock: 3 }, { id: 2, name: "鼠标", price: 20, number: 2, stock: 5 }, { id: 3, name: "键盘", price: 30, number: 1, stock: 6 } ] })
const totalPrice = () => { let total = 0; for (let i = 0; i < data.checkboxList.length; i++) { total += data.checkboxList[i].price * data.checkboxList[i].number }
return total }
const sub = (value) => { if (value.number > 1) { value.number-- } }
const add = (value) => { if (value.number < value.stock) { value.number++ } }
return { data, selectAll, checkSelect, totalPrice, sub, add, del } } }).mount("#app") </script> </body> </html>
|
购物车(优化)
我们不再单独写函数来处理数据的变化,使用watch函数来监听数据的变化并做出反应:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169
| <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <style> table { width: 600px; color: #8f8e8e; text-align: center; border-collapse: collapse; }
table thead { background: #F5F5F5; }
table tr { height: 30px; line-height: 30px; border: 1px solid #ececec; } </style> </head> <body> <div id="app"> <table> <thead> <tr> <td><input type="checkbox" v-model="data.selected"></td> <td>商品</td> <td>单价</td> <td>库存</td> <td colspan="2">操作</td> </tr> </thead>
<tbody> <tr v-for="(value,index) in data.list"> <td><input type="checkbox" :value="value" v-model="data.checkboxList" @change="checkSelect"></td>
<td>{{value.name}}</td> <td>{{value.price}}</td> <td>{{value.stock}}</td> <td> <button @click="sub(value)">-</button> {{value.number}} <button @click="add(value)">+</button> </td> <td> <button @click="del(index,value.id)">删除</button> </td> </tr> </tbody> <tfoot> <tr> <td>总价{{totalPrice}}</td>
</tr> </tfoot> </table> </div>
<script type="module"> import {createApp, reactive, watch, computed} from "./js/vue.esm-browser.js"
createApp({
setup() {
const del = (index, id) => { data.list.splice(index, 1) }
const data = reactive({ selected: false, checkboxList: [], list: [ { id: 1, name: "铅笔", price: 10, number: 1, stock: 3 }, { id: 2, name: "鼠标", price: 20, number: 2, stock: 5 }, { id: 3, name: "键盘", price: 30, number: 1, stock: 6 } ] })
const totalPrice = computed(() => {
return data.checkboxList.reduce((total, item) => total + item.price * item.number, 0) })
const sub = (value) => { if (value.number > 1) { value.number-- } }
const add = (value) => { if (value.number < value.stock) { value.number++ } }
watch(() => data.selected, (newValue, oldValue) => {
if (newValue) { data.checkboxList = data.list } else { data.checkboxList = [] } })
watch(() => data.checkboxList, (newValue, oldValue) => { console.log("newValue", newValue, "oldValue", oldValue) })
return { data, totalPrice, sub, add, del } } }).mount("#app") </script> </body> </html>
|
文章搜索
一般来说网页的数据都是通过API文档发送的,API中的格式一般为json格式,下面是一个通过API来实现文章搜索的案例。
请求的方式也分为get和post请求两种。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90
| <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="js/axios.js"></script> </head> <body> <div id="app"> <select v-model="data.type"> <option value="0">请选择</option> <option value="1">ID</option> <option value="2">标题</option> </select>
<input type="text" v-model="data.content"> <button @click="search()">搜索</button> <br>
<ul> <li v-for="(value,index) in data.list"> {{value}} </li> </ul> </div>
<script type="module"> import {createApp, reactive} from "./js/vue.esm-browser.js"
createApp({ setup() {
const data = reactive({ type: "0", content: "", list: [] })
const search = () => { console.log("搜索类型", data.type, "搜索内容", data.content)
data.list = []
if (data.type === "1") { let id = data.content
axios.get(`http://localhost/article/get/id/${id}`).then( response => { console.log("get,data", response.data)
if (response.data.status === "success") { data.list.push(response.data.data) } } ).catch(error => { console.log("get.error", error) }) } else if (data.type === "2") { let param = { title: data.content }
axios.post('http://127.0.0.1/article/postJson/search', param).then( response => { console.log("post.data", response.data)
if (response.data.status === "success") {
for (let i = 0; i < response.data.data.length; i++) { data.list.push(response.data.data[i]) }
} } ).catch(error => { console.log("post.error", error) }) } }
return { data, search } } }).mount("#app") </script> </body> </html>
|