写点什么

前端开发之 VUE 基础面试题分享

  • 2022 年 1 月 14 日
  • 本文字数:4849 字

    阅读完需:约 16 分钟

​vue 传值方式

vue 传值

  1. 父 子 传值 使用 props 接受

  2. 子 父 传值 父亲写事件函数 子 $emit 触发 传值

  3. 兄弟传值 $bus 中转站

  4. 如果组件之间 关系很远 是很多组件都要用的值 vuex

  5. provide, inject 注入方式

vuex 就是一个全局状态数据管理 简单来说 他的数据类似全局变量 哪个组件都可以使用


在项目中使用 vuex


下载 vuex 包 并导入 use 一下


import Vuex from 'vuex'Vue.use(Vuex)
复制代码


需要 new 一下 写上全局数据

// storenew Vuex.Store({state: {count:1 //这个count 就是全局的数据},mutations: {},actions: {}})

复制代码


需要挂载到 new vue 上


new Vue({router,store,render: h => h(App)}).$mount('#app')
复制代码


<!-- <hr> --><!-- <my-swiper :list="list"></my-swiper> -->
<button @click="getAll">发送请求</button>
home组件啊<hr><h1>count的值:{{$store.state.count}}</h1><button @click="addCount">让全局count+1</button><hr><h2>m1下的全局数据 {{$store.state.m1.m1Name}} </h2> <button @click="add">点击修改某个模块的数据</button>
<!-- 3 哪个组件要用 就直接 使用注册的组件标签名 --> <hr> <!-- 用组件 传了list数据进去 --> <my-swiper :list="list"></my-swiper>
复制代码


</div></template>


<script>// 要在组件使用全局数据// 1 在 html 范围 直接 store.state.名字


// @ is an alias to /src// import HelloWorld from '@/components/HelloWorld.vue'import { mapMutations , mapActions ,mapState } from 'vuex'export default {name: 'Home',components: {// HelloWorld},data(){return {list:[{id:1,src:'http://122.51.238.153/images/1.jpg'},{id:2,src:'http://122.51.238.153/images/2.jpg'},{id:3,src:'http://122.51.238.153/images/3.jpg'},{id:4,src:'http://122.51.238.153/images/4.jpg'}]}},created(){console.log('created')console.log('store',this.store)},mounted(){console.log("home 的 mounted")},methods:{// 这句话的意思是 直接 解构出 全局 m1模块下的 loginMutation// 把loginMutation 放到this上 并且帮你写好了 commit// 相当于帮你简化了代码...mapMutations('m1', ['loginMutation']),//不是modules的直接写 ...mapMutations( ['loginMutation'])add(){// console.log('add',this)// console.log('add',this.route.meta)// this.store.commit("m1/loginMutation")// 和刚刚的思路 就是加上一个模块前缀 m1/// this.store.dispatch("m1/loginAction")},async getAll(){// http://localhost:8080/// 请求 http://122.51.238.153/getok.php// let res=await this.http.get("http://122.51.238.153/getok.php")// console.log('res',res)let res=await this.http.get("/api/getok.php")console.log('res',res)},addCount(){// 让全局数据count+1// 1 正常情况// dispatch 触发action// -》commit触发mutation// -》在mutation修改全局数据//2 其他情况 可以直接跳过action 但是必须mutation修改// console.log('store',this.store.dispatch( 'countAction' )this.$store.commit("countMutation")}}}</script>


这个步骤是写死的 你可以记一下 下载使用脚手架直接就可以选 vuex


他的使用逻辑是什么?


在 store 里面的 state 写的数据 前端培训是全局数据 所有组件都可以使用


使用逻辑


操作全局 vuex 的 state 数据


正常情况 必须 dispatch (action)--->action 去 commit 触发 mutation--》mutation 里面才能修改 state 全局数据


action--->mutation--->修改 state


其他情况 你也可以跳过 action 去 直接 commit mutation--》修改 state 全局数据


vuex 怎么合理规范管理数据,及 mutations 和 actions 区别解析: 此题考查 vuex 中数据的管理和数据结构的设计,还有 mutations 和 actions 的区别


解答 : 首先要明确一个特别重要的原则, 就是 不是所有的数据都要放在 vuex 中, 因为 vuex 有一句名言:假如你并不知道为什么要使用 vuex,那就不要使用它 !


那么什么样式的数据需要放在 vuex 中呢 ? 首先这个数据肯定要被多个组件频繁用到, 如果只是被一个组件 用到, 那完全没有任何必要为了使用 vuex 和使用 vuex


举例: 一个网站用户的昵称,账号,资料,像这种系统级别的信息 随时可能在业务中展示,使用, 如果在组件中存储, 那么要获取 N 次, 所以系统级别的数据是需要放置在 vuex 中的, 那么系统级别数据 也不能所以的放置,为了让数据看着更有层级结构感,可以按照像下面这样设计,


{// 系统消息 system: {user: {},setting: {}}}


上面这种结构,一看 便知道我们应该哪里获取系统数据即 设置数据


如果有些业务数据,也需要共享,最好按照模块的具体业务含义分类 , 比如下面


{// 系统消息 system: {user: {},setting: {}},product: {productList: [], // 商品信息列表 productOrders: [] // 商品订单啊列表}}


如代码所示,我们很清晰的能够分清楚 每个模块的数据,这样不会导致数据管理的混乱


mutations 和 actions 的区别不同于 redux 只有一个 action, vuex 单独拎出了一个 mutations, 它认为 更新数据必须是同步的, 也就是只要调用了 提交数据方法, 在 mutation 里面才可以修改数据


那么如果我们想做 异步请求,怎么做? 这里 vuex 提供了专门做异步请求的模块,action, 当然 action 中也可以做同步操作, 只不过 分工更加明确, 所有的数据操作北京前端培训不论是同步还是异步 都可以在 action 中完成,


mutation 只负责接收状态, 同步完成 数据快照


所以可以认为


state => 负责存储状态


mutations => 负责同步更新状态


actions => 负责获取 处理数据(如果有异步操作必须在 action 处理 再到 mutation), 提交到 mutation 进行状态更新


vuex 模块化 module 管理,使用的时候有注意事项分析: 此题考查 当 vuex 维护的数据越来越复杂的时候, 模块化的解决方案


解析:使用单一的状态树,应用的所有状态都会集中在一个比较大的对象上面,随着项目需求的不断增加,状态树也会变得越来越臃肿,增加了状态树维护的复杂度,而且代码变得沉长;因此我们需要 modules(模块化)来为我们的状态树分隔成不同的模块,每个模块拥有自己的 state,getters,mutations,actions;而且允许每个 module 里面嵌套子 module;如下:


store├── index.js # 我们组装模块并导出 store 的地方├── actions.js # 根级别的 action├── mutations.js # 根级别的 mutation├── state.js # 根级别的 state└── modules├── module1.js # 模块 1 的 state 树└── module2.js # 模块 2 的 state 树


上面的设计中, 每个 vuex 子模块都可以定义 state/mutations/actions


需要注意的是 我们原来使用 vuex 辅助函数 mapMutations/mapActions 引入的是 全局的的 mutations 和 actions , 并且我们 vuex 子模块 也就是 module1,module2 ... 这些模块的 aciton /mutation 也注册了全局,


也就是如果 module1 中定义了 loginMutation, module2 中也定义了 loginMutation, 此时, mutation 就冲突了


如果重名,就报错了.....


如果不想冲突, 各个模块管理自己的 action 和 mutation ,需要 给我们的子模块一个 属性 namespaced: true


那么 组件中怎么使用子模块的 action 和 mutations


// 你可以将模块的空间名称字符串作为第一个参数传递给上述函数,这样所有绑定都会自动将该模块作为上下文 methods:{...mapMutations('m1', ['loginMutation']),add(){console.log('add',this)// this.$store.commit("m1/loginMutation")// 或者下面的 先 mapMutations 相当于帮你写了 commit// this.loginMutation()}}


 // 这句话的意思是 直接 解构出 全局 m1模块下的 loginMutation // 把loginMutation 放到this上 并且帮你写好了 commit// 相当于帮你简化了代码 ...mapMutations('m1', ['loginMutation']),   //不是modules的直接写  ...mapMutations( ['loginMutaton])
复制代码


store.js


import Vue from 'vue'import Vuex from 'vuex'Vue.use(Vuex)// 1 下载 vuex 导入 use 一下// 2 new Vuex.Store// 3 挂载到 new vue 上 export default new Vuex.Store({state: {// 在这里写的就是所有组件都能有 全局数据了// 名字:值// 如果我 1000 个全局数据 有可能重名 count:100},mutations: {countMutation(state){// state 就是那个全局 stateconsole.log('mutation 触发了',state)state.count++}},actions: {// action 对应的函数 countAction(obj){console.log('action 触发了',obj)// obj 对象 里面有 commitobj.commit("countMutation")}},// modules 在 store 全局数据 是可以来分模块管理的// 他可以用来区分每个不同模块的数据// 15:10 上课 modules: {// 模块:{ 一套 state action mutation }m1: {namespaced: true,//开启命名空间大白话 他是 m1 下的 不会影响其他人


  // 模块内容(module assets)  state: { // 模块内的状态已经是嵌套的了,使用 `namespaced` 属性不会对其产生影响    m1Name:"我是m1模块的m1Name"  },   actions: {    loginAction () {         console.log('m1的action')    } // -> dispatch('m1/loginAction')  },  mutations: {    loginMutation () {       console.log('loginMutation-执行啦')    } // -> commit('m1/loginMutation')  }},home:{    namespaced: true,    state:{      count:1    }},about:{  namespaced: true,    state:{      count:100    },    actions:{
} },
复制代码


}})


此题具体考查 Vuex 虽然是一个公共状态, 但是公共状态还可以切分成若干个子状态模块, 也就是 moduels,


解决当我们的状态树过于庞大和复杂时的一种解决方案. 但是笔者认为, 一旦用了 vuex, 几乎 就认定该项目是较为复杂的


参考文档


封装 Vue 组件的步骤组件是什么?组件是一段功能代码 ---大白话 就是一段 html +js +css 你可以重复使用


封装轮播图 - 1 新建 vue 组件 2 Vue.component 注册组件 3 在其他组件使用 标签名


参数:可以传入数据 使用 props 接受 比如 数组 定时器时间等


分析: 本题考查 对于 Vue 组件化开发的熟练程度


解析: 首先明确 组件是本质是什么?


组件就是一个单位的 HTML 结构 + 数据逻辑 + 样式的 操作单元


Vue 的组件 继承自 Vue 对象, Vue 对象中的所有的属性和方法,组件可自动继承.


组件的要素 template => 作为页面的模板结构 script => 作为数据及逻辑的部分 style => 作为该组件部分的样式部分要封装一个组件,首先要明确该组件要做的具体业务和需求, 什么样的体验特征, 完成什么样的交互, 处理什么样的数据


明确上述要求之后, 着手模板的结构设计及搭建,也就是 常说的 html 结构部分, 先完成 静态的 html 结构


结构完成, 着手数据结构的设计及开发, 数据结构一般存储于组件的 data 属性 或者 vuex 状态共享的数据结构


数据设计完成/ 结构完成 接下来 完成数据和模块的结合 , 利用 vuejs 中指令和 插值表达式的特性 将静态结构动态化


展现的部分完成, 接下来完成交互部分,即利用 组件的生命周期的钩子函数 和 事件驱动 来完成 逻辑及数据的处理与操作


最后组件完成,进行测试及使用


常用的组件属性 => data/ methods/filters/ components/watch/created/mounted/beforeDestroy/computed/props


常用组件指令: v-if/v-on/v-bind/v-model/v-text/v-once


Vue 中的 data 是以函数的形式还是对象的形式表示分析: 此题考查 data 的存在形式 解析: 我们在初步学习 Vue 实例化的时候写的代码时这个样子上面代码中的 data 是一个对象, 但是我们在开发组件的时候要求 data 必须是一个带返回值的函数


new Vue({el: '#app',data: {name: 'hello world'}})


export default {data () {return {name: '张三'}}}


为什么组件要求必须是带返回值的函数? 因为 我们的组件在实例化的时候, 会直接将 data 数据作用在视图上,对组件实例化, 会导致我们组件的 data 数据进行共享, 好比 现在有两辆新车, 你一踩油门, 不光你的车往前车,另辆车也和你一样往前冲! 这显然不符合我们的程序设计要求, 我们希望组件内部的数据是相互独立的,且互不响应,所以 采用 return {} 每个组件实例都返回新对象实例的形式,保证每个组件实例的唯一性


用户头像

关注尚硅谷,轻松学IT 2021.11.23 加入

还未添加个人简介

评论

发布
暂无评论
前端开发之VUE基础面试题分享