用户输入用户名密码 之后向后台发送请求,之后会返回token,把返回的token存入到session里面去 之后使用导航守卫 router.beforeEach 在路由请求前去本地取出寸的session 如果没有 说明没有登陆
router.beforeEach((to, from, next) => {
/* to 将要访问的路径 form 表示从哪个路径跳转而来 next 是一个函数表示放行 */
if (to.path === '/login') return next()
const tokenStr = window.sessionStorage.getItem('token')
if (!tokenStr) return next('/login')
next()
})
然后在axios 拦截器里面把token放到请求头里面
//例子
axios.interceptors.request.use(config => {
// 为请求头对象,添加token验证的Authorization字段
config.headers.Authorization = window.sessionStorage.getItem('token')
return config
})
var a = ()=>{
return 1;
}
function b(){
return 2;
}
console.log(a.prototype); // undefined
console.log(b.prototype); // {constructor: ƒ}
var obj = {
a: 10,
b: () => {
console.log(this.a); // undefined 箭头函数this指向window
console.log(this); // Window {postMessage: ƒ, blur: ƒ, focus: ƒ, close: ƒ, frames: Window, …}
},
c: function() {
console.log(this.a); // 10
console.log(this); // {a: 10, b: ƒ, c: ƒ}
}
}
obj.b();
obj.c();
var a=[1,2,3,4,5]
try{
a.forEach(function(item,i){
console.log(item)
if(item===2){
throw new Error("跳出来")
}
})
}catch(e){
}
//输出 1 2 undefined
简单来答就是
函数Person(对象)有个属性prototype(指针)指向原型对象Person.prototype(原型对象,实质也是对象),他有个属性constructor(指针) ,又指向 Person函数对象(互指)
再理解就是
每一个JavaScript对象(null除外)在创建的时候就会与之关联另一个对象,这个对象就是我们所说的原型,每一个对象都会从原型"继承"属性。
father 就是一个构造函数,每个函数都有一个 prototype 属性,
我们给 father 的 prototype上添加一个 name属性 为 ’ Tom ’
我们使用 new 创建了一个实例对象 son
son 便继承了 father 的 name
function father() {
}
var son= new father();
father.prototype.name = 'Tom';
console.log(son.name) // Tom
每一个JavaScript对象(除了 null )都具有的一个属性,叫__proto__,这个属性会指向该对象的原型
function father() {
}
var son= new father();
console.log(son.__proto__ === Person.prototype); // true
每个原型都有一个 constructor 属性指向关联的构造函数 实例原型指向构造函数
function father() {
}
console.log(father === father.prototype.constructor); // true
当如果继承了父亲的name属性之后 自己又有个新的name属性的时候
function father() {
}
father.prototype.name = 'Kevin';
var son= new father();
son.name = 'Daisy';
console.log(son.name) // Daisy
delete son.name;
console.log(son.name) // Kevin
当我们删除了 son的 name 属性时,读取 son.name,从 son对象中找不到 name 属性就会从 son的原型也就是 son.proto ,也就是 father.prototype中查找,幸运的是我们找到了 name 属性,结果为 Kevin。
用递归 根据数据结构使用 dom拼接
父组件与子组件通信 父组件在data里面定义好数据 子组件通过props来接受父组件的数据
子组件与父组件通信 .$emit
兄弟之间用 vuex
//数组结构
const foodList=['西兰花','花菜','韭菜']
const [food1,food2,food3] = foodList
// food1 西兰花
// food2 花菜
// food3 韭菜
//对象结构
const person={
name:"小明",
sex:"男",
}
const {name,sex} = person
query使用path和name传参跳转都可以,而params只能使用name传参跳转
传参跳转页面时,query和params不需要在路由上配参数就能在新的页面获取到参数,
但是params不在路由配参数的话,当用户刷新当前页面的时候,参数就会消失。
也就是说使用params不在路由配置参数,只有第一次进入页面参数有效,刷新页面参数就会消失。
//在方法里面写 也可以用name
this.$router.push({ path:'/search', query: { categoryId: this.categoryId }})
// router-link里面的to
<router-link :to="{path:'/search',query: {categoryId: item.categoryId}}">
接收参数:this.categoryId = this.$route.query.categoryId ;
//在方法里面写
this.$router.push({ name::'/search', query: { categoryId: this.categoryId }})
// router-link里面的to
<router-link :to="{name::'/search',query: {categoryId: item.categoryId}}">
接收参数:this.categoryId = this.$route.params.categoryId ;
通过 Object.defineProperty()
来劫持各个属性的 setter / getter,在数据变动时发布消息给订阅者,触发相应的监听回调
文档对象模型或DOM定义了一个接口,该接口允许JavaScript之类的语言访问和操作HTML文档。元素由树中的节点
表示,并且接口允许我们操纵它们。但是此接口需要付出代价,大量非常频繁的DOM操作会使页面速度变慢
每个元素都是一个节点,每段文字也是一个节点,一个节点就是页面的额一部分,就像家谱一样,每个节点都有孩子节点。
虚拟dom就是为了解决操作真是dom带来的性能问题而出现的,所以说,
虚拟dom就是用js对象模拟真实的dom节点,也就是将所有的更新dom的操作先全部反映在js对象上(虚拟dom上)
操作内存中的js对象显然速度要快很多,等更新完成后,再将最终的js对象映射到真是的dom上,交由浏览器去绘制页面。
resolve: {
extensions: ['.js', '.json', 'jsx']
}
resolve: {
// 使用绝对路径指明第三方模块存放的位置,以减少搜索步骤
modules: [path.resolve(__dirname,'node_modules')]
}
由于Loader对文件的转换操作很耗时,所以需要让尽可能少的文件被Loader处理。我们可以通过以下3方面优化Loader配置:
(1)优化正则匹配
(2)通过cacheDirectory选项开启缓存
(3)通过include、exclude来减少被处理的文件。
回答该题前,一般都会思考一下。很多人会偏题,直接去答计算属性和 watch 怎么用,这是不得分的,因为题目是问区别,并不是用法。
计算属性是自动监听依赖值的变化,从而动态返回内容,监听是一个过程,在监听的值变化时,可以触发一个回调,并做一些事情。
所以区别来源于用法,只是需要动态值,那就用计算属性;需要知道值的改变后执行业务逻辑,才用 watch,用反或混用虽然可行,但都是不正确的用法。
这个问题会延伸出几个问题:
问题 1,有 get 和 set 两个选项。
问题 2,methods 是一个方法,它可以接受参数,而 computed 不能;computed 是可以缓存的,methods 不会;一般在 v-for
里,需要根据当前项动态绑定值时,只能用 methods 而不能用 computed,因为 computed 不能传参。
问题 3,computed 可以依赖其它 computed,甚至是其它组件的 data
问题 4,有以下常用的配置:
这个问题我会先写一段代码:
内容
然后问:怎样给这个自定义组件 custom-component 绑定一个原生的 click 事件?
我一开始并不会问什么是事件修饰符,但是如果候选人说
,就已经错了,说明它对这个没有概念。这里的 @click
是自定义事件 click,并不是原生事件 click。绑定原生的 click 是这样的:
内容
该问题会引申很多,比如常见的事件修饰符有哪些?如果你能说上 .exact
,说明你是个很爱探索的人,会大大加分哦。
.exact 是 Vue.js 2.5.0 新加的,它允许你控制由精确的系统修饰符组合触发的事件,比如:
你可能还需要了解常用的几个事件修饰符:
.stop
.prevent
.capture
.self
而且,事件修饰符在连用时,是有先后顺序的。
为什么组件中的 data 必须是一个函数,然后 return 一个对象,而 new Vue 实例里,data 可以直接是一个对象?
因为组件是用来复用的,JS 里对象是引用关系,这样作用域没有隔离,而 new Vue 的实例,是不会被复用的,因此不存在引用对象的问题。
这是个概念题,主要考察候选人是否知道这个用法。简单说,就是把一个组件的编译缓存起来。
回答这道题,首先你得知道什么是递归组件。而不到 10% 的人知道递归组件。其实在实际业务中用的确实不多,在独立组件中会经常使用,第 14 节和 15 节专门讲过递归组件。那回到问题,递归组件的要求是什么?主要有两个:
主要的区别是,actions 可以执行异步。actions 是调用 mutations,而 mutations 来修改 store。
答:有五种,分别是 State、 Getter、Mutation 、Action、 Module
一、Vuex就是一个仓库,仓库里面放了很多对象。其中state就是数据源存放地,对应于与一般Vue对象里面的data
二、state里面存放的数据是响应式的,Vue组件从store中读取数据,若是store中的数据发生改变,依赖这个数据的组件也会发生更新
三、它通过mapState把全局的 state 和 getters 映射到当前组件的 computed 计算属性中
一、getters 可以对State进行计算操作,它就是Store的计算属性
二、 虽然在组件内也可以做计算属性,但是getters 可以在多组件之间复用
三、 如果一个状态只在一个组件内使用,是可以不用getters
一、Action 类似于 mutation,不同在于:
二、Action 提交的是 mutation,而不是直接变更状态。
三、Action 可以包含任意异步操作
一、如果请求来的数据是不是要被其他组件公用,仅仅在请求的组件内使用,就不需要放入vuex 的state里。
二、如果被其他地方复用,这个很大几率上是需要的,如果需要,请将请求放入action里,方便复用,并包装成promise返回,在调用处用async await处理返回的数据。如果不要复用这个请求,那么直接写在vue文件里很方便。
一、可维护性会下降,你要想修改数据,你得维护三个地方
二、可读性会下降,因为一个组件里的数据,你根本就看不出来是从哪来的
三、增加耦合,大量的上传派发,会让耦合性大大的增加,本来Vue用Component就是为了减少耦合,现在这么用,和组件化的初衷相背。