文章目录
- 1.vue双向绑定的原理
- 2.解释单向数据流和双向数据绑定
- 3.如何去除url中的“#”(history模式和hash模式的区别)
- 4.对MVC、MVVM的理解
- 5.介绍虚拟DOM树
- 6.vue生命周期(4个阶段,8个钩子函数)
- 7.组件间通信
- 8.vue-router路由实现
- 9.v-if 和 v-show 的区别
- 10.$route 和 $router 的区别
- 11.vue组件data为什么必须是函数
- 12.计算属性computed和事件methods有什么区别
- 13.jQuery和vue的区别
- 14.vue中怎么自定义指令
- 1)全局注册
- 2)局部注册
- 15.vue中怎么自定义过滤器
- 16.对keep-alive的了解
- 17.active-class
- 18.嵌套路由
- 19.路由跳转
- 1) 声明式
- 2) 编程式
- 20.懒加载(按需加载路由)
- 问题:
- 原因:
- 解决方案:
- 1) 配置打包工具,将组件分别打包到不同的js代码块中
- 2)当路由请求到该组件时,才动态加载组件的内容
- 21.vuex
- 22.Vue.use(Vuex)
- 23.vue-router导航钩子
- 24.vue自定义指令
- 25.vue的双向绑定原理
1.vue双向绑定的原理
2.解释单向数据流和双向数据绑定
- 单向数据流:
data改变页面会自动改变,页面改变不影响data - 双向数据绑定
data改变页面会自动改变,页面改变影响data自动改变
3.如何去除url中的“#”(history模式和hash模式的区别)
vue-router默认使用hash模式,所以在路由加载时,项目中的URL会自带#;
如果不想使用#,可以使用vue-router的另一种模式history
new Router({
mode:'history',
routes: []
})
4.对MVC、MVVM的理解
5.介绍虚拟DOM树
虚拟DOM树:
仅包含 可能变化的节点 和 可能变化的属性 的树结构。
虚拟DOM树内容较真实DOM树内容少,便于快速遍历比较不同。
当data中模型变量改变时,会通知虚拟DOM树 ==> 虚拟DOM树先缓存本次的修改在元素对象上 ==> 将一批修改生成新的DOM子树,和原虚拟DOM树做对比 ==> 一旦发现不同的元素或内容,就只更新有修改的元素 ==> 虚拟DOM树中,封装了传统DOM API:createElement() appendChild() .innerHTML,避免了大量重复的代码
6.vue生命周期(4个阶段,8个钩子函数)
- beforeCreate() 在实例创建之间执行,数据未加载状态
- created() 在实例创建,数据加载之后,能初始化数据,DOM渲染之前执行
- beforeMount() 虚拟dom树已创建完成,在数据渲染前最后一次更改数据
- mounted() 页面、数据渲染完成,真实dom树挂载完成
- beforeUpdate() 重新渲染之前触发
- updated() 数据已经更改完成,dom也重新render完成,更改数据会陷入死循环
- beforeDestory() 销毁前执行,实例仍然完全可用
- destoryed() 销毁后执行
7.组件间通信
组件间通信
8.vue-router路由实现
9.v-if 和 v-show 的区别
10.$route 和 $router 的区别
11.vue组件data为什么必须是函数
12.计算属性computed和事件methods有什么区别
13.jQuery和vue的区别
14.vue中怎么自定义指令
1)全局注册
2)局部注册
15.vue中怎么自定义过滤器
16.对keep-alive的了解
17.active-class
是 vue-router 模块的 router-link 组件,定义router-link在点击时的样式
18.嵌套路由
代码如下
// router/index.js
import Vue from 'vue'
import Router from 'vue-router'
import home from '@/views/home'
import index from '@/views/index'
import details from '@/views/details'
import login from '@/views/login'
Vue.use(Router)
export default new Router({
linkExactActiveClass:'link-active',
routes: [
{
path: '/',
name: 'home',
component: home,
children: [
{
path: '/',
name: 'index',
component: index,
},
{
path: '/details',
name: 'details',
component: details,
}
]
},
{
path: '/login',
name: 'login',
component: login
}
]
})
<!-- App.vue -->
<template>
<div id="app">
<router-view/>
</div>
</template>
<script>
export default {
name: 'App'
}
</script>
<style>
.link-active {
color:brown
}
#app {
font-family: 'Avenir', Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
</style>
<!-- myheader.vue -->
<template lang="">
<div>
<h1>页头</h1>
<ul>
<li>
<router-link to="/">首页</router-link>
</li>
<li>
<router-link to="/details">详情页</router-link>
</li>
<li>
<router-link to="/login">登陆页</router-link>
</li>
</ul>
<hr>
</div>
</template>
<script>
export default {
}
</script>
<style lang="">
</style>
<!-- home.vue -->
<template lang="">
<div>
<my-header></my-header>
<router-view></router-view>
</div>
</template>
<script>
import myHeader from '@/components/myheader.vue'
export default {
components: {
myHeader
}
}
</script>
<style lang="">
</style>
<!-- index.vue -->
<template lang="">
<div>
<h2>这里是首页</h2>
</div>
</template>
<script>
export default {
}
</script>
<style lang="">
</style>
<!-- details.vue -->
<template lang="">
<div>
<h2>这里是详情页</h2>
</div>
</template>
<script>
export default {
}
</script>
<style lang="">
</style>
<!-- login.vue -->
<template lang="">
<div>
<h1>登录页</h1>
<router-link to="/">返回首页</router-link>
</div>
</template>
<script>
export default {
}
</script>
<style lang="">
</style>
19.路由跳转
1) 声明式
<!-- myheader.vue -->
<template lang="">
<div>
<h1>页头</h1>
<ul>
<li>
<router-link to="/">首页</router-link>
</li>
<li>
<router-link to="/details">详情页</router-link>
</li>
<li>
<router-link to="/login">登陆页</router-link>
</li>
</ul>
<hr>
</div>
</template>
<script>
export default {
}
</script>
<style lang="">
</style>
2) 编程式
$router.push('index')
20.懒加载(按需加载路由)
问题:
vue首屏加载非常慢
原因:
当打包应用时,将所有JavaScript代码打包在一个文件中,导致js代码非常庞大,从而严重影响页面加载速度
解决方案:
1) 配置打包工具,将组件分别打包到不同的js代码块中
module.exports = {
context: path.resolve(__dirname, '../'),
entry: {
app: './src/main.js'
},
output: {
path: config.build.assetsRoot,
filename: '[name].js',
chunkFilename: '[name].js', // 实现懒加载 build/webpack.base.conf.js
publicPath: process.env.NODE_ENV === 'production'
? config.build.assetsPublicPath
: config.dev.assetsPublicPath
},
// ...
}
2)当路由请求到该组件时,才动态加载组件的内容
路由字典中,路由配置和以前完全一样
但是在引入组件对象时,
import login from '@/views/login'
要改为
const login = ()=>{import('@/views/login')} // 仅定义函数,不执行,所以暂时未从内存中引入
当用户在vue中请求当前组件对应的路由地址时,由vue-router自动调用加载函数,动态请求login.vue组件对象
21.vuex
vue框架中状态管理。在main.js引入store.js,注入
应用场景:单页应用中,组件之间的状态,或者是否登陆
vuex中有5中属性,分别是
1. state,保存模型变量,相当于仓库
2. getter 相当于计算属性,
3. mutation 保存对单个模型变量的操作,譬如修改或者读取
4. action 调用mutation中的操作实现比较复杂的功能
5. module 当vuex中维护的数据比较庞大时,可以用module对vuex进行分组维护
// Store.js
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
n: 0,
},
mutations: {
nadd(state){
state.n++
},
nminus(state){
state.n--
},
},
actions: {
calc(context){
context.commit('nadd')
context.commit('nadd')
context.commit('nminus')
}
}
})
// main.js
import Vue from 'vue'
import App from './App'
import router from './router'
import store from './store'
// ...
22.Vue.use(Vuex)
如下所示,Vue.use(Vuex)做了什么
// Store.js
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
n: 0,
},
mutations: {
nadd(state){
state.n++
},
nminus(state){
state.n--
},
},
actions: {
calc(context){
context.commit('nadd')
context.commit('nadd')
context.commit('nminus')
}
}
})
Vue.use(Vuex) 方法执行的是install方法,它实现了vue实例对象的init方法和注入,使传入的store对象能设置到vue上下文环境的store中,因此在vue组件中的任意地方都能够通过this.store访问到该store
23.vue-router导航钩子
24.vue自定义指令
25.vue的双向绑定原理
vue.js是采用 数据劫持 结合 发布者-订阅者模式 的方式,通过Object.defineProperty()来劫持各个属性的setter、getter,在数据变动时发布消息给订阅者,触发相应的监听回调。
具体步骤:
- 需要observe的数据对象进行递归遍历,包括子属性对象的属性,都加上setter和getter,这样的话,给这个对象的某个值赋值,就会触发setter,那么就能监听到数据变化
- compile解析模板指令,将模板中的变量替换成数据,然后初始化渲染页面视图,并将每个指令对应的节点绑定更新函数,添加监听数据的订阅者,一旦数据有变动,收到通知,更新视图
- watcher订阅者是observer和compile之间通信的桥梁,主要做的事情是:
- 在 自身实例化时往属性订阅器(dep)里面添加自己
- 自身必须有个update方法
- 待属性变动dep.notice()通知时,能调用自身的update()方法,并触发compile中绑定的回调
- MVVM作为数据绑定的入口,整合 observer、compile、和watcher三者,通过observer来监听自己的model数据变化,通过compile来解析模板指令,最终利用watcher来搭起observer和compile之间的通信桥梁,达到 数据变化 -> 视图更新;视图交互变化(input) -> 数据model变更的双向绑定效果