看看面试题,只是为了查漏补缺,看看自己那些方面还不懂。切记不要以为背了面试题,就万事大吉了,最好是理解背后的原理,这样面试的时候才能侃侃而谈。不然,稍微有水平的面试官一看就能看出,是否有真才实学还是刚好背中了这道面试题
<body>
<div id="app">
<input type="text" id="txt">
<p id="show"></p>
</div>
</body>
<script type="text/javascript">
var obj = {}
Object.defineProperty(obj, 'txt', {
get: function () {
return obj
},
set: function (newValue) {
document.getElementById('txt').value = newValue
document.getElementById('show').innerHTML = newValue
}
})
document.addEventListener('keyup', function (e) {
obj.txt = e.target.value
})
</script>
以 input 表单元素为例:
<input v-model='something'>
相当于
<input v-bind:value="something" v-on:input="something = $event.target.value">
如果在自定义组件中,v-model 默认会利用名为 value 的 prop 和名为 input 的事件,如下所示:
父组件:
<ModelChild v-model="message"></ModelChild>
子组件:
<div>{{value}}</div>
props:{
value: String
},
methods: {
test1(){
this.$emit('input', '小红')
},
},
(版本在不断更新,以下的区别有可能不是很正确。我工作中只用到vue,对angular和react不怎么熟)
<div id="app">
{{msg}}
<div>这是模板的第一种使用方法1</div>
</div>
<template id="bot">这是模板的第三种使用方法,不常用3</template>
<script>
<div id="bot">模板的第四种创建方法4</div>
</script>
<script>
var vm1 = new Vue({
data: {
msg: "data属性"
},
methods: {
Personal:function () {
console.log("methods方法存放方法")
}
},
template: `<div>模板的第二种使用方法2</div>`,
//template:"#bot",
render: (createElement) => {
return createElement("h1",{"class":"类名","style":"color: red"},"这一个render属性创建的虚拟dom")
},
})
</script>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="javascript/vue.min.js"></script>
</head> <body>
<div id="app">
<p>{{message}}</p> //直接在模板中绑定表达式
<p>{{message.split('').reverse().join('')}}</p> //运用计算属性
<p>{{reverseMessage}}</p> //运用methods方式
<p>{{methodMessage()}}</p>
</div>
<script>
var vm=new Vue({
el:"#app",
data:{
message:"hello"
},
computed:{
reverseMessage:function(){
return this.message.split('').reverse().join('');
}
},
methods:{
methodMessage:function () {
return this.message.split('').reverse().join('');
}
}
})
</script>
</body>
</html>
const store = new Vuex.Store({ //store实例
state: {
count: 0
},
mutations: {
increment (state) {
state.count++
}
},
actions: {
increment (context) {
context.commit('increment')
}
}
})
const moduleA = {
state: { ... },
mutations: { ... },
actions: { ... },
getters: { ... }
}
const moduleB = {
state: { ... },
mutations: { ... },
actions: { ... }
}
const store = new Vuex.Store({
modules: {
a: moduleA,
b: moduleB
})
# 1.创建局部指令
var app = new Vue({
el: '#app',
data: {
},
// 创建指令(可以多个)
directives: {
// 指令名称
dir1: {
inserted(el) {
// 指令中第一个参数是当前使用指令的DOM
console.log(el);
console.log(arguments);
// 对DOM进行操作
el.style.width = '200px';
el.style.height = '200px';
el.style.background = '#000';
}
}
}
})
# 2.全局指令
Vue.directive('dir2', {
inserted(el) {
console.log(el);
}
})
# 3.指令的使用
<div id="app">
<div v-dir1></div>
<div v-dir2></div>
</div>
# html代码:
<div id="app">
<input type="text" v-model="msg" />
{{msg| capitalize }}
</div>
# JS代码:
var vm=new Vue({
el:"#app",
data:{
msg:''
},
filters: {
capitalize: function (value) {
if (!value) return ''
value = value.toString()
return value.charAt(0).toUpperCase() + value.slice(1)
}
}
})
# 全局定义过滤器
Vue.filter('capitalize', function (value) {
if (!value) return ''
value = value.toString()
return value.charAt(0).toUpperCase() + value.slice(1)
})
# 过滤器接收表达式的值 (msg) 作为第一个参数。capitalize 过滤器将会收到 msg的值作为第一个参数。
<keep-alive include='include_components' exclude='exclude_components'>
<component>
<!-- 该组件是否缓存取决于include和exclude属性 -->
</component>
</keep-alive>
<!-- 逗号分隔字符串,只有组件a与b被缓存。 -->
<keep-alive include="a,b">
<component></component>
</keep-alive>
<!-- 正则表达式 (需要使用 v-bind,符合匹配规则的都会被缓存) -->
<keep-alive :include="/a|b/">
<component></component>
</keep-alive>
<!-- Array (需要使用 v-bind,被包含的都会被缓存) -->
<keep-alive :include="['a', 'b']">
<component></component>
</keep-alive>
<!-- 对象语法:-->
<div v-bind:class="{ active: isActive, 'text-danger': hasError }"></div>
data: {
isActive: true,
hasError: false
}
<!-- 数组语法 -->:
<div v-bind:class="[isActive ? activeClass : '', errorClass]"></div>
data: {
activeClass: 'active',
errorClass: 'text-danger'
}
<!-- 对象语法 -->:
<div v-bind:style="{ color: activeColor, fontSize: fontSize + 'px' }"></div>
data: {
activeColor: 'red',
fontSize: 30
}
<!-- 数组语法 -->:
<div v-bind:style="[styleColor, styleSize]"></div>
data: {
styleColor: {
color: 'red'
},
styleSize:{
fontSize:'23px'
}
}
props: ['initialCounter'],
data: function () {
return {
counter: this.initialCounter
}
}
props: ['size'],
computed: {
normalizedSize: function () {
return this.size.trim().toLowerCase()
}
}
<!-- 为了解决第一个问题,Vue 提供了以下操作方法: -->
// Vue.set
Vue.set(vm.items, indexOfItem, newValue)
// vm.$set,Vue.set的一个别名
vm.$set(vm.items, indexOfItem, newValue)
// Array.prototype.splice
vm.items.splice(indexOfItem, 1, newValue)
<!-- 为了解决第二个问题,Vue 提供了以下操作方法: -->
// Array.prototype.splice
vm.items.splice(newLength)
// Parent.vue
<Child @mounted="doSomething"/>
// Child.vue
mounted() {
this.$emit("mounted");
}
// Parent.vue
<Child @hook:mounted="doSomething" ></Child>
doSomething() {
console.log('父组件监听到 mounted 钩子函数 ...');
},
// Child.vue
mounted(){
console.log('子组件触发 mounted 钩子函数 ...');
},
// 以上输出顺序为:
// 子组件触发 mounted 钩子函数 ...
// 父组件监听到 mounted 钩子函数 ...
Vue 源码
export function set (target: Array<any> | Object, key: any, val: any): any {
// target 为数组
if (Array.isArray(target) && isValidArrayIndex(key)) {
// 修改数组的长度, 避免索引>数组长度导致splcie()执行有误
target.length = Math.max(target.length, key)
// 利用数组的splice变异方法触发响应式
target.splice(key, 1, val)
return val
}
// key 已经存在,直接修改属性值
if (key in target && !(key in Object.prototype)) {
target[key] = val
return val
}
const ob = (target: any).__ob__
// target 本身就不是响应式数据, 直接赋值
if (!ob) {
target[key] = val
return val
}
// 对属性进行响应式处理
defineReactive(ob.value, key, val)
ob.dep.notify()
return val
}
function createKeyToOldIdx (children, beginIdx, endIdx) {
let i, key
const map = {}
for (i = beginIdx; i <= endIdx; ++i) {
key = children[i].key
if (isDef(key)) map[key] = i
}
return map
}
**不带参数**
<router-link :to="{name:'home'}">
<router-link :to="{path:'/home'}"> //name,path都行, 建议用name
// 注意:router-link中链接如果是'/'开始就是从根路由开始,如果开始不带'/',则从当前路由开始。
带参数
<router-link :to="{name:'home', params: {id:1}}">
// params传参数 (类似post)
// 路由配置 path: "/home/:id" 或者 path: "/home:id"
// 不配置path ,第一次可请求,刷新页面id会消失
// 配置path,刷新页面id会保留
// html 取参 $route.params.id
// script 取参 this.$route.params.id
<router-link :to="{name:'home', query: {id:1}}">
// query传参数 (类似get,url后面会显示参数)
// 路由可不配置
// html 取参 $route.query.id
// script 取参 this.$route.query.id
<!-- 不带参数 -->
this.$router.push('/home')
this.$router.push({name:'home'})
this.$router.push({path:'/home'})
<!-- query传参 -->
this.$router.push({name:'home',query: {id:'1'}})
this.$router.push({path:'/home',query: {id:'1'}})
// html 取参 $route.query.id
// script 取参 this.$route.query.id
this.$router.push({name:'home',params: {id:'1'}}) // 只能用 name
// 路由配置 path: "/home/:id" 或者 path: "/home:id" ,
// 不配置path ,第一次可请求,刷新页面id会消失
// 配置path,刷新页面id会保留
// html 取参 $route.params.id
// script 取参 this.$route.params.id
query类似get 跳转之后页面 url后面会拼接参数,类似?id=1, 非重要性的可以这样传, 密码之类还是用params刷新页面id还在
params类似 post, 跳转之后页面 url后面不会拼接参数 , 但是刷新页面id 会消失
3.this.$router.replace() (用法同上,push)
4. this.$router.go(n) ()
//简单闭包
function out(){
var a = 1;
function inner() {
console.log(a);
}
inner()
}
out()
//稍微复杂的闭包
function fun(a,b) {
//let a = 0
console.log(b)
return {
fun:function (m) {
//let m = 1
return fun(m,a)
}
}
}
//*let a = fun(0)
a.fun(1)
a.fun(2)
a.fun(3);//undefined 0 0 0*/
// let b = fun(0).fun(1).fun(2);//undefined 0 1
let c = fun(0).fun(1);//undefined 1
c.fun(2)
c.fun(3)
感谢支持、后续更新大量面试题、关注不迷路哦