一、案例体验一:动态展示Hello World数据
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<div id="app"></div>
<script src="lib/vue.js"></script>
<script>
const app = Vue.createApp({
template: `<h2>Hello World</h2>`,
});
app.mount("#app")
</script>
</body>
</html>
问题来了,我们怎么才能动态展示template模板里面的hello world内容呢?比如说我要展示hello Vue咋办呢?直接去改template是不是不方便?
我们在创建app对象的时候除了给它加一个template属性以外,我们还可以继续给他添加属性,比如说添加一个data属性。这里的属性不是随便填写的,得根据vue的api而来。
并且要求我们当前这个data是一个函数(要求的不要问为什么哈),而且这个函数必须要返回一个对象。
那此时我们现在是不是想让title的值展示到template这个里面呢?那这个我们如何做到呢?
我们需要用到插值语法:将某一个对应的属性的值插入到template里面的h2标签里面去。
那插值语法到底是怎么写呢?
# 插值语法:双大括号里面写下对应属性的名称
{{对应属性的名称}}
此时template模板里面的h2里面的内容是不是变成你title属性的值啦?
如果我想改变hello world,只需要改变title的值就可以了。或者新增一个属性message。
页面展示 :
总结:可以将数据放到data这一个属性里面,并且这个属性的要求是一个函数,这个函数要求返回一个对象,这个对象里面所有的属性都是可以通过插值语法插入到模板里面。
实战思路:先去我们的服务器里面请求一些数据存放在data里面,然后通过插值语法动态的将数据放到模板里面。整个过程里面,没有手动的操作过DOM。
咱们以前是怎么操作来着的?先获取元素等等...现在不需要了吧。其实这就是一个声明式编程。我只告诉你我这边要显示什么东西,至于怎么去操作DOM,你这个框架替我去完成。
二、案例体验二:展示列表的数据
正式开发的时候,我们这里message是不是一般拿到的基本都是列表的数据,所以我们需要把列表的数据动态的展示到template这个h2标签里面来。
此时我们这样子写能以列表的形式展示吗?回答当然是不行的。
这样子是直接拿到了数组,把数组转换成了字符串,直接把字符串展示出来了。
效果:
那有小伙伴们说我可以这么写:
这样子可以实现吗 当然可以。
那如果数据有几十条几百条甚至几千条数据呢?你也这么复制粘贴,然后按数组索引取值吗?
我们可以通过v-for 这个语法去遍历movies数据,然后将item通过插值语法插入进去。
总结用法:v-for可以遍历data这个对象里面的数据(数组),然后再通过插值语法将每个属于item插入进来。
三、案例体验三:计数器功能实现
如果我们希望实现一个计数器的案例:
- 点击+1,那么内容会显示数字+1;
- 点击-1,那么内容会显示数字-1;
我们先不去实现功能,先去把界面写出来。
目前我们是不是把想要展示的数字抽离出来了?所以只要我们点加号或者减号之后我们只要去改变counter这个值就好了。一旦counter这个值发生变化,这个界面就会自动去刷新。
目前我们点击这个加号减号是没有反应的。
在我们原生的DOM里面如果你想做上面描述的操作,你得先拿到加号减号这个元素,监听他的点击,监听回调函数在里面做对应的操作?
但是在vue里面,我首先先监听button点击,监听到点击之后必然会执行某些操作。所以我们得有一个函数和我们监听事件绑定在一起,所以我们在Vue创建的对象app里新增另外一个属性methods,它也是一个对象.
我们目前是需要把methods对象里面的方法和button按钮绑定在一起。只要一旦绑定在一起,我们去点击button按钮,就会让他自动去执行该按钮绑定的函数。然后在这个函数里面我们只要去改变counter的值就好了。
思路都理好了。那我们怎么把abc函数和cba函数绑定到两个按钮上面去呢?
很简单,我们只要在按钮上面绑定点击事件 @click="函数名"
那我们还剩最后一步,我怎么在abc函数里实现每点击一次就给counter+1呢?又怎么在cba函数里实现每点击一次就给counter-1呢?
下面上代码:
很多同学可能一开始接触这个有点疑问,
为什么这里的this能拿到上面这个对象呢?因为这个是vue底层帮你完成的(后面讲原理)。
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<div id="app"></div>
<script src="./lib/vue.js"></script>
<script>
const app = Vue.createApp({
template: `
<button @click="decrement">-1</button>
<h2>当前计数: {{counter}}</h2>
<button @click="increment">+1</button>
`,
data: function () {
return {
counter: 0,
};
},
methods: {
increment: function () {
this.counter += 1;
},
decrement: function () {
this.counter--;
},
},
});
app.mount('#app');
</script>
</body>
</html>
总结:
- 先将counter放到template里面的h2标签里
- methods对象里实现2个函数自加一 自减一
- 将按钮绑定点击事件 @click="函数名"
四、案例体验四:计数器功能实现(重构)
上面我们讲到了vue三条案例体验,咱们在写代码的时候,是不是感觉哪里写的特别变扭?
没错,就是我们在写template的时候。
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<div id="app"></div>
<script src="./lib/vue.js"></script>
<script>
const app = Vue.createApp({
template: `
<button @click="decrement">-1</button>
<h2>当前计数: {{counter}}</h2>
<button @click="increment">+1</button>
`,
data: function () {
return {
counter: 0,
};
},
methods: {
increment: function () {
this.counter += 1;
},
decrement: function () {
this.counter--;
},
},
});
app.mount('#app');
</script>
</body>
</html>
如果我们能放在这里编写效率是不是变高?然后把下面写的template里面的内容删掉。
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<div id="app"></div>
<h2>当前计数: {{counter}}</h2>
<button @click="decrement">-</button>
<button @click="increment">+</button>
<script src="./lib/vue.js"></script>
<script>
const app = Vue.createApp({
template: ``,
data: function () {
return {
counter: 0,
};
},
methods: {
increment: function () {
this.counter += 1;
},
decrement: function () {
this.counter--;
},
},
});
app.mount('#app');
</script>
</body>
</html>
但是我们这样子去写的时候,前端页面展示如下:
所以目前存在一个问题:你怎么把上面写的内容跟下面的template联系在一起?因为下面这个template是上面内容的模板。
我们今天就演示一个最简单的方法。
我们直接把下面的template删掉,删掉之后我们目前还有一个问题,带会vue渲染的时候,他知道要渲染谁吗?不知道。
我们可以把上面的内容剪切到id=app的div标签里面。
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<div id="app">
<h2>当前计数: {{counter}}</h2>
<button @click="decrement">-</button>
<button @click="increment">+</button>
</div>
<script src="./lib/vue.js"></script>
<script>
const app = Vue.createApp({
data: function () {
return {
counter: 0,
};
},
methods: {
increment: function () {
this.counter += 1;
},
decrement: function () {
this.counter--;
},
},
});
app.mount('#app');
</script>
</body>
</html>
现在功能是不是实现了?
那这样子做代表的意思是啥呢?为什么可以这么操作呢?
TODO:
当你有template,并且template里面是有内容的时候,vue会自动渲染template里面的东西,并且会把你原来id=app的div里面的内容替换掉。
如果你没有template,vue会自动渲染你id=app的div里面的内容,并且也会解析counter。
我们浏览器F12看下,
效果:
我们加上template看下效果:
是不是替换掉啦?
总结:所以,我们template其实是可以选到上面这个位置里来的,当你写在上面的时候,你在下面template里面就没必要慢慢自己去写了。
所以这个时候我们代码结构是这样子的:
- 模板
- data定义数据
- method定义函数
还有其他方法,后续我们再详细讲解哈~
通过两篇文章,大家能够体验到vue是怎么编写代码了嘛?
五、案例体验五:原生实现计时器案例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<h2>当前计数: <span class="counter"></span></h2>
<button class="add">+1</button>
<button class="sub">-1</button>
<script>
// 1. 获取dom
const h2El = document.querySelector('h2');
const counterEl = document.querySelector('.counter');
const addBtnEl = document.querySelector('.class');
const subBtnEl = document.querySelector('.sub');
// 2. 定义一个变量记录数据
let counter = 100;
counterEl.textContent = counter;
// 2. 监听按钮的点击
addBtnEl.onclick = function () {
counter++;
counterEl.textContent = counter;
};
subBtnEl.onclick = function () {
counter--;
counterEl.textContent = counter;
};
</script>
</body>
</html>
比对:
原生的开发模式(命令式编程):我要想达到一个目的,我得做哪些操作。
- 首先我想要改变counter这个值,得先拿到这个元素el(document.querySelector(".counter"))。
- 监听点击 - 获取元素 - 监听按钮的点击。
- 真正发生点击 - 改变counter++, 将最新的counter设置dom上面。
Vue(声明式编程)
- 声明一个模板 h2->{{counter}} ,button 点击绑定事件
- 声明data: counter -> 0, 声明methods
六、MVVM模型