vue的基础结构
el
new Vue({
el: '#app',
data: {
company: {
name: '掘金',
address: '上海自由世纪广场'
}
}
})
vue中会把data中的数据填充到el指向的模板中,并把模板渲染到浏览器
render
new Vue({
data: {
company: {
name: '掘金',
address: '上海自由世纪广场'
}
},
render(h) {
return h('div', [
h('p', '公司名称:' + this.company.name),
h('p', '公司地址:' + this.company.address)
])
}
}).$mount('#app')
h函数的作用是创建虚拟dom,render是把h函数创建的虚拟dom返回,$mount方法的作用是把虚拟dom转化为真实dom,渲染到浏览器
vue的生命周期
- 初始化---初始化事件,生命周期相关成员,包括h函数
- beforeCreate
- 初始化注入---会把props,data,method等注入到vue的实例上
- created---可以访问到上面注入的成员
- 接下来是把模板编译成render函数---首先判断选项中是否设置了
el
选项,如果没有设置就调用$mount
方法,把el转换成template,接下来把模板变成render函数,接下里判断是否设置了模板,如果没有设置的话会把el的外层html作为模板,然后把template模板编译到渲染函数中,渲染函数就是用来生成虚拟dom的 - beforeMount---挂载之前,无法获取新元素的内容
- 挂载dom,把新的结构渲染到页面上
- mounted---可以访问新的dom
- 当调用
destroy()
方法的时候,首先会触发beforeDestory, - 然后执行清理的工作---解除绑定,销毁子组件和事件监听等
11.destoryed
如果我们使用单文件组件的时候,模板编译是在打包和构建的时候完成的,不在运行期间去编译模板
组件---可复用的vue实例
vue-router的原理实现
使用步骤
- 创建视图组件
- 使用
Vue.use(VueRouter)
注册路由插件,Vue.use()
用来注册插件,接收一个参数,参数是函数的话,会自动调用这个函数,是一个对象的话,会调用对象中的install
方法来注册插件 - 定义路由数组,路由规则
- 创建
router
对象const router = new VueRouter({ routes })
,创建的时候,需要把路由规则传递进来,然后导出 main.js
中导入,创建实例的时候需要把这个导入的路由对象注册上去,当做参数传递进vue
实例中,传入router
的作用是给vue
实例注入$route
和$router
两个属性
$route
和$router
$route
路由规则,存储的是路由的数据,包括参数,路由路径等
$router
是vue-router
的实例,就是路由对象,他(的原型上)提供了一些路由相关的方法,包括push
,replace
,go
等,路由模式等
关于路由的路径解释
- 嵌套路由中,父组件中一定会有
router-view
占位 - 路由的相对路径和绝对路径的区别就是相对路径(不带‘/’)
会拼接父级路由
,绝对路径(带‘/’)是配置的完整路由
routes: [
{
path: '/vue', //父级路径
component: Info,
children: [
{ path: 'home', component: Home }, //相对路径
{ path: '/about', component: About } //绝对路径
]
}
]
相对路径:地址栏最后的路径显示为localhost:8080/#/vue/home
绝对路径:地址栏最后的路径显示为localhost:8080/#/about
编程式导航
this.$router.push()
this.$router.replace()
this.$router.go()
类似这样的页面跳转的方法,就叫做编程式导航
hash和history模式的区别
表现形式区别 一个带#
一个没有
原理的区别
history.pushState()
是ie10以后才支持的
然后history.pushState()
和history.push()
的区别是当调用history.push()
路径发生变化,需要向服务器发送请求,而history.pushState()
不会发送请求,只会改变浏览器的地址,并且把这个地址记录到历史记录中去,从而实现客户端路由
history模式的使用
- history需要服务取得支持
- 单页面应用中只有一个页面
index.html
,服务端不存在http://xxxxxxx/login
这样的页面,正常访问单页应用不会有任何问题,但是当前浏览器地址是这个的时候,同时我们刷新浏览器的时候,会像服务器去请求login
这个页面,而服务器不存在这个页面,于是返回404
- 所以在服务端应该除了静态资源都返回单页应用的
index.html
vue-cli
自带的服务器已经处理好了这个问题,所以在本地开启的服务中,是没有这样的问题的
node服务器配置
如果在nodejs服务器中处理history模式的问题的时候我们需要导入connect-history-api-fallack
模块,把这个模块注册到node服务器中,如下
const path = require('path')
const history = require('connect-history-api-fallack') // 导入处理history模式的模块
const express = require('express')
const app = express()
app.use(history()) // 注册处理history模式的中间件
// 处理静态资源的中间件,网站根目录设为 ../web
app.use(express.static(path.join(__dirname, '../web')))
app.listen(3000, () => {
console.log('服务器开启了')
})
我们再尝试下再nginx服务其中配置处理history模式
nginx服务器的配置
- 从官网下载nginx的压缩包,解压,目录不能有中文
- 打开命令行,切换到nginx目录
- 启动nginx
start nginx 启动
、nginx -s reload 重启
、nginx -s stop 停止
- 把打包好的前端代码拷贝到nginx文件下的html文件夹下面,之后我们需要修改的文件在conf目录下的nginx.conf文件
// 找到http对象下的server下的location
location / {
root html;
index index.html index.htm;
try_files $uri $uri/ /index.html;
}
// try_files的意思是试着访问一下这个文件,$uri当前浏览器请求的路径所对应的文件,找到了就直接返回,找不到就继续往后找
// 找不到,再把这个请求的路径当做一个目录($uri/),再去寻找这个目录下的默认首页index.html或者index.htm,找到直接返回,找不到继续往后找
// 没找到,因为我们访问的是单页应用,前两次寻找没找到,意味着请求路径不存在,所以需要返回单页面应用的首页,也就是根目录文件夹下的index.html
VueRouter实现原理
hash模式
History模式
- 通过history.pushState()方法改变地址栏,并把当前地址记录到浏览器的访问历史中,仅仅是改变地址栏,并不会跳转路径
- 通过监听popstate事件,可以监听到浏览器历史操作的变化,popstate事件的处理函数中,可以记录改变后的地址,点击浏览器的前进后退按钮,或者调用history的back和forward方法的时候,这个事件才会被触发
- 根据当前的路由地址找到对应的组件,进行重新渲染
关于vue这里需要普及一个版本问题
// Runtime+complier
new Vue({
router,
components: { App },
template: '<App/>'
}).$mount('#app')
// Runtime-only版本
new Vue({
router,
render: h => h(App)
}).$mount('#app')
手写一个支持history模式的Vue-router
let _Vue = null
export default class VueRouter {
static install (Vue) {
// 判断是否已安装
if(VueRouter.install.installed) return
VueRouter.install.installed = true
// 把Vue构造函数记录到全局变量
_Vue = Vue
// 把创建Vue实例传入的router对象注入到Vue实例上,new Vue()那边
// _Vue.prototype.$router = this.options.router
_Vue.mixin({
beforeCreated() {
if(this.$options.router){
_Vue.prototype.$router = this.options.router // this.options 创建vue实例,初始化的时候传入的参数
// mixin中this指向的就是vue实例
this.$options.install.init()
}
}
})
}
constructor(options) {
this.options = options // 记录构造函数中传入的options
this.routeMap = {} // 存储 路由地址:对应组件的键值对
this.data = _Vue.observable({ // 使用vue提供的observable方法创建响应式对象,可以直接用在渲染函数和计算属性里面
current: '/' // 记录当前路由地址
})
}
init() {
this.createrouteMap()
this.initComponents(_Vue)
this.initEvent()
}
createrouteMap() {
// 路由树中处理成键值对的形式,存储到routeMap中
this.options.routes.forEach(route => {
this.routeMap[route.path] = route.component
})
}
initComponents (Vue) {
Vue.component('router-link', {
props: {
to: String
},
// template: '<a :href="to"><slot></slot></a>' // vue-cli 默认使用运行时版本的vue,没有编译器
render (h) {
return h('a', {
attrs: {
href: this.to
},
on:{
click: this.clickHandler
}
}, [this.$slots.default])
},
methods: {
clickHandler (e) {
history.pushState({}, '', this.to) // 改变浏览器的地址栏,把当前地址加入到历史记录中
this.$router.data.current = this.to // data是响应式的对象,值改变之后,会重新加载对应的组件,重新渲染
e.preventDefault() // 阻止默认行为 使浏览器不跳转不刷新
}
}
})
const self = this
Vue.component('router-view', {
render (h) { // h函数的作用就是创建虚拟dom
// 找到当前的路由地址 self.data.current
const component = self.routeMap[self.data.current]
return h(component) // h函数可以直接把一个组件转换成虚拟dom
}
})
}
initEvent() { // 处理浏览器后退前进
window.addEventListener('popstate', () => {
// 取出当前地址栏中的地址,我们要的仅仅是路径部分,第一个/后面的部分
this.data.current = window.location.pathname
})
}
}
常见问题FAQ
- 免费下载或者VIP会员专享资源能否直接商用?
- 本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
- 提示下载完但解压或打开不了?
- 找不到素材资源介绍文章里的示例图片?
- 模板不会安装或需要功能定制以及二次开发?
发表评论
还没有评论,快来抢沙发吧!