Vue核心特性解析(内含实践项目:设置购物车)

news/2024/11/24 18:59:40/
htmledit_views">

Vue 3 作为html" title=前端>前端开发领域的热门框架,为构建用户界面提供了高效且灵活的解决方案。在上一篇博客:深度解析Vue3中,我们了解到了响应式数据、v-on、v-if、v-for、v-bind等Vue相关属性,这篇我们继续探讨Vue的其他属性,为你揭开Vue的魅力所在。

一、双向绑定指令

1、基本概念

html" title=前端>前端处理表单时,我们常常需要将表单输入框的内容同步给 JavaScript 中相应的变量。手动连接值绑定和更改事件监听器可能会很麻烦,而此时我们就可以使用v-model指令

v-model用于在表单元素(如<input>、<textarea>、<select>)和组件上创建双向绑定指令。这说明了该指令可以同时实现数据从数据层(JavaScript)到视图层(HTML)的渲染,可以从视图层获取用户输入并更新数据层

v-model 会忽略任何表单元素上初始的 valuechecked 或 selected attribute。它将始终将当前绑定的 JavaScript 状态视为数据的正确来源。所以应该在 JavaScript 中使用响应式系统的API来声明该初始值。

2、实际应用

(1)文本框(text)

①单向绑定

数据是单向流动的,通常是从数据层流向视图层。当数据发生改变时, 视图会自动更新. 但用户手动更改 input 的值, 数据不会自动更新。比如:

html"><head><style>.textColor{color: red;}</style>
</head>
<body><div id="app"><h3>文本框 <ins>{{ data.text }}</ins></h3>input元素的value属性动态化(单向数据绑定): <input type="text" :value="data.text">    <br></div><script type="module">import { createApp, reactive } from './vue.esm-browser.js'createApp({setup() {const data = reactive({text: " ", })return {data}}}).mount("#app")</script>
</body>

运行结果如下: 

看代码,如果用户输入文本框中输入内容后,在“文本框”的后面没有实时更新相应内容,这便是单向绑定。

②双向绑定指令

数据不仅会从数据层流向视图,视图上的变化也会实时更新到数据层,二者相互影响。比如:

html"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>双向数据绑定指令v-model (实时渲染)</title><style>.textColor{color: red;}</style>
</head>
<body><div id="app"><h3>文本框 <ins>{{ data.text }}</ins></h3>双向数据绑定: <input type="text" v-model="data.text"></div><script type="module">import { createApp, reactive } from './vue.esm-browser.js'createApp({setup() {const data = reactive({text: "输入姓名", })return {data}}}).mount("#app")</script>
</body>

运行结果如下:

双向绑定指令则会根据用户输入的内容实时更新到“文本框”后面。

(2)单选框(radio)

用于记录用户的单选选择,将用户选中的值绑定到数据中。比如:

html"><!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>双向数据绑定指令v-model (实时渲染)</title><style>.textColor{color: red;}</style>
</head><body><div id="app"><h3>您的性别(单选):<ins> {{ data.radio }}</ins></h3> <!-- 对于多个<input type="radio">, v-model 绑定的是 input 单选元素组的选中的值value --><input type="radio" v-model="data.radio" value="男" name="radio">男<input type="radio" v-model="data.radio" value="女" name="radio">女<hr></div><script type="module">import { createApp, reactive } from './vue.esm-browser.js'createApp({setup() {const data = reactive({radio: "", })return {data}}}).mount("#app")</script></body>
</html>

运行结果如下:

 用户选择“男”或“女”后,data.radio的数据会实时更新为所选单选框的value值,并在页面上显示。

(3)多选框(checkbox)

用于记录用户的多选选择,将用户选中的值绑定到数据中。比如:

html"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>双向数据绑定指令v-model (实时渲染)</title><style>.textColor{color: red;}</style>
</head><body><div id="app"><h3>您的爱好(多选): {{ data.checkbox }}</h3><input type="checkbox" v-model="data.checkbox" value="足球">足球<input type="checkbox" v-model="data.checkbox" value="蓝球">蓝球<input type="checkbox" v-model="data.checkbox" value="羽毛球">羽毛球<hr></div><script type="module">import { createApp, reactive } from './vue.esm-browser.js'createApp({setup() {const data = reactive({checkbox: [], })return {data}}}).mount("#app")</script>
</body>

运行结果如下:

 当用户勾选或取消勾选选项时,checkbox数组会添加或删除相应选项的value值,页面上显示checkbox数组内容的部分也会更新。

(4)单个复选按钮的双向数据绑定

单个复选按钮的双向绑定把复选按钮的选中状态(视图层面)和一个布尔类型的数据(模型层面)关联起来。用户点击复选按钮改变其选中状态,这个状态变化会被“传递”给绑定的数据,使该数据变为true(选中时)或false(未选中时)。常用于网页登录的“记住密码”,如:

html"><!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>双向数据绑定指令v-model (实时渲染)</title><style>.textColor{color: red;}</style>
</head><body><div id="app"><h3>需要记住密码?  {{ data.remember }} </h3><input type="checkbox" v-model="data.remember">记住密码</div><script type="module">import { createApp, reactive } from './vue.esm-browser.js'createApp({setup() {const data = reactive({remember: false, })return {data}}}).mount("#app")</script></body>
</html>

运行结果如下:

当用户点击记住密码时,返回true的值

(5)下拉框(select)

绑定用户选择的下拉项的值。如:

html"><head><style>.textColor{color: red;}</style>
</head>
<body><div id="app"><h3>下拉选择,您的专业是: {{ data.select }}</h3>  <select v-model="data.select"><option value="计算机">计算机</option><option value="数字媒体">数字媒体</option><option value="中医养生">中医养生</option><option value="针灸推拿">针灸推拿</option></select></div><script type="module">import { createApp, reactive } from './vue.esm-browser.js'createApp({setup() {const data = reactive({select: ""  })return {data}}}).mount("#app")</script>
</body>

运行结果如下:

 

 当用户在下拉框中选择一个选项时,select数据会更新为所选选项的value值,页面上显示select的内容也会相应改变。

二、计算属性

1、基本概念

计算属性(computed)是基于响应式数据进行计算得到的值。计算属性会根据它所依赖的数据的变化而自动重新计算,并且计算结果会被缓存起来

2、实际应用

平时我们在网上购物时,选择多个商品或选多数量时,在购物车下方会计算商品的总数或价格,我们用其中的总数举例。

html"><body><div id="app"><h3>购买水果总数量为: {{ add() }}</h3>   苹果购买数量: <input type="text" v-model.number="data.x"> <br>香蕉购买数量:<input type="text" v-model.number="data.y"> <br></div><script type="module">import { createApp, ref, reactive, computed } from './vue.esm-browser.js'createApp({setup() {const data = reactive({x: "",y: "",})//方法-不做缓存const 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>

运行结果如下:

当用户输入购买数量时,sub函数会实时增加数量,计算购买总数量。

 代码分析:

①add方法是一个普通的函数,当被调用时会在控制台输出相应信息,并返回data.x与data.y相加的结果。这里每次调用add方法都会重新执行该函数内的逻辑,不会对结果进行缓存

②sub是通过computed函数创建的计算属性。当它所依赖的data.x和data.y发生变化时,会自动重新计算结果,并在控制台输出相应信息。而且计算属性会对结果进行缓存,只有在其依赖的数据发生改变时才会重新计算,相比于普通方法在性能上可能更优(当多次获取结果且依赖数据未变时)。

3、优势

  • 计算属性会缓存计算结果。比如:当购物车内的商品只修改了名称,但其价格和数量没有被改变时,计算属性中计算总数量和总价便不会重新计算,因为他们所依赖的数据没有发生变化,这样也可以更好地避免进行过多的计算
  • 当计算机属性所依赖的数据发生变化时,计算的数据也会实时更新,这也能确保数据的有效性

三、侦听器

1、基本概念

计算属性允许我们声明性地计算衍生值。然而在有些情况下,我们需要在状态变化时执行一些“副作用”:例如更改 DOM,或是根据异步操作的结果去修改另一处的状态,而此时我们可以利用侦听器。

侦听器(watch)用于观察和响应数据的变化。他允许数据在发生变化时执行特定的操作。比如:异步操作等。

2、实际应用

当用户选择选项后在后台弹出提示,比如:

html"><body><div id="app"><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, ref, reactive, watch } from './vue.esm-browser.js'createApp({  setup() {const date = reactive({       //日期year: "2023",month: "10"})watch( () => date.year,     (newValue, oldValue) => {console.log("date.year的旧值:", oldValue, " --> date.year的新值:", newValue)if (date.year == "2024") {console.log("您选中的年份是:2024年")}})return {  date }}}).mount("#app")</script>
</body>

 在这个例子中,watch函数监听data对象。当data对象发生变化时,回调函数就会被执行,并且可以获取到变化后的新值(newValue)和变化前的旧值(oldValue)。即用户选择了2024后,控制台则会输出上一个年份和用户当前选择的年份,如下图:

注:代码中的初始年份为2023

3、与计算机属性的区别

(1)计算属性:是基于依赖数据计算得到一个值,并且有缓存机制。只要依赖数据不变,计算属性的值就不会重新计算。它主要用于根据已有数据计算出一个新的值用于显示等场景。

(2)侦听器:重点在于监听数据的变化,然后执行副作用操作(如发送网络请求、修改其他数据等)。它没有计算属性那样的缓存机制,每次数据变化都会执行回调函数

四、实践项目:实现购物车功能

通过Vue的学习,我们可以更好地利用他们的特性,制作一个购物车,实现以下从左图到右图的效果,用户通过点击“+”或“—”的按钮选择购买商品的数量,在文本框内输入商品单价后会自动计算所购买的商品总数和总价

 在实现该项目时,我们可以先制作一个简单的框架

html"><!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>实战小项目:购物车</title><style>body {font-family: Arial, sans-serif;}.cart-item {width: 50%;margin-bottom: 15px;padding: 10px;border: 2px solid gray;border-radius: 10px;background-color: #ddd;}.buttons {margin-top: 5px;}.buttons button {padding: 5px 10px;margin-right: 5px;font-size: 16px;cursor: pointer;border: none;border-radius: 3px;background-color: pink;}.buttons input {width: 25px;}.buttons button:hover {background-color: yellow;}.quantity {font-size: 18px;font-weight: bold;margin-left: 10px;}h1, h2 {color: #333;}</style>
</head>
<body><div id="app" ><h1>实战小项目:购物车</h1><div class="cart-item" ><div class="buttons"><span>苹果&nbsp;&nbsp;</span><button >-</button><span class="quantity">1 &nbsp;&nbsp;</span><button >+</button><p>请输入价格:<input type="text" /> 元/斤 <br> 单价:1 元/斤</p></div></div><h3>商品总数:  <ins> 1 </ins> 件</h3><h3>商品总价:  <ins> 1 </ins> 元</h3></div>
</body>
</html>

该代码包含了HTML和CSS样式, 这其中包含着之前的知识点,大家可以查看前面相关博客进行书写,也可以复制该代码,运用Vue的相关属性实现购物车的功能。

1、创建一个Vue应用程序

html" title=javascript>javascript"><script>
createApp({setup() {}}).mount("#app")
</script>

接下来我们就在该代码内实现我们想要的效果

2、插入数组

        使用reactive函数创建了一个名为cartItems的响应式数组,数组内包含了三个初始商品对象,每个对象有name(商品名称)、quantity(商品数量)、price(商品价格)三个属性,初始值分别设定了一些默认值(如数量和价格都为0),用于存储购物车中的商品信息。随着用户在页面上的操作(如调整数量、输入价格),这些数据会实时更新

html" title=javascript>javascript">const cartItems = reactive([{ name: '苹果', quantity: 0, price: 0 },{ name: '香蕉', quantity: 0, price: 0 },{ name: '菠萝', quantity: 0, price: 0 }]);

增加数组后我们要将其遍历出来则可以使用v-for指令,假设有n个商品,则生成n个商品项(&nbsp;&nbsp;为空格

html" title=javascript>javascript">  <div class="cart-item" v-for="(item, index) in cartItems"> <span>{{item.name}}&nbsp;&nbsp;</span><span class="quantity">{{cartItems[index].quantity}}&nbsp;&nbsp;</span></div></div>

3、增加或减少商品数量

首先在button元素内设置按键,用于用户增加或减少商品数量,通过v-on:click指令绑定按钮

html" title=javascript>javascript"><button v-on:click="decreaseQuantity(index)">-</button><button v-on:click="increaseQuantity(index)">+</button>

两行代码分别位于商品名称的左右,代码如下:

html" title=javascript>javascript"><button v-on:click="decreaseQuantity(index)">-</button>
<span class="quantity">{{cartItems[index].quantity}}&nbsp;&nbsp;</span>
<button v-on:click="increaseQuantity(index)">+</button>

接下来在script元素内接受一个index参数,用于指定要增加数量的商品在cartlItems数组中的索引位置,在内部将商品的数量加1,实现增加数量的功能。

html" title=javascript>javascript">  const increaseQuantity = (index) => {cartItems[index].quantity++;};

 与加法类似,在内部将商品的数量减1,实现减少数量的效果,但在减1之前应该先判断商品数量(quantity)是否大于0,是则减1,但要限制数量不能少于0

html" title=javascript>javascript"> const decreaseQuantity = (index) => {if (cartItems[index].quantity > 0) {cartItems[index].quantity--;}};

其中decreaseQuantity(index)和increaseQuantity(index),其中index作为商品在cartItems数组内的索引

4、输入价格

通过v-model双向绑定指令,使其能够实时更新商品的价格,同时在下面展示输入单价。

html"><p>请输入价格:<input type="text" v-model="cartItems[index].price" /> 元/斤 <br>单价:{cartItems[index].price}} 元/斤
</p >

5、计算总价和总数量

通过computed函数创建一个totalItems属性,这样当购物时商品数量增加或减少可以实时更新

①使用reduce方法,在该函数内有两个参数(total,item),其中total作为累加器,初始值为0(由reduce函数的第二个参数指定),它会累计每次回调函数执行后的结果。item是cartItems数组中的每个商品对象。在每次回调执行时,将当前商品对象的quantity属性值累加到total上,这样遍历完整个cartItems数组后,total就得到了所有商品数量的总和。

html" title=javascript>javascript">const totalItems = computed(() => {return cartItems.reduce((total, item) => total + item.quantity, 0);});

扩展

reduce函数:用于将数组中的元素通过某种方式累积为一个单一的值。它可以对数组中的每个元素执行一个由用户提供的回调函数,把这个函数的返回值不断累积,最后返回一个最终结果。

举个例子:

html" title=javascript>javascript">const numbers = [1, 2, 3, 4, 5];
const sum = numbers.reduce((a, b) => {return a + b;}, 0);

在该代码中初始值0提供给了a,b的值为1,返回0+1=1作为新的a的值;第二次则a为1,b为2,返回1+2=3作为a的值,以此类推。

②通过reduce函数我们也可以实现计算商品总价的功能

html" title=javascript>javascript">const totalPrice = computed(() => {return cartItems.reduce((total, item) => total + (item.quantity * item.price), 0);});

6、return语句

最后通过return语句将对象和方法暴露出来,使得它们可以在HTML模板中进行数据绑定和方法调用,让Vue实例与页面元素关联起来,从而实现整个购物车功能在页面上的呈现和交互。

html" title=javascript>javascript"> return {cartItems,totalItems,totalPrice,increaseQuantity,decreaseQuantity};

该示例可以清晰地看到如何运行Vue的各种属性,通过事件绑定、计算属性等来构建一个简单而使用的购物车应用。大家也来试试看吧!

完整代码如下;

html"><!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>实战小项目:购物车</title><style>body {font-family: Arial, sans-serif;}.cart-item {width: 50%;margin-bottom: 15px;padding: 10px;border: 2px solid gray;border-radius: 10px;background-color: #ddd;}.buttons {margin-top: 5px;}.buttons button {padding: 5px 10px;margin-right: 5px;font-size: 16px;cursor: pointer;border: none;border-radius: 3px;background-color: pink;}.buttons input {width: 25px;}.buttons button:hover {background-color: yellow;}.quantity {font-size: 18px;font-weight: bold;margin-left: 10px;}h1, h2 {color: #333;}</style>
</head><body><div id="app"><h1>实战小项目:购物车</h1><!-- 提示:可以使用v-for指令,假设有n个品类,则生成n个商品项--><div class="cart-item" v-for="(item, index) in cartItems"><div class="buttons"><span>{{item.name}}&nbsp;&nbsp;</span><button v-on:click="decreaseQuantity(index)">-</button><span class="quantity">{{cartItems[index].quantity}}&nbsp;&nbsp;</span><button v-on:click="increaseQuantity(index)">+</button><p>请输入价格:<input type="text" v-model="cartItems[index].price" /> 元/斤 <br>单价:{{cartItems[index].price}} 元/斤</p ></div></div><!-- 提示:可以用计算属性或数据变动侦听器,跟踪商品数和单价的变化,进而求出总数和总价--><h3>商品总数: <ins> {{totalItems}} </ins> 件</h3><h3>商品总价: <ins> {{totalPrice}} </ins> 元</h3></div><script type="module">import { createApp, reactive, computed } from './vue.esm-browser.js';createApp({setup() {const cartItems = reactive([{ name: '苹果', quantity: 0, price: 0 },{ name: '香蕉', quantity: 0, price: 0 },{ name: '菠萝', quantity: 0, price: 0 }]);// 计算商品总数const totalItems = computed(() => {return cartItems.reduce((total, item) => total + item.quantity, 0);});// 计算商品总价const totalPrice = computed(() => {return cartItems.reduce((total, item) => total + (item.quantity * item.price), 0);});const increaseQuantity = (index) => {cartItems[index].quantity++;};const decreaseQuantity = (index) => {if (cartItems[index].quantity > 0) {cartItems[index].quantity--;}};return {cartItems,totalItems,totalPrice,increaseQuantity,decreaseQuantity};}}).mount('#app');</script>
</body></html>


http://www.ppmy.cn/news/1549608.html

相关文章

机器翻译基础与模型 之三:基于自注意力的模型

基于RNN和CNN的翻译模型&#xff0c;在处理文字序列时有个问题&#xff1a;它们对序列中不同位置之间的依赖关系的建模并不直接。以CNN的为例&#xff0c;如果要对长距离依赖进行描述&#xff0c;需要多层卷积操作&#xff0c;而且不同层之间信息传递也可能有损失&#xff0c;这…

Spark 中的 Shuffle 是分布式数据交换的核心流程,从源码角度分析 Shuffle 的执行路径

Spark 中的 Shuffle 是分布式数据交换的核心流程&#xff0c;涉及多个组件的协同工作。为了深入理解其处理过程&#xff0c;我们可以从源码角度分析 Shuffle 的执行路径&#xff0c;分为 Shuffle Write 和 Shuffle Read 两个阶段。 1. Shuffle Write 阶段 Shuffle Write 的主要…

11/19使用Spring,gradle实现前后端交互

创建 Gradle 项目 在你常用的 IDE&#xff08;如 Intellij IDEA&#xff09;中选择创建新的 Gradle 项目&#xff0c;按照向导进行相应的配置&#xff0c;选择合适的项目名称、目录等信息。配置 build.gradle 文件&#xff08;Gradle 项目的配置文件&#xff09;&#xff0c;添…

蚁群算法(Ant Colony Optimization, ACO)

简介 蚁群算法&#xff08;Ant Colony Optimization, ACO&#xff09;是一种基于自然启发的优化算法&#xff0c;由意大利学者马可多里戈&#xff08;Marco Dorigo&#xff09;在1992年首次提出。它受自然界中蚂蚁觅食行为的启发&#xff0c;用于解决离散优化问题。 在自然界…

jquery还有其应用场景,智慧慢慢地被边缘化,但不会消亡

一、jQuery 的辉煌过往 jQuery 的诞生与崛起 在前端开发的漫长历史中&#xff0c;2006 年诞生的 jQuery 犹如一颗耀眼的新星划破天际。它由 John Resig 创造&#xff0c;一出现便以其独特的魅力迅速吸引了广大开发者的目光。在那个前端技术发展相对缓慢的时期&#xff0c;jQue…

ESP32移植Openharmony外设篇(6)光敏电阻ADC读取

光照传感器 模块简介 产品描述 光敏电阻&#xff08;photoresistor orlight-dependent resistor&#xff0c;后者缩写为LDR&#xff09;是一种基于内光电效应的半导体元件&#xff0c;它的阻值依赖于入射光强的变化 。入射光强增加&#xff0c;光敏电阻的阻值减小&#xff0…

apr共享内存

下载&#xff1a; Download - The Apache Portable Runtime Project 编译&#xff1a; 使用cmake-gui生成库&#xff1a; apr-1.lib aprapp-1.lib libapr-1.lib libaprapp-1.lib libapr-1.dll 在Developer PowerShell for VS 2019中&#xff1a; 执行nmake -f Makefile.win来…

什么是“数学活动”?

数学活动嘛&#xff0c;不就是关于数学的活动&#xff0c;还有什么可说的&#xff1f;非也&#xff0c;且看下面定义。 一、不同人的定义&#xff1a; ① “数学活动”是指在数学教学过程中&#xff0c;以学生学习兴趣和内在需要为基础&#xff0c;以主动探索、变革、改造对象…