Vue2-自定义创建项目、ESLint、Vuex及综合案例购物车

news/2025/3/19 12:34:10/文章来源:https://www.cnblogs.com/yuanyu610/p/18780789

Vue2


自定义创建项目

基于VueCli自定义创建项目架子

步骤:

  1. 安装VueCLI脚手架npm i @vue/cli -g 可以通过vue --version 判断是否下载VueCLI

  2. 在某个文件夹中创建vue项目vue create 项目名称 (项目名中不能包含大写字母)

  3. 选择Manually select features

  4. 选择Babel(语法降级)、Router、CSS Pre-processors、Linter(ES规范) (空格可选中)

  5. 选中Vue2

  6. 选择CSS预处理器为less

  7. 选中Lint为ESLint + Standard config 无分号规范、Lint on save保存时校验

  8. 将所有文件放在单独的文件中进行管理In dedicated config files


ESlint代码规范

代码规范:一套写代码的约定规则,如:赋值符号的左右是否需要空格,一句结束是否要加;

正规的团队需要统一的编码风格

JavaScript Standard Style规范说明:https://standardjs.com/rules-zhcn.html

如:

  • 字符串使用单引号:'abc' (单引号的可阅读性高于双引号)

  • 无分号:const name='abc'

  • 关键字后加空格:if (name='ls'){...}

  • 函数名后加空格:function name (arg){...}

  • 坚持使用全等=== 而不是==

  • ......

如果代码不符合standard规范,Eslint会报错,并准确告知具体的行数和字符数

  • 可以根据错误提示来手动修正,参考文档规则参考 - ESLint - 插件化的 JavaScript 代码检查工具

  • 自动修正:基于Vscode插件ESLint高亮错误,并配置实现自动修复错误

    image

    //当保存的时候eslint自动帮助修复错误"editor.codeActionsOnSave": {"source.fixAll":true},//保存代码 不自动格式化"editor.formatOnSave": false //如果是true会与修复错误冲突
    

    在vscode的设置>打开设置中进行上述配置(必须将vscode中的自动保存取消,手动保存才起作用)


Vuex

Vuex是Vue的一个状态管理工具,状态即数据(可以帮助我们管理Vue通用的数据(多组件共享的数据))

image

场景:

  • 某个状态在很多个组件来使用(个人信息)

  • 多个组件共同维护一份数据(购物车)

  • 例:

    • 三个组件共享一份数据

    • 任意一个组件都可以修改数据

    • 三个组件的数据是同步的

优势:

  • 共同维护一份数据,数据集中化管理

  • 响应式变化

  • 操作简洁


Vuex的安装与使用

步骤:

  1. 安装Vuex:npm i vuex@3npm install -d vuex@3

  2. 新建Vuex模块文件:在src>store下新建index.js专门存放Vuex

  3. 创建仓库

    // 存放vuex的核心代码import Vue from 'vue'
    import Vuex from 'vuex'
    // 插件安装
    Vue.use(Vuex)// 创建仓库
    const store = new Vuex.Store()// 导出
    export default store
    
  4. main.js中导入挂载

    import Vue from 'vue'
    import App from './App.vue'
    import store from '@/store/index'Vue.config.productionTip = falsenew Vue({render: h => h(App),store
    }).$mount('#app')
    
  5. 在App.vue中打印store测试仓库是否成功创建

    created () {console.log(this.$store)}
    

    image

Vuex的state状态

提供数据

State提供唯一的公共数据源,所有的共享数据都要统一放到Store中的State中存储

// 创建仓库
const store = new Vuex.Store({state: {title: '嘀嘀嘀',count: 100}
})

state状态即数据,类似于Vue组件中的data,但存在区别:

  • data是组件自己的数据

  • state是所有组件共享的数据

使用数据

  • 通过store直接访问

    • 模板中:{{$store.state.xxx}}

    • 组件逻辑中:this.$store.state.xxx

    • JS模块中:store.state.xxx

  • 通过辅助函数:可以把state中的数据定义在计算属性 中,如

    {{count}}computed(){count(){return this.$store.state.count}
    }
    

    mapState可以帮助把store中的数据自动映射到组件的计算属性

    1. 导入mapState:import {mapState} from 'vuex'

    2. 数组方式引入state:mapState(['count'])

    3. 展开运算符映射:computed:{ ...mapState(['count'])}

    例:

    <template><div class="App"><h1>根组件-{{ title }}-{{ count }}</h1><BaseA></BaseA><BaseB></BaseB></div>
    </template><script>
    import BaseA from './components/BaseA.vue'
    import BaseB from './components/BaseB.vue'
    import { mapState } from 'vuex'export default {components: {BaseA,BaseB},created () {console.log(this.$store)},computed: {...mapState(['count', 'title'])}
    }
    </script><style scoped>.App{border: 1px solid gainsboro;width: 550px;height: 800px;margin: auto;text-align: center;}
    </style>

修改数据-mutations

Vuex同样遵循单向数据流,组件中不能直接修改仓库的数据

可以通过在创建仓库时配置strict:true开启严格模式 如果组件直接修改仓库中的数据会报错

适合初学者,上线时需要关闭 会消耗运行性能

image

state数据的修改只能通过mutations 在实例化store对象的时候定义mutations对象,并在对象中存放修改state的方法

例:

const store = new Vuex.store({state:{count:0},mutations:{addCount(state){state.count+=1}}
})

组件中提交调用mutations

this.$store.commit('addCount')

提交的mutations是可以传递参数的this.$store.commit('xxx',参数)

需要注意的是:传递的参数只能有一个,如果实在要传递多个参数可写成对象的形式

例 :

const store = new Vuex.store({state:{count:0},mutations:{addCount(state,n){ //n被称为提交载荷state.count+=n}}
})

页面中的调用:

this.$store.commit('addCount',10)

如果想实现input组件与state数据的双向绑定:

  1. 输入框内容渲染::value="{{count}}"

  2. 监听输入获取内容:@input

  3. 封装mutations处理函数:mutations传参

  4. 调用传参:commit调用

例:

store>index.js

// 存放vuex的核心代码import Vue from 'vue'
import Vuex from 'vuex'
// 插件安装
Vue.use(Vuex)// 创建仓库
const store = new Vuex.Store({strict: true, // 严格模式,任何直接修改仓库值的代码都会报错// 通过state提供数据state: {title: '嘀嘀嘀',count: 100},// 通过mutations提供修改state的方法mutations: {handleAdd (state, n) {state.count += n},changeCount (state, n) {state.count = n}}
})// 导出
export default store

App.vue

<template><div class="App"><h1>根组件-{{ title }}-{{ count }}</h1><input type="text" :value="count" @input="handleInput"><BaseA></BaseA><BaseB></BaseB></div>
</template><script>
import BaseA from './components/BaseA.vue'
import BaseB from './components/BaseB.vue'
import { mapState } from 'vuex'export default {components: {BaseA,BaseB},created () {console.log(this.$store)},computed: {...mapState(['count', 'title'])},methods: {handleInput (e) {this.$store.commit('changeCount', +e.target.value)}}
}
</script><style scoped>.App{border: 1px solid gainsboro;width: 550px;height: 800px;margin: auto;text-align: center;}
</style>

子组件BaseA.vue

<template><div class="box"><h2>BaseA子组件</h2>从vuex中获取的值:{{count }}<label for=""></label><br><button @click="handleAdd(1)">值+1</button><button @click="handleAdd(5)">值+5</button></div>
</template><script>
import { mapState } from 'vuex'
export default {computed: {...mapState(['count', 'title'])},methods: {handleAdd (n) {this.$store.commit('handleAdd', n)}}
}
</script><style scoped>.box{border: 1px solid gainsboro;width: 400px;height: 300px;margin-bottom: 10px;margin: auto;}
</style>

image

可以通过mapMutations把位于mutations中的方法提取出来映射到组件methods中

例:

// 创建仓库
const store = new Vuex.Store({strict: true, // 严格模式,任何直接修改仓库值的代码都会报错// 通过state提供数据state: {title: '嘀嘀嘀',count: 100},// 通过mutations提供修改state的方法mutations: {handleAdd (state, n) {state.count += n},handleSub (state, n) {state.count -= n},changeCount (state, n) {state.count = n}}
})
<template><div class="box"><h2>BaseB子组件</h2>从vuex中获取的值:{{ count }}<label for=""></label><br><button @click="handleSub(1)">值-1</button><button @click="handleSub(5)">值-5</button></div>
</template><script>
import { mapState, mapMutations } from 'vuex'
export default {computed: {...mapState(['count', 'title'])},methods: {...mapMutations(['handleSub'])}
}
</script>

调用:

this.subCount(10) 
//或 @click="handleSub(10)

actions

actions用于专门处理异步操作 (mutations中的内容必须是同步的,便于监测数据变化,记录调试

例:在1s之后将state中的count修改为111

// 创建仓库
const store = new Vuex.Store({strict: true, // 严格模式,任何直接修改仓库值的代码都会报错// 通过state提供数据state: {title: '嘀嘀嘀',count: 100},// 通过mutations提供修改state的方法mutations: {handleAdd (state, n) {state.count += n},handleSub (state, n) {state.count -= n},changeCount (state, n) {state.count = n}},// actions 处理异步,不能直接操作state,还是需要通过commit来操作actions: {// context 上下文 (由于此处未分模块,可以当成仓库store使用)// context.commit('mutations',参数)changeCountAction (context, num) {// 使用setTimeout模拟异步setTimeout(() => {context.commit('changeCount', num)}, 1000)}}
})

页面中调用:

<button @click="handleChange(111)">一秒后修改为111</button>methods: {handleAdd (n) {this.$store.commit('handleAdd', n)},handleChange (n) {this.$store.dispatch('changeCountAction', n)}}

可以通过辅助函数mapActions把位于actions中的方法提取出来映射到组件methods中

例:

action:{changeCountAction(context,num){setTimeout(()=>{context.commit('changeCount',num)},1000)}
}
import {mapActions} from 'vuex'methods:{...mapActions(['changeCountAction'])
}

调用:

this.changeCountAction(111)

getters

类似于计算属性,有时需要从state中派生出一些状态,这些状态是依赖state的,此时需要使用getters

例:
state中定义了list数组,范围是1-10,组件中需要显示出大于5的值

state:{list:[1,2,3,4,5,6,7,8,9,10]
}

定义getters:

getters:{filterList(state){return state.list.filter(item=>item>5)}
}

访问getters:必须有返回值

  • 通过store访问getters:{{$store.getters.filterList}}

  • 通过辅助函数mapGetters映射 由于映射的是属性,因此需要放在计算属性中调用

    computed:{...mapGetters(['filterList'])
    }{{filterList}}
    

module模块

由于vuex使用单一状态树应用的所有状态会集中到一个较大的对象

当应用变得非常复杂时,store对象就有可能变得相当臃肿

(当项目变得越来越大的时候,vuex会变得越来越难以维护)

//单一状态树
state:{userInfo:{name:'yuanyu'age:24},theme:'dark',desc:'嘀嘀嘀'
}

image

步骤:

  1. 在store文件夹下新建modules文件夹,在文件夹中新建各模块的JS文件,如user.js、setting.js

  2. 每个模块有自己对应的state、mutations、actions、getters

    const state = {}
    const mutations = {}
    const actions = {}
    const getters = {}
    
  3. 将这四个配置项导出

    export default {state,mutations,actions,getters
    }
    
  4. 将创建的模块文件导入store文件夹下的index.js

    import user from './modules/user'const store = new Vuex.Store({strict: true, // 严格模式,任何直接修改仓库值的代码都会报错// 通过state提供数据state: {title: '嘀嘀嘀',count: 100},// 通过mutations提供修改state的方法mutations: {handleAdd (state, n) {state.count += n},handleSub (state, n) {state.count -= n},changeCount (state, n) {state.count = n}},// actions 处理异步,不能直接操作state,还是需要通过commit来操作actions: {// context 上下文 (由于此处未分模块,可以当成仓库store使用)// context.commit('mutations',参数)changeCountAction (context, num) {// 使用setTimeout模拟异步setTimeout(() => {context.commit('changeCount', num)}, 1000)}},modules: {user}
    })

模块中的state

尽管已经分模块了,但是子模块的state还是会挂到根级别的state中,属性名就是模块名

  • 直接通过模块名访问$store.state.模块名.xxx

    如:<div>{{ $store.state.user.userInfo.name }}</div>

  • 通过mapState映射

    • 默认根级别的映射mapState(['xxx'])

    • 子模块的映射mapState('模块名',['xxx']) 需要开启命名空间namespaced:true

      export default {namespaced: true,state,mutations,actions,getters
      }
      

      例:

      import { mapState } from 'vuex'
      export default {computed: {...mapState(['count', 'title', 'user']),...mapState('user', ['userInfo']) //'模块名',['模块中的数据']}}<div>{{ user.userInfo.name }}</div>
      <div>{{ userInfo.name }}</div>
      

模块中的getters

  • 直接通过模块名访问$store.getters['模块名/xxx']

  • 通过mapGetters映射

    • 默认根级别映射mapGetters(['xxx'])

      如:<div>{{ $store.getters['user/UpperCaseName'] }}</div>

    • 子模块的映射mapGetters('模块名',['xxx']) 需要开启命名空间

      <div>{{ UpperCaseName }}</div>import { mapState, mapGetters } from 'vuex'
      export default {computed: {...mapState(['count', 'title', 'user']),...mapState('user', ['userInfo']),...mapGetters('user', ['UpperCaseName'])}}
      

模块中的mutations

默认模块中的mutation和actions会被挂载到全局,需要开启命名空间才会被挂载到子模块

调用子模块中的mutations:

  • 直接通过store调用:$store.commit('模块名/xxx',额外参数)

    例:

    <button @click="updateUser">更新个人信息</button>methods: {updateUser () {this.$store.commit('user/setUser', {name: '111',age: 22})}}const mutations = {setUser (state, newUserInfo) {state.userInfo = newUserInfo}
    }
    

  • 通过mapMutations映射

    • 默认根级别的映射mapMutations(['xxx'])

    • 子模块的映射mapMutations('模块名',['xxx']) 需要开启命名空间

      <button @click="setUser({name:'2222',age:12})">更新个人信息</button>methods: {...mapMutations('user', ['setUser'])}
      

模块中的actions调用

  • 直接通过store调用$store.dispatch('模块名/xxx',额外参数)

  • 通过mapActions映射

    • 默认根级别的映射mapAction(['xxx'])

      例:

      <button @click="update2">一秒后更新信息</button>update2 () {this.$store.dispatch('user/setUserSecond', {name: '111',age: 22})}const actions = {setUserSecond (context, newInfo) {setTimeout(() => {context.commit('setUser', newInfo)}, 1000)}
      }
      

    • 子模块的映射mapActions('模块名',['xxx']) 需要开启命名空间

      <button @click="setUserSecond({name: '111',age: 22})">一秒后更新信息</button>methods:{...mapActions('user', ['setUserSecond'])
      }const actions = {setUserSecond (context, newInfo) {setTimeout(() => {context.commit('setUser', newInfo)}, 1000)}
      }
      

综合案例-购物车

功能模块分析:

  1. 请求动态渲染购物车,数据存vuex

  2. 数字框控件修改数据

  3. 动态计算总价和总数量


步骤:

  1. 使用VueCLI新建项目(勾选less、ESLint、Vuex、Babel)

  2. 创建子组件并在根组件中引入,搭建框架

  3. 构建购物车store模块

    export default {namespaced: true,state () {return {// 购物车数据list: []}},mutations: {},getters: {},actions: {}
    }
    
    import Vue from 'vue'
    import Vuex from 'vuex'
    import cart from './modules/cart'Vue.use(Vuex)export default new Vuex.Store({modules: {cart}
    })
    
  4. 请求获取数据:

    当后端接口还为准备就绪时,可利用json-server快速生成增删改查的接口

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/901466.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

yum install -y devtoolset-8-gcc*

如果执行结果为上面这个结果的话,需要执行以下操作 yum install centos-release-scl*修改CentOS-SCLo-scl.repo文件 baseurl=https://mirrors.aliyun.com/centos/7/sclo/x86_64/rh/ 和 gpgcheck=0修改CentOS-SCLo-scl-rh.repo文件和上面一样查看 [root@iZbp153shsqfoddljmkit4…

几个技巧,教你去除文章的 AI 味!

给大家分享一些快速去除文章 AI 味的小技巧,有些是网上被分享过的,也有些是我个人的经验。学会之后,无论是写工作文案、毕业设计、自媒体文章,还是平时生活中写写好评,都是非常轻松的。最近有不少朋友在利用 AI 写毕业设计论文,几秒钟一篇文章就刷出来的,爽的飞起。 结果…

Sci Chart中的XyDataSeries与UniformXyDataSeries

在 SciChart 中,XyDataSeries 和 UniformXyDataSeries 是两种用于处理数据序列的核心类,主要差异体现在数据存储方式、性能优化及适用场景上。 以下是具体对比: 1. 数据存储与结构差异 **XyDataSeries<TX, TY>** 需要同时存储 X 和 Y 值的完整坐标对。例如,对于每个数…

强化学习基础_基于价值的强化学习

Action-Value Functions 动作价值函数 折扣回报(Discounted Return) 折扣回报 Ut 是从时间步 t 开始的累积奖励,公式为: Rt 是在时间步 t 获得的奖励。γ 是折扣因子(0<γ<1),用于减少未来奖励的权重。这是因为未来的奖励通常不如当前奖励重要,例如在金融领域,未…

USB杂谈

一、USB控制器 OHCI 1.0、1.1控制器 UHCI:1.0、1.1控制器 EHCI 2.0控制器 XHCI 3.0控制器 EHCI 2.0控制器 HID:人机交互接口,鼠标、手柄 、键盘、扫描枪USB协议中对集线器的层数是有限制的,USB1.1规定最多为5层,USB2.0规定最多为7层。 理论上,一个USB主控制器最多可接127个…

2025年3月中国数据库排行榜:PolarDB夺魁傲群雄,GoldenDB晋位入三强

2025年3月排行榜解读出炉,榜单前四现波动,PolarDB时隔半年重返榜首、GoldenDB进入前三,此外更有一些新星产品表现亮眼!欢迎阅读、一起盘点~阳春三月,万物复苏。2025年3月中国数据库流行度排行榜的发布,不仅展现了中国数据库企业在技术创新、生态建设和应用深化方面的显著…

# 20241902 2024-2025-2 《网络攻防实践》第四周作业

1.实验内容 通过本次实验,在搭建的实验环境中完成TCP/IP协议栈重点协议的攻击实验,包括ARP缓存欺骗攻击、ICMP重定向攻击、SYN Flood攻击、TCP RST攻击、TCP会话劫持攻击,并熟悉wireshark、netwox和ettercap等软件的操作。 2.实验过程 实验1 ARP缓存欺骗攻击 本实验中Kali为…

【Azure Fabric Service】分享使用Visual Studio 2022发布中国区Service Fabric服务应用的办法

问题描述 使用Visual Studio 2022如何发布Service Fabric到中国区云服务呢? 因为使用VS2022中的插件无法创建Service Fabric Cluster服务。那么,是否又比较好的替代方案呢?问题解答 是的,有替代方案。 除了昨天介绍使用的Powershell命令外( 【Azure Fabric Service】演示使…

如何让GameObject销毁时无论是否Active过,都调用OnDestroy

1)如何让GameObject销毁时无论是否Active过,都调用OnDestroy2)升级到URP画面会提升吗3)如何用Dynamic Mesh做出在墙上打洞的效果4)UE可以把烘焙好的光照贴图导出吗这是第424篇UWA技术知识分享的推送,精选了UWA社区的热门话题,涵盖了UWA问答、社区帖子等技术知识点,助力…

测序芯片-不同键合工艺对比-flowcell-代加工-外协加工-委外加工-激光代加工-河南郑州-芯晨微纳(河南)

基因测序(包括DNA测序和RNA测序)是研究生命信息的重要方法之一。DNA测序(DNA sequencing,或译DNA定序)是指分析特定DNA片段的碱基序列, 也就是腺嘌呤(A)、胸腺嘧啶(T)、胞嘧啶(C)与鸟嘌呤(G)的排列方式。同理,RNA测序是指分析特定RNA片段的碱基序列,也就是腺嘌呤(A)、鸟嘌呤…