1.Vue概述
1.1 什么是Vue
Vue (读音 /vjuː/,类似于 view) 是一套用于构建用户界面的渐进式框架。与其它大型框架不同的是,Vue 被设计为可以自底向上逐层应用。Vue 的核心库只关注视图层,不仅易于上手,还便于与第三方库或既有项目整合。另一方面,当与现代化的工具链以及各种支持类库结合使用时,Vue 也完全能够为复杂的单页应用提供驱动。
渐进式: 构建项目可以由简单到复杂。
1.2 Vue优点
1)体积小,压缩后的文件只有33k。
2)运行效率更高 采用虚拟机DOM,一种可以预先通过javaScript对数据进行计算。把最终的DOM操作计算出来并且优化的技术。 由于这个DOM操作属于预处理操作,并没有真实的操作DOM ,所以叫做虚拟DOM。
3)双向数据绑定,让开发者不再去操作DOM,将更多的经历投入到业务中。
4))生态丰富,市面上有大量的开源项目基于vue 进行开发,成熟稳定。
1.3 VUE框架中的MVVM思想
1)字母解释
- M model 数据
- V view 视图
- VM (view-model) 数据和视图的控制
2)当页面数据发生变化时,则通过dom监听将数据传给model
当model的数据发生变化时,则通过数据绑定 绑定到页面中
1.4 vue项目目录作用
1. build文件夹:打包配置的文件夹
- webpack.base.conf.js :打包的核心配置
- build.js:构建生产版本,项目开发完成之后,通过build.js打包(加载base与prod,读取完之后通过webjpack命令对项目进行打包)
- webpack.prod.conf.js:被build.js调用,webpack生产包的一个配置。基础代码都在1.1里面写,1.3是对1.1的扩展与补充
- dev-client.js:热更新的插件,进行对客户端进行重载
- dev-server.js:服务器。(背后的原理是启动一个express框架,这是一个基于node做的一个后端框架,后端框架可以在前端起一个服务)
- vue-loader.conf.js:被base加载,
- utils.js:工具类,公共的配置
2. config文件夹:打包的配置,webpack对应的配置
- index.js:可与1.1合并成一个文件,但由于spa想做一个清晰的架构,因此把它们拆分开了
3. src文件夹:开发项目的源码
4. App.vue : 入口组件
5. static文件夹:静态资源,图片
6. .babelrc:ES6解析的配置
7. .gitignore:忽略某个或一组文件git提交的一个配置
8. index.html:单页面的入口,通过webpack的打包构建之后,会对src源码进行编译,最终把它们插入到html里面来
9. package.json:基础配置,告诉我们项目的信息(版本号、项目姓名、依赖)
10. node_modulues:项目的安装依赖
设置vue启动项目后默认显示的页面
通过配置路由,可以设置vue项目启动后默认显示的页面。路由的path设置为path:"/",启动项目后就会显示默认的组件页面。
import Vue from 'vue'
import Router from 'vue-router'
Vue.use(Router)
import Home from '../components/Home.vue'
import View from '../components/View.vue'
import ViewTwo from '../components/ViewTwo.vue'
export default new Router({
routes: [
{
path:"/", // path 设置为 “/” ,默认显示该页面
component:Home,
name:"Home"
},
{
path:"/view",
component:View,
name:"View"
},
{
path:"/viewtwo",
component:ViewTwo,
name:"ViewTwo"
}
],
mode:"history" // mode 设置为history ,去掉地址栏上的 # 号
})
vue项目中自定义页面标题
main.js中添加以下代码
Vue.directive('title', {//单个修改标题
inserted: function (el, binding) {
document.title = el.dataset.title
}
})
然后直接在想要的页面中单独设置标题
<div class="process_detail-page" v-title data-title="待办测试也"></div>
vue中文件在assets与static的区别
相同点:资源在html中使用,都是可以的。
不同点:使用assets下面的资源,在js中使用的话,路径要经过webpack中file-loader编译,路径不能直接写。
assets中的文件会经过webpack打包,重新编译,推荐该方式。而static中的文件,不会经过编译。项目在经过打包后,会生成dist文件夹,static中的文件只是复制一遍而已。简单来说,static中建议放一些外部第三方,自己的放到assets,别人的放到static中。
注意:如果把图片放在assets与static中,html页面可以使用;但在动态绑定中,assets路径的图片会加载失败,因为webpack使用的是commenJS规范,必须使用require才可以,具体代码如下:
html
<div id="hook">
<h3>演示钩子的组件</h3>
<p>直接使用路径</p>
<img src="../../assets/11.png" alt="图片加载失败" title="assets中的图片">
<img src="../../../static/11.png" alt="图片加载失败" title="static中的图片">
<br>
<p>动态绑定路径</p>
<img :src="assetsURL" alt="图片加载失败" title="assets中的图片">
<img :src="staticURL" alt="图片加载失败" title="static中的图片">
</div>
js
data (){
return {
assetsURL: require('../../assets/11.png'),
staticURL: '../../../static/11.png'
}
}
效果图
1.5 new Vue()过程的简述
new Vue()是实例化一个Vue对象
new Vew() 会在构造函数中执行_init(options),随后导入五大Mixin,进行实例化的初始化过程。
initMixin(Vue) // options初始化
stateMixin(Vue) // 状态(props、state、computed、watch)
eventsMixin(Vue) // 事件
lifecycleMixin(Vue) // 生命周期
renderMixin(Vue) // 页面渲染
initLifecycle:初始化生命周期
initEvents:初始化事件
initRender:渲染页面
callHook(vm,‘beforeCreate’) :beforeCreate钩子函数
initState:初始化状态 props data computed watch methods
callHook(vm,‘created’):created钩子函数
我们重点关注下 initState中的 initData,也就是老生常谈的数据双向绑定。
function initData (vm: Component) {
let data = vm.$options.data
data = vm._data = typeof data === 'function'
? getData(data, vm)
: data || {}
if (!isPlainObject(data)) {
data = {}
process.env.NODE_ENV !== 'production' && warn(
'data functions should return an object:\n' +
'https://vuejs.org/v2/guide/components.html#data-Must-Be-a-Function',
vm
)
}
// proxy data on instance
const keys = Object.keys(data)
const props = vm.$options.props
const methods = vm.$options.methods
let i = keys.length
while (i--) {
const key = keys[i]
if (process.env.NODE_ENV !== 'production') {
if (methods && hasOwn(methods, key)) {
warn(
`Method "${key}" has already been defined as a data property.`,
vm
)
}
}
if (props && hasOwn(props, key)) {
process.env.NODE_ENV !== 'production' && warn(
`The data property "${key}" is already declared as a prop. ` +
`Use prop default value instead.`,
vm
)
} else if (!isReserved(key)) {
proxy(vm, `_data`, key)
}
}
// observe data
observe(data, true /* asRootData */)
}
其中有两个重要关键字 proxy 和 observe。
前者的作用:
proxy将key做代理 简介调用
我们在vue中调用数据: this.demo = 123
但是在源码初始化的过程中,是这样的 this._data.demo = 123
proxy就是将key值做了代理,简化了调用,方便了我们。
后者的作用:
开始进行双向数据绑定 observe(data, true /* asRootData */)
observe做一个数据监听 订阅者 Object.defineProperty 在存取値可以添加依赖进行操作,在复制是通知订阅者进行依赖更新 。
这就是vue中的数据拦截
简化后的observe
export function observe (value) {
if (!isObject(value)) {
return
}
let ob = new Observer(value)
return ob
}
export class Observer {
constructor (value) {
this.value = value
this.dep = new Dep()
this.vmCount = 0
def(value, '__ob__', this)
this.walk(value)
}
walk (obj) {
const keys = Object.keys(obj)
for (let i = 0; i < keys.length; i++) {
defineReactive(obj, keys[i], obj[keys[i]])
}
}
}
export function defineReactive (obj, key, val) {
const dep = new Dep()
let childOb = observe(val)
Object.defineProperty(obj, key, {
enumerable: true,
configurable: true,
// 取值时给数据添加依赖
get: function reactiveGetter () {
const value = val
if (Dep.target) {
dep.depend()
if (childOb) {
childOb.dep.depend()
}
}
return value
},
// 赋值时通知数据依赖更新
set: function reactiveSetter (newVal) {
const value = val
if (newVal === value) {
return
}
val = newVal
childOb = observe(newVal)
dep.notify()
}
})
}
简单阐述下vue双向数据绑定的原理:
发布者-订阅者 + 数据劫持
在上述的代码中,重点关注 defineReactive函数,对vue对象中的每个属性进行了递归遍历的监听,利用 Object.defineProperty对每个属性进行监听,在取值的时候添加依赖进行依赖收集,在复制的时候进行通知订阅者进行依赖更新。
转发和重定向的区别和使用
页面的跳转:转发
疑问
能否在OneServlet中保存值到请求域中,在另一个TwoServlet中打印出来?
如果是不同的请求,不能取出来。如果是同一次请求是可以取出来的。
转发与重定向的作用
在Servlet中实现页面的跳转有两种方式:转发和重定向
什么是转发
概念
由服务器端进行的页面跳转
原理图