js中的变量声明:在js中变量没有使用声明符号进行声明的时候,系统会自动创建一个全区变量的声明方式声明该变量
var
符号进行声明,该符号声明变量会作为该作用域的全局变量let
进行声明,该符号的底层时函数自调用的形式,声明的变量只在本作用于本条声明之下起作用闭包:
//这里是一个对象
var object={
//对象的属性
name:'obj',
//获取对象的方法
getName:function(){
//方法体获取this指向
var that=this;
//返回内嵌方法体
return function(){
//通过let的只想问题访问obj的name
console.log(that.name)
}
}
}
//使用对象的方法的时候】、
obj.getName()
//这种方法时无法执行打印的,因为返回的是一个方法function(){console.log(that.name)}
obj.getName()();
//这种方式可以执行getName()方法
//创建方法,因为使用内嵌的return方式返回所以方法需要加()才能直接使用,函数自调用的方式
var add = (function () {
//内置属性,私有化,函数自调用的方式,该变量属于局部作用域
var counter = 0;
//返回方法
return function () {
<!-- 返回方法操作 -->
return counter += 1;
}
//
})();
//这种声明的方式直接使用add()即可使用
作用域:作用域在js中分为函数作用域与全局作用域,表示的时一个集合,全局作用域表示的就是所有地方都可以访问到的集合,局部作用域就是只有在局部可以访问的集合
闭包的变量在外部无法访问,(不要是上面2中的对象形式)
重载与重写
封装继承多态
//这就是封装
function Person(name , age , sex){
this.name = name ;
this.age = age ;
this.sex = sex ;
this.show = function (){
console.log( this.age + "========"+ this.sex );
}
}
//这里变更了this的指向
function Student(name , age , sex , score){
this.score = score ;
Person.apply(this,[name , age , sex]);
}
function Worker(name , age , sex , job){
this.job = job ;
Person.call(this,name , age , sex);
}
//这里使用的是原型链的方式
Dancer.prototype = new Person('Sunshine',18,'女');
function Dancer(salary ){
this.salary = salary ;
}
var student = new Student('Sunshine',18,'女',100);
var worker = new Worker('Sunshine',18,'女','IT');
var dancer = new Dancer(20000);
console.log(student);
console.log(worker);
console.log(dancer);
prototype
子对象,__proto__
一般使用来操作父对象创建‘类’
function person(name,age){
this.name=name;
this.age=age;
}
数组对象的遍历,一般来说可以使用for循环,或者for in循环,或者for of循环
对象中的属性是什么变量?
题目:要点使用var声明的变量会变量提升,赋值留在原地;使用let声明变量会在原地声明不会变量提升;不使用声明符号会在原地强制声明
// 第一个打印报错,因为没有声明
console.log(a);
// 已赋值,在原地强行创建变量a
a=10;
// 打印10
console.log(a)
this的使用情况
闭包向外层抛出方法的方式
什么是BFC
垂直居中的方式
图片与文字对齐
当子元素使用脱离文档流之后,父元素怎么自适应高度?
数据库数据类型
char与varcahr
数据库乱码问题
float和double区别
continue与break
n=5 var num=n++ + ++n + n++ + ++n +n;
js的数据类型
undefined 与null的区别
函数自调用
数组的方法
var arr = [1,2,3,4];
// 需要遍历的数组
var sum =0;
// 自定义变量存储求和
arr.forEach(function(value,index,array){
// 这里的valuex形参承接的时数组中的每一个元素,index承接的时数组元素的下标,array承接的是数组本身
array[index] == value; //结果为true
// 这里array[index]与value是array中同一个元素
sum+=value;
// 求和计算
});
// 打印sum
console.log(sum); //结果为 10
数组的元素的添加删除方法
特殊的删除与添加方法
splice与slice的区别
filter过滤方法与map指定元素处理方法,与ES6的reduce方法
reducer 函数接收4个参数:
javascript数组去重的方式
const aa=[...new Set(array)]
或者使用array.from方式冲类似数组对象中获取const bb=Array.from(new Set(array))
浅拷贝与深拷贝
浅拷贝的实现,与深拷贝的实现
优先级wenti
jsonP跨域
server.on('/login/:waysName',function(req, res){
req.params.waysName==>jsonp
req.query.callback==>test
// 主要的是后端判断是否使用jsonp的方式进行数据返回
// 前端script路径传递参数的时候需要传递一个callback函数名
// 该函数时前端脚本中全局夯函数,因为当jsonP方式获取到服务端的文件后会立即加载,然后会立即执行,这里调用全局函数用来处理数据
var urlPath = url.parse(req.url).pathname;
// 这里是使用url接续地址,哦判断是不是使用jsonP方式进行获取数据
var qs = querystring.parse(req.url.split('?')[1]);
// 这里时使用解析查询字符串确定返回的callback使用哪个方法进行树的处理
if(urlPath === '/jsonp' && qs.callback){
// 对返回头进行设置
res.writeHead(200,{'Content-Type':'application/json;charset=utf-8'});
// 需要发送的数据
var data = {
"name": "Monkey"
};
// 将其转化为json字符串
data = JSON.stringify(data);
// 拼接返回的json的字符串
var callback = qs.callback+'('+data+');';
// 返回字符串
res.end(callback);
}
else{
res.writeHead(200, {'Content-Type':'text/html;charset=utf-8'});
res.end('Hell World\n');
}
});
<script src="http://127.0.0.1:8080/login/jsonp?callback=test">script>
后端的时候挂载使用cors方式app.use(cors());这种方式中使用的挂载是没有设置具体参数的,这种情况表示的是允许所有的跨域请求
为单个的请求进行跨域部署:
app.get('/', cors(), (req, res) => {
res.json({
message: 'Hello World'
});
});
用选项配置cors:自定义选项配置跨域
var corsOptions = {
origin: 'http://localhost:8080',
optionsSuccessStatus: 200 // For legacy browser support
}
app.use(cors(corsOptions));
这种表示可以从地址localhost:8080访问该API,禁止其他域进行访问
39. 使用代理跨域方式
1. 再vue脚手架的项目中配置vue.config.js文件配置
module.exports = {
devServer:{
proxy:{
"/juhe":{
target:"http://apis.juhe.cn",
changeOrigin: true,
secure:false,
pathRewrite:{
"^/juhe":""
}
}
}
}
}
function handle(data){
console.log(data);
}
function test(sql,callback){
let arr=sql.split('');
callback(arr)
}
test('我是山大王',handle)
function draw(){
var canvas = document.getElementById('tutorial');
if(!canvas.getContext) return;
var ctx = canvas.getContext("2d");
ctx.fillStyle = "rgb(200,0,0)";
//绘制矩形
ctx.fillRect (10, 10, 55, 50);
ctx.fillStyle = "rgba(0, 0, 200, 0.5)";
ctx.fillRect (30, 30, 55, 50);
}
draw();
let const var
结构与赋值
map对象
Set对象
ES6 Proxy方式
4. Proxy 可以对目标对象的读取、函数调用等操作进行拦截,然后进行操作处理。Reflect 可以用于获取目标对象的行为,它与 Object 类似,但是更易读,为操作对象提供了一种更优雅的方式
5. Proxy类似使用了了属性访问器,自定义规则
let target = {
name: 'Tom',
age: 24
}
let handler = {
get: function(target, key) {
console.log('getting '+key);
return target[key]; // 不是target.key
},
set: function(target, key, value) {
console.log('setting '+key);
target[key] = value;
}
}
let proxy = new Proxy(target, handler)
proxy.name // 实际执行 handler.get
proxy.age = 25 // 实际执行 handler.set
// getting name
// setting age
// 25
面试重点
深拷贝与将拷贝的区别在于浅拷贝拷贝的对象与原目标对象指向的是不是同一个数据对象;浅拷贝拷贝的对象,两个对象有一个数据被更改,另外一个都会获取到被更改后的数据,深拷贝数据更改不会影响到另一个对象;另外先简单的数字字符串等赋值使用拷贝不会出现被更改的现象;这是因为存储的位置不同导致的;浅拷贝和深拷贝是针对存储在堆内存中的数据来说的,存储在栈内存的数据不存在深浅拷贝的现象
this的使用场景,在定义函数的时候且该this没有被使用,使用this,这里指向的是windows或者global全局对象;在调用的时候使用的this指向的是被调用的对象,谁调用指向谁;构造函数中的this一般是自动指向的空对象,函数内部的this就会被空对象替换掉;如果这个函数中包含多个对象,尽管这个函数是被最外层的对象所调用,this指向的也只是它上一级的对象
js的执行是同步的,也就是阻塞的,顺序执行,现在js中异步执行一段代码需要使用异步函数,比如说setTimeOut方式或者是SetInterval方式执行;另外就是使用事件监听的方式减函数执行为异步函数;使用观察者模式执行;使用ES6的Promises方式执行
事件模型指的是在HTML中的DOM操作,捕获,目标触发,冒泡;捕获阶段是首先要确定你需要在声明地方实现事件触发,需要通过DOM操作获取到绑定事件的元素;目标触发对触发事件的元素添加事件监听,等待触发获取触发事件;冒泡,指的是事件触发时,事件会从当前点击开始以从内向外的方式依次触发上层元素的事件,称为事件冒泡;
事件冒泡是当在一个元素上绑定一个事件,比如说点击事件,然后该事件被触发,如果定义了该事件触发处理函数,就会调用这个函数,如果没有就会先父级对象传递该事件,直至获取到事件处理函数,或者到达顶级元素(需要注意的是,冒泡会一致冒泡到顶级祖先元素);阻止事件冒泡的方法:1使用event.stopPropagation()
进行事件冒泡的阻止;注意的是该方法会阻止事件冒泡但是不会阻止先超链接标签的默认事件行为;2jquery使用return false方式可以阻止冒泡和标签的默认行为;3、使用event.preventDefault();
会阻止标签的默认事件
常用的数组的API有以下几种作用:截取数组、删除数组元素、删除并插入数组元素、将数组转换为字符串、数组的链接组合为新数组、获取数据元素的下标、数组是否包含特定的元素、数组的反转、数组的排序、数组的遍历,方法:
css弹性布局的使用方法:display:flex
弹性布局的几个属性:
css布局单位有px像素,em相对父元素的字体大小,rem相对根元素的字体大小,%百分比,vw相对屏幕宽度的百分比,vh相对屏幕高度的百分比,rpx手机端的相对宽度但闻,移动端全部为750rpx
css选择器,有id选择器,类选择器,伪类选择器,属性选择器,子代选择器,后代选择器,兄弟选择器,标签选择器,分组选择器等等
清除浮动:在浮动的元素后面紧接着的元素的样式中使用clear属性;使用BFC方式清除浮动,(父元素使用overflow:hidden、父元素也添加浮动属性、使用::after伪类为元素添加一个clear属性、父元素使用定位)
闭包就是减变量放到了函数作用域中这样在全局的情况下就没法直接访问函数作用域中的变量,然后为了访问函数作用域的变量,在函数内部定义与获取或者操作方法,然后将该方法作为返回值返回外层对象
跳转页面后有些样式没有生效,1、样式写错了2、样式绑定的元素没有加载、3、样式文件路径错误
使用history的时候,history唯一改变的就是url的模式,使用history后跳转页面后的样式没有生效,可能是因为打包产生了路径的变化但是在路由中并没有做相应的配置
箭头函数省略了function 关键字,当参数只有一个的时候,甚至省略了小括号,当函数体是return时且只有一行的时候省略了大括号和关键之return
computed是计算属性,组件的声明周期中只执行一次;watch是监听函数模块,只要被监听的变量出现变化,就会触发对应的监听函数。监听函数使用被监听的函数的变量名作为监听的方法名
keep-alive保持存活,组件间的相互切换默认是会销毁掉被切换掉的组件,重新切换到该组件的时候重新初始化,当有要求保持不销毁组件的时候要求保持原来的状态就可以使用keep-alive
使用方法是在路由字典中使用meta
字段,添加keepAlive?:true
属性即可,然后使用keep-alive的标签包含router-view,结合v-if使用
<keep-alive>
<router-view v-if='$route.meta.keepAlive'>
keep-alive>
使用方式二:组件的script
结构中,包含参数name:'自定义命名';
,在使用的时候使用keep-alive
标签包含组件使用标签,并使用属性include='name'
<script>
export default {
name: 'a',
data () {
return {}
}
}
script>
<keep-alive include='a'><component>component>keep-alive>
<keep-alive exclude="a"><component>component>keep-alive>
这三个都是VUEX的组成部分,Mutation表示的是对VUEX保存的数据的修改方法的集合,action表示的是一些执行方法的集合,提交的是mutations,getter表示的是获取数据的方法的集合
使用方式一:
getters: 直接使用this. s t o r e . g e t t e r s . 方 法 名 ( 参 数 ) m u t a t i o n s : ‘ t h i s . store.getters.方法名(参数) mutations:`this. store.getters.方法名(参数)mutations:‘this.store.commit(‘increment’),传递参数的使用方式:
store.commit(‘increment’, 10)actios:
store.dispatch(‘increment’)**使用方式二:** getters:在使用的组件中使用
import { mapGetters } from 'vuex’在组件的需要使用的对象中使用打散符号,将方法布置到当前组件中 mutations:
import { mapMutations } from ‘vuex’`
model+view+view-model,model+view+controler
diff算法就是用来比较虚拟dom树和真实DOM树的不同之处,然后将虚拟dom树的不同指出修改到真实dom树上
for: 循环可以使用break,containue,return
forEach: 数组自带的遍历方式,自动遍历数组,
map: 只能遍历数组,具有返回值
for of: 遍历具有迭代器属性的数组类数组对象,无法获取下标
for in: 会遍历原型链数据
Reduce里传递的是用改方法函数,作为累加器,如果不传递参数,会报错undefined is not a function
get是不安全的,属于明文,所有的传递的参数信息都会在url中显示出来,post对用户来说是不可见的;get传递的数据少,因为url的长度是幽香的,post传递的数据多,一般漠然不受限制;get执行效率比post高
JSON.parse()将json字符串还原成对象,JSON.stringify()将对象转换为字符串
axios本身是一种异步请求方式,想要使用axios进行同步执行,需要使用async -await
ES7中对异步操作可以使用async -await进行同步限制,async修饰的同步方法需要等待await修饰的代码操作完成才能继续执行
使用方式:
async reated(){
let data = await axios.get(url,pramas{
id:1
}).then(res=>console.log(res))
}
可以创建一个js文件用来保存封装的axios方法
- 导入axios对象 import axios from 'axios'
- 设置默认请求地址 axios.defaults.baseURL = 'http://shopping.com/'
- 设置默认超时事件 axios.defaults.timeout = 10000
- 请求头设置 axios.defaults.headers.post['Content=Type']='application/json'
- 设置方法 function get(){} function post(){}
- 将设置的请求方法进行导出 moudle.export={get,post}
虚拟DOM树是一个元素对象树,用来描述一段html片段的,当页面渲染的时候,会创建一个虚拟dom树,再次渲染的时候会从新创建一个新的虚拟DOM树,通过diff算法,记录新旧虚拟DOM的差异从而将差异更新到真实DOM树上
vue的双向绑定的原理是虚拟DOM树加上属性访问器,原理的官方名称为数据劫持加发布者模式+订阅者模式;使用属性访问器给data中的对象添加get,set规则,使用虚拟DOM树查找修改差异,渲染到真实DOM树上;view-model可以通过事件绑定进行一个监听,动态更改数据变化;虚拟DOM树实现从 model到view的数据渲染
两者都是根据条件判断是否显示,不同之处在于v-if是直接销毁元素,而不是隐藏元素,v-show是对元素进行了隐藏,display:none
vue的声明周期有create,mount,update,destory分别由两个钩子函数,before和after,表示该生命周期前后执行。create生命周期包含beforeCreate,created,afterCreate三个阶段
js中所有的函数都有一个原型对象属性,这个原型默认是Object的实例,也就是一个空对象;原型链简单来说就是由原型对象属性构成的链状结构,对象的__proto__
属性就是该对象的原型,原型也是对象也有该属性,所以形成一个链状结构,这个结构到Object这里也就到头了;instanceof
是判断实例对象的__proto__和生成该实例的构造函数的prototype是不是引用的同一个地址.使用原型链可以实现继承。
首先变量方面的由let,const,然后是解构,打散收集符号,模板字符串,箭头函数,参数加强(默认值设置),class类与继承extend,子类的super方法,for of遍历方法和for in
一种方法利用ES6的Set对象元素不能重复,且Set的构造方法可以传递一个数组,直接将数组作为参数创建一个Set对象,然后将对象打散到一个新的数组中,新的数组没有重复元素;一种思想,创建一个新空数组,遍历原本的数组,判断每个元素在新数组中是否存在,存在就pass不存在就添加到新数组,至于使用什么方法,for循环遍历,数组的forEach方法,数组的map方法,indexof,includes等均可
Promises由三种状态分别是进行中,已履行,拒绝,pending,fulfilled,rejected,进行中表示正在执行,这个时候不会触发方式,旅行表示执行结束通过,这时候触发resolve方法传递参数给.then方法里的callback,拒绝触发reject方法,也会传递参数,给.catch方法
promises是一种构造函数,使用new Promises创建的对象都会带有.then,.catch…all等方法,promises用来解决使用异步函数回调函数的深层嵌套产生回调地狱的象先,使得异步函数可以实现链式编辑;async以及await是ES7出现的,优化Promises的解决方案;async是修饰符号,被修饰的函数会默认返回一个promises对象,所以可以直接进行.then操作;await也是一个修饰符,和async一致,返回的是一个Promises对象,表示的是等待一个异步操作完成的结果
Promise可以避免异步种的回调地狱 使异步变得更加简单清新,更可控
async以及awai却是为了简化Promise,可以说async以及awai是JavaScript异步编程目前的终级解决方案
vue-router是路由,官方的路由管理器。通过vue-router方便管理和跳转组件。vue项目都是单页面项目,使用路由可以实现组件间的跳转。在vue-router单页面应用中,则是路径之间的切换,也就是组件的切换。路由模块的本质 就是建立起url和页面之间的映射关系。而之所以不适用a标签是因为单页面标签只有一个html
vue组件间的传参一般由vueX方式传参,路由传参,父子组件间传参可以使用props方式传参,子传父参数不仅可以使用vueX方式传递参数,还可以使用Vue本身(在父元素中定义方法myfun,子元素中使用this.$emit(‘myfun’,item)既可以激活使用父组件中的myfun方法,并传递子组件的数据)
路由传参方式一:在路由字典中的path属性中配置例如 path: ‘/login/:userId/:id’,配置字典中的name属性,传值页面的跳转使用传递对象的方式进行跳转,使用name关键字进行路由的映射,使用params对象传递查询字符串,获取查询字符串的方式是this. r o u t e . p a r a m s . 查 询 参 数 名 ( 或 者 直 接 使 用 p a t h t h i s . route.params.查询参数名(或者直接使用path this. route.params.查询参数名(或者直接使用paththis.router.push(’/login/uname.upwd’方式,获取还是使用this.$route.params.userId...
))
路由传递参数二:使用query的方式进行查询字符串传参,传递参数this.$router.push({path:'/login',query:{userId:'雄安命'}})
,获取传递参数的方式是this.$route.query.userId
或者是this.$router.currentRoute.query.userId
第三种使用方式:
组件传值一般使用的较多的是vueX方式,该方式满足各种方式的组件传值,另外还有利用路由跳转携带参数传值的,父子组件中可以使用props方式进行父传子,子传父可以使用vuex,使用vue的emit方法唤醒父组件的自定义方法,并传递子组件的参数
vueX是一公告的数据源,是一个专门为vue开发的状态管理模式,核心是store,用来保存数据的,还有其他几大对象比如getters,moutations,actions,moudles几大模块,分别保存对state的数据的获取方法,更改方法,对更改方法集合对象操作的方法,以及模块管理集合
如果需要监听路由变化可以使用vue的watch方法
watch:{
$route(to,from){
console.log(from.path);//从哪来
console.log(to.path);//到哪去
this.刷新方法
}
}
监听路由变化获取新老路由的值
watch:{
$route:{
handler(val,oldval){
console.log(val);//新路由信息
console.log(oldval);//老路由信息
},
// 深度观察监听
deep: true
}
}
监听路由触发的方法
methods:{
getPath(){
console.log(1111)
}
},
watch:{
'$route':'getPath'
}
全局监听路由可以使用路由首位监听
// 全局监听路由
router.beforeEach((to, from, next) => {
console.log(to);
next();
});
组件内监听路由
beforeRouteEnter (to, from, next) {
// 在渲染该组件的对应路由被 confirm 前调用
// 不!能!获取组件实例 `this`
// 因为当钩子执行前,组件实例还没被创建
},
beforeRouteUpdate (to, from, next) {
// 在当前路由改变,但是该组件被复用时调用
// 举例来说,对于一个带有动态参数的路径 /foo/:id,在 /foo/1 和 /foo/2 之间跳转的时候,
// 由于会渲染同样的 Foo 组件,因此组件实例会被复用。而这个钩子就会在这个情况下被调用。
// 可以访问组件实例 `this`
},
beforeRouteLeave (to, from, next) {
// 导航离开该组件的对应路由时调用
// 可以访问组件实例 `this`
}
什么是路由首位?路由首位就是在路由执行之前或者之后执行的路由方法,主要用来通过跳转或取消的方式守卫导航。路由首位有全局的,单个的还有组件级别的。
全局前置守卫:前置守卫顾名思义就是导航触发的时候先会经过前置守卫,当前置守卫执行执行玩发出resolve之后,导航才会执行
全局解析守卫:导航被确认之前,同时在所有组件内守卫和异步路由组件被解析之后,解析守卫就被调用。
全局后置钩子: 这些钩子不会接受 next 函数也不会改变导航本身
路由独享守卫: 单独在路由字典中对应的路由上直接设置路由
组件内的守卫: 组件内特殊的钩子方法beforeRouteEnter,beforeRouteUpdate,beforeRouteLeave分别表示路由调用前,当前路由改变但是该组件被复用,导航离开当前组件
Echarts可视化组件,vantUI,miniUI,elementUI,bootstrap,swiper等
vm.$on('test', function (msg) {
console.log(msg)
})
vm.$emit('test', 'hi')
可以利用监听事件和触发事件进行子传父的阐述传递
display:none: 会让元素完全从渲染树中消失,渲染的时候不占据任何空间, 不能点击, visibility: hidden:不会让元素从渲染树消失,渲染元素继续占据空间,只是内容不可见,不能点击 opacity: 0: 不会让元素从渲染树消失,渲染元素继续占据空间,只是内容不可见,可以点击
text-overflow: ellipsis; overflow: hidden; display: -webkit-box; /重点,不能用block等其他/ -webkit-line-clamp: 2; //行数 /*! autoprefixer:off / -webkit-box-orient: vertical; / autoprefixer:on */
这种指定了文本的行数,可以多行不确定文本函数但确定会溢出,使用over-flow隐藏溢出内容,然后使用伪类::after方法创建一个伪元素,使用内容为省略号
div{
width: 300px;
position: relative;
line-height: 1.4em;
height: 4.2em;
overflow: hidden;
}
div::after{
content: "...";
position: absolute;
right: 0;
bottom: 0;
}
防抖就是避免用户连续在一定时间内不停触发事件,限制单位时间内时间触发的次数;节流:在事件发生后一段时间后执行触发事件,这期间用户继续触发动作视为只触发一次,直到事件执行完毕后才能重新触发