1.Vue 不同环境配置不同的接口地址;
在项目中,前端请求访问的地址如果有跨域,我们会在config–>index.js中配置代理。
这样前端请求就可以使用'/api/接口名称',但是在生产环境下,我们不需要接口请求前面加'/api',所以就需要判断开发环境和生产环境。
1)
config -> dev.env.js 添加开发接口地址
config -> prod.env.js 添加生产环境的地址
2)
在封装axios时,添加判断:
if (location.hostname == '正式的域名') {
baseUrl = '正式地址'
} else { //测试环境
baseUrl = '测试地址'
}
axios.defaults.baseURL = baseUrl
2.用户未登录进入该url的登录拦截逻辑:
1.首先在定义路由的时候需要添加自定义字段(requireAuth)字段可以自己设置名称,判断该路由的访问是否需要登录,如果用户已经登录,顺利进入该路由,否则就进入登录页。在路由管理页面添加meta,在meta字段里设置。
meta:{requireAuth:true}// 添加该字段,true表示进入这个路由是需要登录的
2.定义完路由后,利用vue-router的钩子函数beforeEach对路由进行判断;
router.beforeEach((to, from, next) => {
if (to.meta.requireAuth) { // 判断该路由是否需要登录权限
if (store.state.token) { // 通过vuex state获取当前的token是否存在
next();
} else {
next({
path: '/login',
query: {
redirect: to.fullPath
} // 将跳转的路由path作为参数,登录成功后跳转到该路由
})
}
} else {
next();
}
})
3.axios是什么?怎么使用?
axios是一个基于promise的HTTP请求库,简单地说就是可以发送get、post请求,可以用在浏览器和node.js中。
axios的特性:
1)可以在浏览器中发送XMLHttpRequests
2)可以在node.js中发送http请求
3)支持Promise API
4)拦截请求和响应
5)转换请求数据和响应数据
6)能够取消请求
7)自动转换json数据
8)客户端支持保护安全免受 XSRF 攻击
4.VueX是什么?哪种场景能使用它?
1)VueX是一个专门为vue构建的状态集管理。主要为了解决组件之间状态共享的问题。强调的是集中式管理。主要是便于维护、便于解耦,不是所有项目都适合vuex,如果不是构建大型项目,会使代码变得繁琐多余。
2)VueX的核心
state:存放数据
mutations:变更状态(同步的)
getters:
actions:调用mutations,更改状态的。(可以异步)
modules
5.路由的钩子函数
路由的钩子函数主要是用来拦截导航,让它完成跳转和取消
主要分为全局和局部
全局的:
1)beferEach
2)afetrEach
6.vue的生命周期详解(必看)
vue生命周期分为四个阶段
creating
mounting
updating
destroying
beforeCreated:el和data都未初始化(可以加loading)
Created:data数据初始化,el未初始化(结束loading)
beforeMount:完成el和data初始化(虚拟DOM)
mounted:挂载完成,真实DOM渲染完成(发起请求,拿数据,渲染DOM)
beforeUpdate:组件更新前的函数,数据更新了,但是,vue(组件)对象对应的dom中的内部(innerHTML)没有变,所以叫作组件更新前
update:组件更新之后执行的函数,vue(组件)对象对应的dom中的内部(innerHTML)改变了,所以,叫作组件更新之后
beforeDestroy:组件销毁之前调用,在这一步,实例仍然可以完全可用(可在此处清除定时器,清除事件绑定)
destroyed:Vue 实例销毁后调用。调用后,Vue 实例指示的所有东西都会解绑定,所有的事件监听器会被移除,所有的子实例也会被销毁
其中 created 和 mounted 比较重要,一个是data数据和事件的初始化,一个是html 模板 挂载渲染到页面完毕
附加: keep-alive 方法
actived() 组件加上keep-alive,进入组件触发的方法
deactived() 离开组件的时候触发的方法
7.路由懒加载
1)vue异步组件技术,vue-router配置路由,使用路由的异步组件技术,可以实现按需加载。但是这种情况下,一个组件生成一个js文件。
{
path:'/home',
name:'home'.
component:resolve => require(['@/components/home'],resolve)
}
2)路由懒加载(使用import)
const Foo = () => import(/* webpackChunkName: "group-foo" */ './Foo.vue')
{
path:'/home',
name:'home'.
component:Foo
}
在build目录下找到webpack.prod.conf.js文件,将output修改为
output: {
path: config.build.assetsRoot,
filename: utils.assetsPath('js/[name].[chunkhash].js'),//文件格式,文件名.文件哈希
chunkFilename: utils.assetsPath('js/[name].[chunkhash].js')//文件切割后的文件名称。
这里的name对应的就是路由中引入文件时候的webpackChunkName
}
3)webpack提供的require.ensure技术,也可以按需加载,多个路由指定相同的chunkName,会合并打包成一个js文件。
{
path:'/home',
name:'home'.
component:resolve=>require.ensure([],() => resolve(require('../components/PromiseDemo')),home)
}
8.封装组件过程
1)新建组件,组件包含template、script、style
2)父组件中,使用import引入组件 import 组建名称 form 组件路径
3)父组件中,components注册组件 components:{ 组件名称 }
9.vue路由传参方式
<div v-for="article in articles" @click="getDescribe(article.id)"></div>
1)getDescribe(id){
this.$router.push({
path:'/describe/${id}'
})
}
对应的路由配置:
{
path: '/describe/:id',
name: 'Describe',
component: Describe
}
获取参数:this.$route.params.id;
2)getDescribe(id){
this.$router.push({
name:'/describe',
params:{
id:id
}
})
}
获取参数:this.$route.params.id
3)getDescribe(id){
this.$router.push({
path:'/describe',
query:{
id:id
}
})
}
获取参数:this.$route.query.id; //query方式参数会显示在url的后面
10.插槽的作用?
**匿名插槽:**
子组件:
<template>
<h3>test-slot</h3>
//父组件里的span会替换掉slot所以这里的123是看不见的
//如果父组件在使用子组件testSlot的时候不在里面加内容则这里的slot会显示出来
<slot>123</slot>
</template>
父组件:
<template>
<div id="app">
<test-slot>
<span>我是父组件里的文字,但是我要被放到子组件里</span>
</test-slot>
</div>
</template>
**渲染结果:**
test-slot
我是父组件里的文字,但是我要被放到子组件里
**多个插槽也叫具名插槽:**
子组件:
<template>
<h3>test-slot</h3>
//父组件里的span会替换掉slot所以这里的123是看不见的
//如果父组件在使用子组件testSlot的时候不在里面加内容则这里的slot会显示出来
<slot name='header'>123</slot>
<slot>123</slot>
<slot name='footer'>123</slot>
</template>
父组件:
<template>
<h3>多个具名插槽</h3>
<div slot='header'>头部内容</div>
<div>内容部分</div>
<div slot='footer'>底部内容</div>
</template>
**渲染结果:**
多个具名插槽
头部内容
内容部分
底部内容
**作用域插槽:**
作用域插槽是一种特殊类型的插槽,子组件的值传到父组件使用
子组件:
子组件props里接收一个父组件传递的数组,在作用域插槽slot里边,绑定数组的属性。
<template>
<div class="hello">
<slot :cname="items[2].cname"></slot>
<slot :addr="items[2].addr"></slot>
<slot age="18"></slot>
</div>
</template>
<script>
export default {
data () {
return {
num:100
}
},
props:['items'],
methods:{
},
created(){
console.log('items',this.$props.items);
}
}
</script>
父组件:
在test-slot子组件标签上通过:item='items'给子组件传递数组,通过slot-scope='props'获取子组件作用域插槽所有的属性值
<template>
<div id="app">
<h2>app</h2>
<test-slot :items="items">
<template slot-scope="props">
<span>{{ props.addr }}</span>
<span>{{ props.cname }}</span>
<span>{{ props.age }}</span>
</template>
</test-slot>
</div>
</template>
<script>
import testSlot from './components/testSlot.vue'
export default {
data (){
return {
items:[
{ text:'文字1' , cname:'tom' , addr:'usa' },
{ text:'文字2' , cname:'wangwu' , addr:'uk' },
{ text:'文字3' , cname:'zhangsan' , addr:'un' }
]
}
},
methods:{
},
components:{
testSlot
}
}
</script>
**渲染结果:**
zhangsan un 18
11 了解过MVC吗,说下对MVC的理解
MVC:Model View Controller。Model 指 模型,用于存储数据;
View 指 视图,用于展示数据;Controller 指 控制器,用于调用其他子服务,使Model 和 View 解耦合。
Model 和 view 不直接通信,而是通过controller 联系起来,Controller 相当于 外观模式的应用。
*12 为什么在项目中data需要使用return返回数据呢?
不使用return包裹的数据会在项目的全局可见,会造成变量污染
使用return包裹后数据中变量只在当前组件中生效,不会影响其他组件
13 说下vue里面的 computed 和 watch 的区别
computed 计算属性,watch 监听变化
区别是
computed 是计算值
应用:简化 template 里面 {{}} 的计算和处理 props 或 $emit 的传值
具有缓存性,页面重新渲染值不计算,只有当被计算的值发生变化才计算
watch 是观察值是否发生变化
应用:监听 props,$emit 或本组件的值执行异步操作
无缓存性,页面重新渲染就算值不变化也会执行
watch 里面还要注意下 immediate 和 deep 属性
watch与computed的区别是:
watch更加适用于监听某一个值的变化并做对应的操作,比如请求后台接口等;
而computed适用于计算已有的值并返回结果
14 说一下你知道的http的状态码
200 请求资源成功
400 客户端请求格式错误
403 需要客户端身份验证
404 请求资源不存在
413 请求资源过大
500 服务器端错误
3xx 一般为重定向
详细链接:https://tool.oschina.net/commons?type=5
注意: 301和302得区别
301:被请求的资源已永久移动到新位置,并且将来任何对此资源的引用都应该使用本响应返回的若干个 URI 之一。
302:请求的资源现在临时从不同的 URI 响应请求。由于这样的重定向是临时的,客户端应当继续向原有地址发送以后的请求。
15 get和post的区别
**get** 参数直接放在url里面,并且传输的参数大小受不同浏览器限制,也不安全,毕竟直接暴露在url中,其值只能为字符串。
**post** 参数在报文体中,传输得容量比get大,参数不暴露出来相对安全。
**get** 发送一个数据包 ,**post** 发送两个
等等等等。。。。还有很多
详细链接:https://www.cnblogs.com/logsharing/p/8448446.html
16 对 ES6 新特性的了解
解构赋值、 let const 、块级作用域 、箭头函数 、promise。
let 和 const var 区别
**const** 声明的是**常量**,必须赋值
1)一旦声明必须赋值,不能使用null占位。
2)声明后不能再修改
3)如果声明的是复合类型数据,可以修改其属性
4> **let**和 **var** 声明的是变量,声明之后可以更改,声明时可以不赋值
5> var允许重复声明变量,后一个变量会覆盖前一个变量。let和const在同一作用域不允许重复声明变量,会报错
6> var声明的变量存在变量提升(将变量提升到当前作用域的顶部)。即变量可以在声明之前调用,值为undefined。
7> let和const不存在变量提升。即它们所声明的变量一定要在声明后使用,否则报ReferenceError错`在这里插入代码片`
var不存在块级作用域。let和const存在块级作用域。
ES5中作用域有:全局作用域、函数作用域。没有块作用域的概念。
ES6(简称ES6)中新增了块级作用域。块作用域由 { } 包括,if语句和for语句里面的{ }也属于块级作用域。
模板字符串
- 将表达式嵌入字符串中进行拼接。用**${}**来界定。
//ES5
var way = 'String'
console.log('ES5:' + way)
//ES6
let way = 'String Template'
console.log(`ES6: ${way}`)
2.多行字符串拼接
在ES5时我们通过反斜杠()来做多行字符串或者字符串一行行拼接。ES6反引号(“)直接搞定。
17 箭头函数和普通函数的区别
箭头函数 和 普通函数 的 this 指向不同
(1)箭头函数是匿名函数,不能作为构造函数,不能使用new
(2)箭头函数不绑定arguments,取而代之用rest参数…解决
(3)箭头函数不绑定this,会捕获其所在的上下文的this值,作为自己的this值
(4)箭头函数通过 call() 或 apply() 方法调用一个函数时,只传入了一个参数,对 this 并没有影响。
(5)箭头函数没有原型属性
(6)箭头函数不能当做Generator函数,不能使用yield关键字
参考文章:https://www.cnblogs.com/biubiuxixiya/p/8610594.html
18.new 一个 箭头函数可以吗,为什么
箭头函数是匿名函数,不能作为构造函数,不能使用new
19 new 一个对象的过程
相加粗样式当于运行构造函数:
this 指向这个对象,
对 this 进行属性赋值,
将 this 的 隐式原型 指向 构造函数的 显式原型,
返回这个对象
20 了解过 setTimeout 的原理
event loop机制
详细链接:https://www.cnblogs.com/xgqfrms/p/11399442.html
21.promise 和 setTimeout 的区别(微队列和宏队列)
扫到了目前的知识盲区:微任务队列 和 宏任务队列
promise.then 和 process.nextTick 都是 微任务
setTimout 和 setInterval 是 宏任务
微任务 比 宏任务 优先级高
setTimeout promise 遇到一起 promise先执行
详细链接:https://blog.csdn.net/qq_30376375/article/details/82990588
22.写一段 promise 和 setTimeout 的代码,问你输出结果
23.js 的基本数据类型
number string boolean undefined null
24 v-if与v-show的区别
相同点:都可以动态控制 DOM 元素的显示隐藏
区别:
v-if : 是将 DOM 元素整个添加或删除
v-show: 是为 DOM 元素添加css的样式display,设置 none 或者 是 block,DOM 元素 还是存在的
性能对比
v-if 有更高的切换消耗;
v-show 有更高的初始渲染消耗
应用场景
v-if 适合用于条件不大可能改变的情境下;
v-show 适合用于 频繁切换;
25 vue 中双向数据绑定是如何实现的
26 Vue组件通信(父传子、子传父、兄弟通信)
父传子、子传父、兄弟通信(bus)、本地存储、vuex
27 Vue-router共有几种模式?默认是哪种?
history模式 hash模式 默认 hash模式
28 NextTick是什么
在下次 DOM 更新循环结束之后执行延迟回调。在修改数据之后立即使用这个方法,获取更新后的 DOM
29 Vue-cli打包命令是什么?打包后会导致路径问题,应该在哪里修改
npm run build-环境-域名-打包文件夹 -平台
打包后会项目中生成一个dist文件夹
在打包之前,需要将文件中config文件夹下的index.js中的 assetsPublicPath:”” 中的 / 改为 ./
30 assets和static的区别
assets目录中文件在打包的时候会进行打包压缩然后上传到打包好的目录,如果接口中的文件,不能放到assets中去。
static目录中的文件直接拷贝到打包好的目录中 不会进行压缩, 放第三方的json文件或者图片
31 null 和undefined 区别
null :null 表示一个值被定义了,定义为“空值”;
undefined 表示根本不存在定义。
- 变量被声明了,但没有赋值时,就等于 undefined
- 调用函数时,应该提供的参数没有提供,该参数等于 undefined
- 对象没有赋值的属性,该属性的值为 undefined
- 函数没有返回值时,默认返回 undefined
null表示“没有对象”,即该处不应该有值。典型用法是:
- 作为函数的参数,表示该函数的参数不是对象
- 作为对象原型链的终点
32 隐藏一个元素有哪几种方法
opacity:0 z-index v-if v-show display:none visibility:hidden
display:none、visibility:hidden 和 opacity:0 的区别
display:none 隐藏后不占据额外空间,它会产生回流和重绘
visibility:hidden 和 opacity:0 元素虽然隐藏了,但它们仍然占据着空间,它们只会引起页面重绘
display:none 不会被子元素继承,但是父元素都不在了,子元素自然也就不会显示了
visibility:hidden 会被子元素继承,可以通过设置子元素visibility:visible 使子元素显示出来
opacity: 0 会被子元素继承,但是不能通过设置子元素opacity: 0使其重新显示
33 数组去重复的方法
方法1:简单粗暴的ES6方法Set,Set数据结构,它类似于数组,其成员的值都是唯一的。
var arr = [1, 2, 3, 2, 1, 3];
console.log(new Set(arr))//打印结果:Set(3) {1, 2, 3}
方法2:使用filter过滤函数去重。
var arr = [1, 2, 3, 1, 2, 3];
console.log(arr.filter((v, i, arr) => arr.indexOf(v) === i))//打印结果:(3) [1, 2, 3]
方法3:遍历数组法。
实现的思路:新建一个数组,遍历传入的数组,值不在新数组中就加入到该新数组;
注意:判断值是否在数组中可以用indexOf是ES5 方法,IE9以下不支持,需兼容低版本浏览器。
function unique(array) {
var n = []; //一个新的临时数组
//遍历当前数组
for (var i = 0; i < array.length; i++) {
if (n.indexOf(array[i]) == -1) n.push(array[i]);
//如果当前数组的第i已经保存进了临时数组,那么跳过,
//否则把当前项push到临时数组里面
}
return n;
}
console.log(unique([1, 2, 3, 1, 2, 3])) //打印结果:(3) [1, 2, 3]
方法4:利用splice()方法直接在原数组进行操作。
双层循环,外层循环元素,内层循环时比较值。
值相同时,则删去这个值。
注意:删除元素之后,需要将数组的长度也减1。
优点:简单易懂。
缺点:占用内存高,速度慢。
Array.prototype.unique = function () {
var arr = this,
i,
j,
len = arr.length;
for (i = 0; i < len; i++) {
for (j = i + 1; j < len; j++) {
if (arr[i] == arr[j]) {
arr.splice(j, 1);
len--;
j--;
}
}
}
return arr;
};
var a = [1, 2, 3, 1, 2, 3];
var b = a.unique();
console.log(b); //打印结果:(3) [1, 2, 3]
方法5:利用对象的属性不能相同的特点进行去重
Array.prototype.unique = function () {
var arr = this,
i,
obj = {},
result = [],
len = arr.length;
for (i = 0; i < arr.length; i++) {
if (!obj[arr[i]]) { //如果能查找到,证明数组元素重复了
obj[arr[i]] = 1;
result.push(arr[i]);
}
}
return result;
};
var a = [1, 2, 3, 1, 2, 3];
var b = a.unique();
console.log(b); //打印结果:(3) [1, 2, 3]
方法6:数组递归去重
Array.prototype.unique = function () {
var arr = this,
len = arr.length;
arr.sort(function (a, b) { //对数组进行排序才能方便比较
return a - b;
})
function loop(index) {
if (index >= 1) {
if (arr[index] === arr[index - 1]) {
arr.splice(index, 1);
}
loop(index - 1); //递归loop函数进行去重
}
}
loop(len - 1);
return arr;
};
var a = [1, 2, 3, 1, 2, 3];
var b = a.unique();
console.log(b); //打印结果:(3) [1, 2, 3]
34 v-model是什么?怎么使用?
v-model用于表单数据的双向绑定,其实它就是一个语法糖,这个背后就做了两个操作:
v-bind绑定一个value属性
v-on指令给当前元素绑定input事件
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/79254.html