在线访问手册:
https://hanxueqing.github.io/Web-Front-end-Interview-Q-A/
github地址:
https://github.com/Hanxueqing/Web-Front-end-Interview-Q-A
前端构建集成工具(打包)
什么是前端集成解决方案?
FIS(Front-end Integrated Solution)是专为解决前端开发中自动化工具、性能优化、模块化框架、开发规范、代码部署、开发流程等问题的工具框架。
前端集成解决方案解决了前端哪些问题?
- 开发团队代码风格不统一,如何强制开发规范。
- 前期开发的组件库如何维护和使用
- 如何模块化前端项目
- 服务器部署前必须压缩,检查流程如何简化,流程如何完善。
你使用过哪些前端构建集成?你用过什么打包工具?
- Gulp
gulp是工具链、构建工具,可以配合各种插件做js压缩,css压缩,less编译,替代手工实现自动化工作
(1)构建工具
(2)自动化
(3)提高效率用
- webpack
webpack是文件打包工具,可以把项目的各种js文、css文件等打包合并成一个或多个文件,主要用于模块化方案,预编译模块的方案
(1)打包工具
(2)模块化识别
(3)编译模块代码方案用
webpack打包
一款模块化打包工具,webpack是基于配置的,通过配置一些选项来让webpack执行打包任务
webpack在打包的时候,依靠依赖关系图,在打包的时候要告知webpack两个概念:入口和出口
plugins:在webpack编译用的是loader,但是有一些loader无法完成的任务,交由插件(plugin)来完成,插件的时候需要在配置项中配置plugins选项,值是数组,可以放入多个插件使用,而一般的插件都是一个构造器,我们,我们只需在plugins数组中放入该插件的实例即可。
loader:在webpack中专门有一些东西用来编译文件、处理文件,这些东西就叫loader。
webpack都用过哪些loader?
url-loader 可以将css中引入的图片(背景图)、js中生成的img图片处理一下,生成到打包目录里
url-loader/file-loader 将图片转成base64
html-withimg-loader 可以将html中img标签引入的img图片打包到打包目录
css-loader 可以将引入到js中的css代码给抽离出来
style-loader 可以将抽离出来的css代码放入到style标签中
sass-loader/less-loader sass/less预编译
postcss-loader 兼容前缀
babel-loader 将es6转成es5转成大部分浏览器可以识别的语法
vue-loader 把vue组件转换成js模块
为何要转译此模块?
可以动态的渲染一些数据,对三个标签做了优化
写虚拟dom
v-if和v-show的区别
v-if 是“真正”的条件渲染,因为它会确保在切换过程中条件块内的事件监听器和子组件适当地被销毁和重建。 v-if 也是惰性的:如果在初始渲染时条件为假,则什么也不做——直到条件第一次变为真时,才会开始渲染条件块。 相比之下,v-show 就简单得多——不管初始条件是什么,元素总是会被渲染,并且只是简单地基于 CSS 进行切换。 一般来说,v-if 有更高的切换开销,而 v-show 有更高的初始渲染开销。因此,如果需要非常频繁地切换,则使用 v-show 较好;如果在运行时条件很少改变,则使用 v-if 较好。
路由守卫
讲一下都有哪些路由守卫?
全局前置守卫:router.beforeEach 在路由切换开始时候调用
全局后置守卫:roter.afterEach 在路由切换离开时候调用
局部路由守卫:beforeEnter 写在路由对象里
组件内的守卫:
beforeRouteEnter 路由进入到这个组件之前调用,不能获取当前组件对象 this
beforeRouteUpdate 在组件被复用时调用
beforeRouteLeave 路由离开这个组件之后调用,能获取当前组件对象 this
路由守卫中的参数都是什么意思
每个钩子方法接收三个参数:
- to: Route: 即将要进入的目标,路由对象
- from: Route: 当前导航正要离开的路由
- next: Function: 一定要调用该方法来 resolve 这个钩子。执行效果依赖 next 方法的调用参数。
- next(): 进行管道中的下一个钩子。如果全部钩子执行完了,则导航的状态就是 confirmed (确认的)。
- next(false): 中断当前的导航。如果浏览器的 URL 改变了(可能是用户手动或者浏览器后退按钮),那么 URL 地址会重置到 from 路由对应的地址。
- next(‘/’) 或者 next({ path: ‘/’ }): 跳转到一个不同的地址。当前的导航被中断,然后进行一个新的导航。
确保要调用 next 方法,否则钩子就不会被 resolved。
具体说一下每个路由守卫的功能
导航守卫(路由钩子/路由守卫/导航守卫/导航钩子/路由生命周期)
正如其名,
vue-router
提供的导航守卫主要用来通过跳转或取消的方式守卫导航。有多种机会植入路由导航过程中:全局的,单个路由独享的,,或者组件级的。
在某些情况下,当路由跳转前或跳转后、进入、离开某一个路由前、后,需要做某些操作,就可以使用路由钩子来监听路由的变化。
全局守卫
(1)全局前置守卫beforeEach
当一个导航触发时,全局前置守卫按照创建顺序调用。守卫是异步解析执行,此时导航在所有守卫 resolve 完之前一直处于 等待中,所以页面不会加载任何内容。
一定要在路由守卫中调用next()方法来resolve这个钩子
// 全局前置路由
router.beforeEach((to,from,next)=>{
console.log("beforeEach:全局前置守卫")
// 一定要调用next()方法来resolve这个钩子
next();
})
(2)全局后置守卫afterEach
也可以注册全局后置钩子,然而和前置守卫不同的是,这些钩子不会接受 next
函数也不会改变导航本身:
// 全局后置钩子
router.afterEach((to,from)=>{
if (to.path === "/list/audio") {
alert("已经进入list列表audio页面")
}
})
局部守卫
路由独享的守卫
在路由配置上直接定义beforeEnter守卫:
{ path :"/mine",component:()=>import("../views/Mine"),beforeEnter(to,from,next){
console.log("进入到mine页面了")
next();
}}
组件内的守卫
最后,你可以在路由组件内直接定义以下路由导航守卫:
-
beforeRouteEnter
在进入该组件之前执行,该路由守卫中获取不到实例this,因为此时组件实例还没被创建。
beforeRouteEnter
守卫 不能 访问this
,因为守卫在导航确认前被调用,因此即将登场的新组件还没被创建。在Home.vue中添加beforeRouteEnter:
beforeRouteEnter(to,from,next){ console.log("beforeRouteEnter:进入组件之前",this) next() }
打印this,显示undefined
不过,你可以通过传一个回调给
next
来访问组件实例。在导航被确认的时候执行回调,并且把组件实例作为回调方法的参数。beforeRouteEnter (to, from, next) { next(vm => { // 通过 `vm` 访问组件实例 }) }
注意
beforeRouteEnter
是支持给next
传递回调的唯一守卫。对于beforeRouteUpdate
和beforeRouteLeave
来说,this
已经可用了,所以不支持传递回调,因为没有必要了。
-
beforeRouteLeave
在离开该组件之前执行,该路由守卫中可以访问组件实例"this"。
在Home.vue中添加beforeRouteLeave:
beforeRouteLeave(to,from,next){ console.log("beforeRouteLeave:离开组件之前",this) next() }
此时可以打印组件实例"this"
这个离开守卫通常用来禁止用户在还未保存修改前突然离开。该导航可以通过
next(false)
来取消。
-
beforeRouteUpdate(2.2 新增)
当一个组件被重复调用的时候执行该守卫
在Deatil.vue中添加beforeRouteUpdate:
beforeRouteUpdate(to,from,next){ console.log("beforeRouteUpdate") next() }
image
在vue项目中哪里用到过路由守卫?举一个使用到路由守卫的案例
我们想实现当路由变化的时候头部信息动态更改,我们先把内容写成这种样式:
template中:
{{title}}
data中:
data(){
return{
icon:"home",
title:"豆瓣首页",
}
},
这时候就需要用到路由守卫,当路由切换的时候可以做一些业务逻辑,首先需要引入全局路由
import router from "@/router"
在全局前置路由守卫router.beforeEach中,使用switch语句来匹配,根据路由name属性来设置对应的title和icon:
created(){
router.beforeEach((to,from,next)=>{
switch(to.name){
case "home":
this.title = "豆瓣首页"
this.icon = "home"
break;
case "audio":
this.title = "豆瓣影音"
this.icon = "audio-description"
break;
case "broadcast":
this.title = "豆瓣广播"
this.icon = "caret-square-o-left"
break;
case "group":
this.title = "豆瓣小组"
this.icon = "group"
break;
case "mine":
this.title = "豆瓣我的"
this.icon = "cog"
break;
default:
break;
}
next();
})
}
路由
什么是SPA单页应用?你怎么理解单页应用?
现在的应用都流行SPA(single page application),传统的项目大多使用多页面结构,需要切换内容的时候我们往往会进行单个html文件的跳转,这个时候受网络、性能影响,浏览器会出现不定时间的空白界面,用户体验不好。
单页面应用就是用户通过某些操作更改地址栏url之后,动态地进行不同模板内容的无刷新切换,用户体验好。
单页应用的优点
- 更好的用户体验,让用户在web感受natvie的速度和流畅;
- 经典MVC开发模式,前后端各负其责。
- 一套Server API,多端使用(web、移动APP等)
- 重前端,业务逻辑全部在本地操作,数据都需要通过AJAX同步、提交;
Vue切换路由的方法?vue-router的原理?
Vue中会使用官方提供的vue-router插件来使用单页面,原理就是通过检测地址栏变化后将对应的路由组件进行切换(卸载和安装)。
- 引入vue-router,如果是在脚手架中,引入VueRouter之后,需要通过Vue.use来注册插件
- 创建router路由器
- 创建路由表并配置在路由器中
- 在根实例里注入router,目的是为了让所有的组件里都能通过this.$router/route来使用路由的相关功能api
- 利用router-view来指定路由切换的位置
- 使用router-link来创建切换的工具,默认会渲染成a标签,添加to属性来设置要更改的path信息,且会根据当前路由的变化为a标签添加对应的router-link-active/router-link-exact-active(完全匹配成功)类名。
router-link标签的属性
组件支持用户在具有路由功能的应用中(点击)导航。 通过 to 属性指定目标地址,默认渲染成带有正确链接的 标签,可以通过配置 tag 属性生成别的标签。另外,当目标路由成功激活时,链接元素自动设置一个表示激活的 CSS 类名。
to
router-link的to属性,默认写的是path(路由的路径),可以通过设置一个对象,来匹配更多。
我的歌单
name
name是要跳转的路由的名字,也可以写path来指定路径,但是用path的时候就不能使用params传参,params是传路由参数,query传queryString参数。
replace
路由跳转到不同的url默认是push的过程,当用户点击浏览器后退按钮式时,则回到之前url,replace属性可以控制router-link的跳转不被记录。
依次点击首页——列表——音频——视频——我的,点击返回按钮时,依次返回之前的url。
在List.vue的
{{nav.title}}
再依次点击首页——列表——音频——视频——我的,点击返回按钮时,可以看到从音频——视频之间的跳转没有被记录。
active-class
标签切换时,选中状态的显示效果:
还可以通过
{{nav.title}}
设置.title样式
显示效果:
tag
我的歌单
最近播放
路由跳转的方式
组件支持用户在具有路由功能的应用中(点击)导航。 通过 to 属性指定目标地址,默认渲染成带有正确链接的a标签,可以通过配置 tag 属性生成别的标签。另外,当目标路由成功激活时,链接元素自动设置一个表示激活的 CSS 类名。 -
编程式导航:this.$router.replace
This.$router.go
一级路由的实现
-
如果不是使用脚手架创建的项目,需要手动安装vue-router路由模块。
cnpm install vue-router -S
-
引入vue-router,如果是在脚手架中,引入VueRouter之后,需要通过Vue.use来注册插件。
import Vue from 'vue' import Router from 'vue-router' Vue.use(Router)//让vue可以使用vue-router插件
注册vue-router插件之后,this上就有了$route/router属性。
-
创建router路由器,并导出。
let router = new Router({ routes:[ ] }) export default router;
-
在根实例里注入router
new Vue({ //挂载router router,//为了可以让组件使用this.$route,this.$router的一些api属性或者方法 store, render: h => h(App) }).$mount('#app')
此时组件可以通过this.$router/router来使用路由相关功能的api。
-
创建router路由表
let router = new Router({ routes:[ { path:"/home",component:Home }, { path: "/list", component: List }, { path: "/mine", component: Mine } ] })
-
在App.vue中利用router-view来指定路由切换的位置
Hello app.vue!路由切换效果:
image -
使用router-link来创建切换路由的工具
首页 列表 我的 会渲染成a标签,添加to属性来设置要更改的path信息
二级路由(路由嵌套)
在创建路由表的时候,可以为每一个路由对象创建children属性,值为数组,在这个里面又可以配置一些路由对象来使用多级路由,注意:一级路由path前加'/',二级路由前不需要加'/'。
{ path :"/list",component:()=>import("../views/List"),children:[
// 二级路由前不需要加“/”
{ path: "audio", component: () => import("../views/Audio") },
{ path: "video", component: () => import("../views/Video") }
]}
二级路由组件的切换位置依然由router-view来指定(指定在父级路由组件的模板中)。
动态路由
在router路由表中配置动态路由,下面的代码就是给detail路由配置接收id的参数,多个参数继续在后面设置。
// 配置动态路由
{ path:"/detail/:id",component:()=>import("../views/Detail.vue")}
在页面中通过
我的歌单
最近播放
在Detail.vue中打印this.$route.params.id
export default {
created(){
//获取动态路由传递过来的参数
console.log(this.$route.params.id)
}
}
在页面中通过$route.params.id渲染获取到的动态id
我是详情页,我的动态id是:{{$route.params.id}}
一个vue组件中能有多个router-view吗?为什么
有时候想同时 (同级) 展示多个视图,而不是嵌套展示,例如创建一个布局,有 sidebar
(侧导航) 和 main
(主内容) 两个视图,这个时候命名视图就派上用场了。你可以在界面中拥有多个单独命名的视图,而不是只有一个单独的出口。如果 router-view
没有设置名字,那么默认为 default
。
一个视图使用一个组件渲染,因此对于同个路由,多个视图就需要多个组件。确保正确使用 components
配置 (带上 s):
const router = new VueRouter({
routes: [
{
path: '/',
components: {
default: Foo,
a: Bar,
b: Baz
}
}
]
})
参考:命名识图(VUE官网)
https://router.vuejs.org/zh/guide/essentials/named-views.html#%E5%B5%8C%E5%A5%97%E5%91%BD%E5%90%8D%E8%A7%86%E5%9B%BE
Vue路由传参有几种方式
路由参数
在router路由表中配置动态路由,下面的代码就是给detail路由配置接收id的参数,多个参数继续在后面设置。
// 配置动态路由
{ path:"/detail/:id",component:()=>import("../views/Detail.vue")}
在页面中通过
我的歌单
最近播放
在Detail.vue中打印this.$route.params.id
export default {
created(){
//获取动态路由传递过来的参数
console.log(this.$route.params.id)
}
}
在页面中通过$route.params.id渲染获取到的动态id
我是详情页,我的动态id是:{{$route.params.id}}
queryString参数
queryString参数不需要在路由表设置接收,直接设置?后面的内容:
我的歌单
最近播放
在路由组件中通过this.$route.query接收
export default {
created(){
//获取动态路由传递过来的参数
console.log(this.$route.params.id,this.$route.query.title)
}
}
打印结果:
页面渲染效果:
上面的参数传递也可以写成对象的形式:
最近播放
通过prop将路由与组件解耦
在组件中接收路由参数需要this.$route.params.id,代码冗余,现在可以在路由表里配置props:true。
{ path:"/detail/:id",component:()=>import("../views/Detail.vue"),name:"detail",props:true}
在路由组件中可以通过props接收id参数去使用
props:["id"],
在页面中就可以通过{{id}}的方式来使用路由传递的参数
我的动态id是:{{id}}
路由模式
为了构建SPA(单页面应用),需要引入前端路由系统,这也就是Vue-router存在的意义。前端路由的核心,就在于:改变视图的同时不会向后端发出请求。
hash和history这两个方法应用于浏览器的历史记录站,在当前已有的back、forward、go 的基础之上,它们提供了对历史记录进行修改的功能。只是当它们执行修改是,虽然改变了当前的URL,但你浏览器不会立即向后端发送请求。
hash:即地址栏URL中的#符号(此hsah 不是密码学里的散列运算)
路由有两种模式:hash、history,默认会使用hash模式
比如这个URL:http://www.baidu.com/#/hello, hash 的值为#/hello。它的特点在于:hash 虽然出现URL中,但不会被包含在HTTP请求中,对后端完全没有影响,因此改变hash不会重新加载页面。
history:利用了HTML5 History Interface 中新增的pushState() 和replaceState() 方法。(需要特定浏览器支持)
如果url里不想出现丑陋hash值(#),在new VueRouter的时候配置mode值为history来改变路由模式,本质使用H5的histroy.pushState方法来更改url,不会引起刷新。
// 默认会使用hash模式
mode:"history",
history模式,会出现404 的情况,需要后台配置。
hash模式和history模式在发生404错误时:
-
hash模式下,仅hash符号之前的内容会被包含在请求中,当用户访问https://www.baidu.com/#/home时实际请求的是:https://www.baidu.com/。因此对于后端来说,即使没有做到对路由的全覆盖,页面也不会返回404错误;
-
history模式下,前端的url必须和实际向后端发起请求的url 一致,因为我们的应用是个单页客户端应用,如果后台没有正确的配置,当用户在浏览器直接访问 https://www.baidu.com/home/detail,缺少对/home/detail的路由处理,就会返回 404错误,这就不好看了。
image
所以呢,你要在服务端增加一个覆盖所有情况的候选资源:如果 URL 匹配不到任何静态资源,则应该返回同一个 index.html 页面,这个页面就是你 app 依赖的页面。
hash哈希路由的原理
window.onload = function(){
//当hash发生变化的时候, 会产生一个事件 onhashchange
window.onhashchange = function(){
console.log( '你的hash改变了' );
//location对象是 javascript内置的(自带的)
console.log( location );
}
}
上例,我们已经通过hash( 就是锚文本 ) 变化, 触发了onhashchange事件, 就可以把hash变化与内容切换对应起来,就实现了单页路由的应用!
监控hash值变化,hash一旦变化,页面内容变化,实现无刷新切换。
参考:js单页hash路由原理与应用实战
https://www.cnblogs.com/ghostwu/p/7357381.html
路由的懒加载
当打包构建应用时,JavaScript 包会变得非常大,影响页面加载。如果我们能把不同路由对应的组件分割成不同的代码块,然后当路由被访问的时候才加载对应组件,这样就更加高效了。结合 Vue 的异步组件和 Webpack 的代码分割功能,轻松实现路由组件的懒加载。
懒加载也叫延迟加载,即在需要的时候进行加载,随用随载。在单页应用中,如果没有应用懒加载,运用webpack打包后的文件将会异常的大,造成进入首页时,需要加载的内容过多,延时过长,会出现长时间的白屏,即使做了loading也是不利于用户体验,而运用懒加载则可以将页面进行划分,需要的时候加载页面,可以有效的分担首页所承担的加载压力,减少首页加载用时。简单的说就是:进入首页时不用一次加载过多资源,造成页面加载用时过长。
懒加载写法:
// 路由的懒加载方式
{ path :"/home",component:()=>import("../views/Home")},// 当我访问/home首页时,页面才去加载Home组件,减少首页加载的时长
{ path :"/list",component:()=>import("../views/List")},
{ path :"/mine",component:()=>import("../views/Mine")}
非按需加载则会把所有的路由组件块的js包打在一起。当业务包很大的时候建议用路由的按需加载(懒加载)。 按需加载会在页面第一次请求的时候,把相关路由组件块的js添加上。
参考:路由的懒加载(VUE官网)
https://router.vuejs.org/zh/guide/advanced/lazy-loading.html
通过正则匹配路由
// The matching uses path-to-regexp, which is the matching engine used
// by express as well, so the same matching rules apply.
// For detailed rules, see https://github.com/pillarjs/path-to-regexp
const router = new VueRouter({
mode: 'history',
base: __dirname,
routes: [
{ path: '/' },
// params are denoted with a colon ":"
{ path: '/params/:foo/:bar' },
// a param can be made optional by adding "?"
{ path: '/optional-params/:foo?' },
// a param can be followed by a regex pattern in parens
// this route will only be matched if :id is all numbers
{ path: '/params-with-regex/:id(\\d+)' },
// asterisk can match anything
{ path: '/asterisk/*' },
// make part of th path optional by wrapping with parens and add "?"
{ path: '/optional-group/(foo/)?bar' }
]
})
官方例子github地址:https://github.com/vuejs/vue-router/blob/next/examples/route-matching/app.js
Vuex
什么是Vuex?
vuex是一个专门为vue构建的状态集管理工具,vue和react都是基于组件化开发的,项目中包含很多的组件,组件都会有组件嵌套,想让组件中的数据被其他组件也可以访问到就需要使用到Vuex。
Vuex主要解决了什么问题?
Vuex主要是为了解决多组件之间状态共享问题,它强调的是集中式管理(组件与组件之间的关系变成了组件与仓库之间的关系)把数据都放在一个仓库中管理,使用数据的时候直接从仓库中获取,如果仓库中一个数据改变了, 那么所有使用这个数据的组件都会更新。Vuex把组件与组件之间的关系解耦成组件与仓库之间的关系,方便数据维护。
Vuex的流程?Vuex的核心?
(1)将需要共享的状态挂载到state上:this.$store.state来调用
创建store,将状态挂载到state上,在根实例里面配置store,之后我们在组件中就可以通过this.$store.state来使用state中管理的数据,但是这样使用时,当state的数据更改的时候,vue组件并不会重新渲染,所以我们要通过计算属性computed来使用,但是当我们使用多个数据的时候这种写法比较麻烦,vuex提供了mapState辅助函数,帮助我们在组件中获取并使用vuex的store中保存的状态。
(2)我们通过getters来创建状态:通过this.$store.getters来调用
可以根据某一个状态派生出一个新状态,vuex也提供了mapGetters辅助函数来帮助我们在组件中使用getters里的状态。
(3)使用mutations来更改state:通过this.$store.commit来调用
我们不能直接在组件中更改state,而是需要使用mutations来更改,mutations也是一个纯对象,里面包含很多更改state的方法,这些方法的形参接收到state,在函数体里更改,这时,组件用到的数据也会更改,实现响应式。vuex提供了mapMutations方法来帮助我们在组件中调用mutations 的方法。
(4)使用actions来处理异步操作:this.$store.dispatch来调用
Actions类似于mutations,不同在于:Actions提交的是mutations,而不是直接变更状态。Actions可以包含任意异步操作。也就是说,如果有这样的需求:在一个异步操作处理之后,更改状态,我们在组件中应该先调用actions,来进行异步动作,然后由actions调用mutations来更改数据。在组件中通过this.$store.dispatch方法调用actions的方法,当然也可以使用mapMutations来辅助使用。
简便版流程:
组件使用数据且通过异步动作更改数据的一系列事情:
1.生成store,设置state
2.在根实例中注入store
3.组件通过计算属性或者mapState来使用状态
4.用户产生操作,调用actions的方法,然后进行异步动作
5.异步动作之后,通过commit调用mutations的方法
6.mutations方法被调用后,更改state
7.state中的数据更新之后,计算属性重新执行来更改在页面中使用的状态
8.组件状态被更改,创建新的虚拟dom
9.组件的模板更新之后重新渲染在dom中
什么情况下用到vuex?
使用Vuex的情况:多组件间频繁通信
目前市场上有两种使用vuex的情况,
第一种:将需要共享、需要管理的状态放入vuex中管理,也就是说在必要时使用
第二种:将所有的数据都交由vuex管理,由vuex来承担更多的责任,组件变得更轻量级,视图层更轻
项目中使用到vuex的一些场景?
(1)购物车数据共享
(2)用户登录
(3)打开窗口,出现一个表单数据,然后关闭窗口,再次打开还想出现,就使用vuex
Vuex的项目结构
Vuex 并不限制你的代码结构。但是,它规定了一些需要遵守的规则:
- 应用层级的状态应该集中到单个 store 对象中。
- 提交 mutation 是更改状态的唯一方法,并且这个过程是同步的。
- 异步逻辑都应该封装到 action 里面。
只要你遵守以上规则,如何组织代码随你便。如果你的 store 文件太大,只需将 action、mutation 和 getter 分割到单独的文件。
对于大型应用,我们会希望把 Vuex 相关代码分割到模块中。下面是项目结构示例:
├── index.html
├── main.js
├── api
│ └── ... # 抽取出API请求
├── components
│ ├── App.vue
│ └── ...
└── store
├── index.js # 我们组装模块并导出 store 的地方
├── actions.js # 根级别的 action
├── mutations.js # 根级别的 mutation
└── modules
├── cart.js # 购物车模块
└── products.js # 产品模块
来源:项目结构(VUE官网)
https://vuex.vuejs.org/zh/guide/structure.html#%E9%A1%B9%E7%9B%AE%E7%BB%93%E6%9E%84
vuex与local storage有什么区别
区别:vuex存储在内存,localstorage(本地存储)则以文件的方式存储在本地,永久保存;sessionstorage( 会话存储 ) ,临时保存。localStorage和sessionStorage只能存储字符串类型,对于复杂的对象可以使用ECMAScript提供的JSON对象的stringify和parse来处理。
应用场景:vuex用于组件之间的传值,localstorage,sessionstorage则主要用于不同页面之间的传值。
永久性:当刷新页面(这里的刷新页面指的是 --> F5刷新,属于清除内存了)时vuex存储的值会丢失,sessionstorage页面关闭后就清除掉了,localstorage不会。
注:很多同学觉得用localstorage可以代替vuex, 对于不变的数据确实可以,但是当两个组件共用一个数据源(对象或数组)时,如果其中一个组件改变了该数据源,希望另一个组件响应该变化时,localstorage,sessionstorage无法做到,原因就是区别1。
Slot插槽
vue里提供了一种将父组件的内容和子组件的模板整合的方法:内容分发,通过slot插槽来实现。
在组件标签内部写入的内容默认的会被替换掉,如果想要在组件的模板里使用这些内容,就在对应的位置写上slot标签,这个slot标签就代表着这些内容。
匿名槽口
在父组件中使用子组件的时候,在子组件标签内部写的内容,在子组件的模板中可以通过
slot槽口插入的内容
我是aaa组件
具名槽口
父组件在子组件标签内写的多个内容我们可以给其设置slot属性来命名,在子组件的模板通过使用带有name属性的slot标签来放置对应的slot,当slot不存在的时候,slot标签内写的内容就出现。
slot上面通过name属性指定槽口名称,然后使用的时候通过slot="槽口名称"。
在上面的内容
在下面的内容
我是aaa组件
slot插槽让我们在原有模版的基础上,定制更加多样化的组件。
作用域插槽
当我们想在父组件中访问子组件内部的一些数据时,就需要在子组件内部的
绑定到
老师姓名:{{prop.teacher.name}} 老师年龄:{{prop.teacher.age}}
v-slot
v-slot
指令自 Vue 2.6.0 起被引入,提供更好的支持slot
和slot-scope
特性的 API 替代方案。在接下来所有的 2.x 版本中slot
和slot-scope
特性仍会被支持,但已经被官方废弃,且不会出现在 Vue 3 中。
现在我们使用 v-slot
重构上面的代码:
老师姓名:{{prop.teacher.name}} 老师年龄:{{prop.teacher.age}}
一个不带 name
的
出口会带有隐含的名字“default”,使用时可以简化为v-slot="prop“
。
具名槽口
子组件中通过name属性给槽口设定名称
父组件中通过v-slot:名称
的方式来使用具名槽口
学生姓名:{{prop.student.name}} 学生年龄:{{prop.student.age}}
当我们在父组件中多次调用子组件时,可以通过设置不同的样式,来设定子组件中数据的展示形式。
主流js框架对比
Vue和React的区别
(1)react销毁组件的时候,会将组件的dom结构也移除,vue则不然,在调用destory方法销毁组件的时候,组件的dom结构还是存在于页面中的,this.$destory组件结构还是存在的,只是移除了事件监听。
(2)react中没有指令
(3)在vue中,data属性是利用object.defineProperty处理过的,更改data的数据的时候会触发数据的getter和setter,但是react中没有做这样的处理,如果直接更改的话,react是无法得知的。
react更改状态:在setState中,传入一个对象,就会将组件的状态中键值对的部分更改,还可以传入一个函数,这个回调函数必须向上面方式一样的一个对象函数可以接受prevState和props。
(4)react中属性是不允许更改的,状态是允许更改的。react中组件不允许通过this.state这种方式直接更改组件的状态。自身设置的状态,可以通过setState来进行更改。
拓展:对比其他框架(Vue官网给出的详细解释)
https://vue.docschina.org/v2/guide/comparison.html
Vue和JQuery的区别
jQuery是使用选择器($)选取DOM对象,对其进行赋值、取值、事件绑定等操作,其实和原生的HTML的区别只在于可以更方便的选取和操作DOM对象,而数据和界面是在一起的。
比如需要获取label标签的内容:$("lable").val();
,它还是依赖DOM元素的值。
Vue则是通过Vue对象将数据和View完全分离开来了。对数据进行操作不再需要引用相应的DOM对象,可以说数据和View是分离的,他们通过Vue对象这个vm实现相互的绑定。这就是传说中的MVVM。
vue适用的场景:复杂数据操作的后台页面,表单填写页面
jquery适用的场景:比如说一些html5的动画页面,一些需要js来操作页面样式的页面
然而二者也是可以结合起来一起使用的,vue侧重数据绑定,jquery侧重样式操作,动画效果等,则会更加高效率的完成业务需求
参考:jquery和vue对比
https://www.cnblogs.com/MR-YY/p/6898464.html
react与vue之间的相同点和不同点?
相同点:
1.都支持ssr服务器端渲染,vue:nuxt;react:next。
2.都有Virtual DOM,组件化开发,通过props参数进行父子组件数据的传递,都实现组件之间的模块化webComponent规范。
3.数据驱动视图,数据改变视图发生更改。
4.都有支持native的方案,React的React native,Vue的weex(终端的原生端端解决方案)
5.都有管理状态集工具,React有redux,Vue有自己的Vuex(自适应vue,量身定做)
不同点:
- React严格上只针对MVC的view层(用户界面的javascript库),Vue则是MVVM模式。
- virtual DOM不一样:vue会跟踪每一个组件的依赖关系,不需要重新渲染整个组件树。而对于React而言,每当应用的状态被改变时,全部组件都会重新渲染,所以react中会需要shouldComponentUpdate这个生命周期函数方法来进行控制。
- 组件写法不一样:React推荐的做法是 JSX + inline style, 也就是把HTML和CSS全都写进JavaScript了,即'all in js';Vue推荐的做法是webpack+vue-loader的单文件组件格式,即html,css,js写在同一个文件;
- 数据绑定: vue实现了数据的双向绑定,react没有实现。
- state对象在react应用中不可变的,需要使用setState方法更新状态;在vue中,state对象不是必须的,数据由data属性在vue对象中管理。