目录
1. 渲染函数
render(针对的是组件模板)
//组件模板:
let myA = {
template: `<div>123<div>`,
//渲染函数 参数createElement是一个函数 创建节点的函数
render(createElement) { createElement() }
}
plugin
插件通常用来为 Vue 添加全局功能。Vue.js 的插件应该暴露一个 install 方法。这个方法的第一个参数是 Vue 构造器,第二个参数是一个可选的选项对象。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="../js/vue.js"></script>
<script src="../js/vue-router.js"></script>
</head>
<body>
<div id="app">
{{msg}} {{msg | myFilter}}
</div>
<script>
// 声明插件对象
let myPlugin = {
//install方法在Vue.use(myPlugin)会运行
install(Vue, options) {
// console.log(1);
// 提供一些静态属性或者方法
Vue.isVue = () => { }
// 提供一些原型属性或者方法
Vue.prototype.$sayVue = () => { }
// 全局注册(组件/过滤器/指令/混入)
Vue.filter('myFilter', (data) => {
return data.toUpperCase()
})
}
};
// console.log(Vue.isVue);
// 使用插件,在new Vue之前使用
Vue.use(myPlugin);
// console.log(Vue.isVue);
// Object.prototype.say = () => { }
// let obj = new Object()
// obj.say();
let vm = new Vue({
el: '#app',
data: {
msg: 'hello'
},
methods: {}
})
// console.log(vm.$sayVue);
</script>
</body>
</html>
2. 路由机制
vue-router是vue的一个插件,用来提供路由功能。通过路由的改变可以动态加载组件,达到开发单页面程序的目的。
- 安装:
- 方式一 : CDN引入
<script src="https://cdn.bootcdn.net/ajax/libs/vue/3.2.0-beta.7/vue.cjs.js"></script> <script src="https://cdn.bootcdn.net/ajax/libs/vue-router/4.0.10/vue-router.cjs.js"></script>
- 方式二:本地引入
<script src='vue.js'></script> <script src='vue-router.js'></script>
- 方式三 : cnpm下载
cnpm install vue-router
- 使用:在html文件中使用时需要引入vueRouter(先引入vue.js,在引入vueRouter)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="../js/vue.js"></script>
<script src="../js/vue-router.js"></script>
</head>
<body>
<div id="app">
<!-- 4.路由使用 -->
<router-link to='/a'>组件1</router-link>
<router-link to='/b'>组件2</router-link>
<!-- 为组件加载提供容器或窗口 -->
<!-- 实现了组件之间的动态加载 -->
<router-view></router-view>
</div>
<script>
// 1.注册组件
let com1 = {
data() {
return {}
},
template: `
<div>
组件1
</div>
`
}
let com2 = {
data() {
return {}
},
template: `
<div>
组件2
</div>
`
}
// 2.定义路由
let router = new VueRouter({
routes: [
{
path: '/',
redirect: '/a' //重定向
},
{
path: '/a', //路径
component: com1, //路径对应的组件
name: 'com1', //路由命名
alias: '/A' //路由(path)别名
},
{
path: '/b',
component: com2,
name: 'com2'
}
]
})
let vm = new Vue({
el: '#app',
data: {},
methods: {},
// 3.路由注册
router: router
})
</script>
</body>
</html>
3. 动态路由匹配
需要把某种模式匹配到的所有路由,全部映射到同一个组件。
例如 : 有一个user组件,对于所有id不同的用户,都要使用这个组件来渲染,那么可以在vue-router的路由路径中使用动态路径参数来达到这个效果。
复用组件时,想对路由参数的变化作出响应的话,你可以简单地 watch $route 对象,或者使用组件内部的导航守卫
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="../js/vue.js"></script>
<script src="../js/vue-router.js"></script>
</head>
<body>
<div id="app">
<!-- 4.路由使用 -->
<router-link to='/user/1001'>组件1</router-link>
<router-link to='/b'>组件2</router-link>
<!-- 为组件加载提供容器或窗口 -->
<!-- 实现了组件之间的动态加载 -->
<router-view></router-view>
</div>
<script>
// 1.注册组件
let com1 = {
data() {
return {
id: null
}
},
template: `
<div>
组件1
{{id}}
</div>
`,
created() {
this.id = this.$route.params.id
// console.log(this.$route.params);
},
watch: {
// 使用监听器,来监听路由对象变化
$route(to, from) {
console.log('$route变化', to, from);
}
}
}
let com2 = {
data() {
return {}
},
template: `
<div>
组件2
</div>
`
}
// 2.定义路由
let router = new VueRouter({
routes: [
{
path: '/user/:id',
component: com1,
name: 'user',
alias: '/A'
},
{
path: '/b',
component: com2,
name: 'com2'
}
]
})
let vm = new Vue({
el: '#app',
data: {},
methods: {},
// 3.路由注册
router: router
})
</script>
</body>
</html>
4. 嵌套路由
实际生活中的应用界面,通常由多层嵌套的组件组合而成。同样地,URL 中各段动态路径也按某种结构对应嵌套的各层组件。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="../js/vue.js"></script>
<script src="../js/vue-router.js"></script>
<style>
header {
height: 50px;
background-color: rgba(153, 235, 137, 0.8);
}
main {
display: flex;
}
.left {
width: 150px;
border: 3px solid orange;
height: 700px;
margin: 10px 10px 0 0;
}
.right {
flex: 1;
/* width: calc(100%-150px); */
border: 3px solid blue;
height: 700px;
margin-top: 10px;
}
</style>
</head>
<body>
<div id="app">
<header>我是网站头部</header>
<main>
<div class="left">
<router-link to='/user'>用户管理</router-link><br>
<router-link to='/student'>学生管理</router-link><br>
<router-link to='/class'>班级管理</router-link>
</div>
<div class="right">
<!-- 为组件加载提供容器/窗口 -->
<!-- 实现了组件之间的动态加载 -->
<router-view></router-view>
</div>
</main>
</div>
<script>
// 1.注册组件
let com1 = {
data() {
return {}
},
template: `
<div>
用户管理
</div>
`
}
let com2 = {
data() {
return {}
},
template: `
<div>
学生管理
<div>
<router-link to='/student/grade'>成绩管理</router-link>
<router-link to='/student/register'>学籍管理</router-link>
</div>
<router-view></router-view>
</div>
`
}
let com3 = {
data() {
return {}
},
template: `
<div>
班级管理
</div>
`
}
let comGrade = {
data() {
return {}
},
template: `
<div>
成绩管理
</div>
`
}
let comRegister = {
data() {
return {}
},
template: `
<div>
学籍管理
</div>
`
}
// 2.定义路由
let router = new VueRouter({
routes: [
{
path: '/user',
component: com1
},
{
path: '/student',
component: com2,
children: [
{ path: 'grade', component: comGrade },
{ path: 'register', component: comRegister }
]
},
{
path: '/class',
component: com3
}
]
})
let vm = new Vue({
el: '#app',
data: {},
methods: {},
// 3.路由注册
router: router
})
</script>
</body>
</html>
5. 编程式导航
除了使用
<router-link>
创建 a 标签来定义导航链接,还可以借助 router 的实例方法,通过编写代码来实现。this.$router.push()跳转到指定路由,会向history栈添加一个新的记录,当用户点击浏览器回退按钮的时候,可以回到跳转前的url。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="../js/vue.js"></script>
<script src="../js/vue-router.js"></script>
<style>
header {
height: 50px;
background-color: rgba(153, 235, 137, 0.8);
}
main {
display: flex;
}
.left {
width: 150px;
border: 3px solid orange;
height: 700px;
margin: 10px 10px 0 0;
}
.right {
flex: 1;
/* width: calc(100%-150px); */
border: 3px solid blue;
height: 700px;
margin-top: 10px;
}
</style>
</head>
<body>
<div id="app">
<header>我是网站头部</header>
<main>
<div class="left">
<router-link to='/user'>用户管理</router-link><br>
<router-link to='/student'>学生管理</router-link><br>
<router-link to='/class'>班级管理</router-link>
</div>
<div class="right">
<!-- 为组件加载提供容器/窗口 -->
<!-- 实现了组件之间的动态加载 -->
<router-view></router-view>
</div>
</main>
</div>
<script>
// 1.注册组件
let com1 = {
data() {
return {}
},
template: `
<div>
用户管理
</div>
`
}
let com2 = {
data() {
return {}
},
template: `
<div>
学生管理
<div>
<button @click='clickHandler'>成绩管理</button>
<button @click='clickHandler'>学籍管理</button>
<button @click='$router.go(-1)'>返回</button>
</div>
<router-view></router-view>
</div>
`,
methods: {
clickHandler(e) {
if (e.target.innerText == '成绩管理') {
// 使用this.$router.push完成编程式导航
// this.$router.push({ path: '/student/grade' })
if (this.$route.fullPath != '/student/grade') {
// this.$router.push({ name: 'grade' })
// this.$router.push({
// name: 'grade',
// params: {
// id: 1001,
// name: 'zs'
// }
// })
this.$router.replace('/student/grade')
}
} else {
// this.$router.push({ path: '/student/register' })
if (this.$route.fullPath != '/student/register') {
// this.$router.push({ name: 'register' })
// 使用path跳转,并且使用query传递参数
this.$router.push({
path: '/student/register',
query: {
id: 1002,
name: 'ls'
}
})
}
}
}
}
}
let com3 = {
data() {
return {}
},
template: `
<div>
班级管理
</div>
`
}
let comGrade = {
data() {
return {}
},
template: `
<div>
成绩管理
</div>
`,
created() {
console.log('params', this.$route.params);
}
}
let comRegister = {
data() {
return {}
},
template: `
<div>
学籍管理
</div>
`,
created() {
console.log('query', this.$route.query);
}
}
// 2.定义路由
let router = new VueRouter({
// 修改路由模式
// mode: 'history',
routes: [
{
path: '/user',
component: com1
},
{
path: '/student',
component: com2,
children: [
{ path: 'grade', component: comGrade, name: 'grade' },
{ path: 'register', component: comRegister, name: 'register' }
]
},
{
path: '/class',
component: com3
}
]
})
let vm = new Vue({
el: '#app',
data: {},
methods: {},
// 3.路由注册
router: router
})
</script>
</body>
</html>
6. 路由组件传参
路由传递是指,从A页面跳转到B页面时,将A页面中的变量传递给B页面使用,传递参数的方式有两种 :
path-query 传参
使用path与query结合的方式传递参数时,参数会被拼接在浏览器地址栏中,并且刷新页面后数据也不会丢失。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="../js/vue.js"></script>
<script src="../js/vue-router.js"></script>
</head>
<body>
<div id="app">
<router-link to="/user">user</router-link>
<router-link to="/manager">manager</router-link>
<router-view></router-view>
</div>
<script>
let user = {
template: `
<div @click="userHandler">普通用户,点击此处可跳转至管理员页面</div>
`,
data() {
return {
list: "hello",
obj: {
name: 'tom',
age: 3
}
}
},
methods: {
userHandler() {
// 跳转
this.$router.push({
path: '/manager',
query: {
list: this.list,
obj: JSON.stringify(this.obj)
}
})
}
},
}
let manager = {
template: `
<div>管理员 {{$route.query.list}} {{$route.query.obj}}</div>
`
}
let router = new VueRouter({
routes: [{
path: '/user',
component: user
}, {
path: '/manager',
component: manager
}]
})
new Vue({
el: "#app",
router
})
</script>
</body>
</html>
name-params 传参
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="../js/vue.js"></script>
<script src="../js/vue-router.js"></script>
</head>
<body>
<div id="app">
<router-link to="/user">user</router-link>
<router-link to="/manager">manager</router-link>
<router-view></router-view>
</div>
<script>
let user = {
template: `
<div @click="userHandler">普通用户,点击此处可跳转至管理员页面</div>
`,
data() {
return {
list: "hello",
obj: {
name: 'tom',
age: 3
}
}
},
methods: {
userHandler() {
// 跳转
this.$router.push({
name: 'manager',
params: {
list: this.list,
obj: JSON.stringify(this.obj)
}
})
}
},
}
let manager = {
template: `
<div>管理员 {{$route.params.list}} {{$route.params.obj}}</div>
`
}
let router = new VueRouter({
routes: [{
path: '/user',
component: user,
name: 'user'
}, {
path: '/manager',
component: manager,
name: 'manager'
}]
})
new Vue({
el: "#app",
router
})
</script>
</body>
</html>
7. 路由模式
hash 模式
hash模式的工作原理是hashchange事件,可以在window监听hash的变化。我们在url后面随便添加一个#xx触发这个事件。
window.onhashchange = function(event){ console.log(event);
// 打印出一HashChangeEvent事件对象,在该对象内有newURL和oldURL
// location.hash中也有相关的信息
// 假设hash值是个颜色值,通过location.hash来获取到对应的hash值,然后设置页面中的某个元素的背景颜色来改变页面 }
history模式
把window.history对象打印出来可以看到里边提供的方法和记录长度 history对象内有back(),forword(),go()等方法 前进,后退,跳转操作方法:
history.go(-3);//后退3次
history.go(2);//前进2次
history.go(0);//刷新当前页面
history.back(); //后退
history.forward(); //前进
vue-router 使用的模式
vue-router 默认 hash 模式 —— 使用 URL 的 hash 来模拟一个完整的 URL,于是当 URL 改变时,页面不会重新加载。如果不想要很丑的 hash,可以用路由的 history 模式,这种模式充分利用 history.pushState API 来完成 URL 跳转而无须重新加载页面。不过这种模式要玩好,还需要后台配置支持。
hash路由和history路由的区别:
1.hash路由在地址栏URL上有#,而history路由没有会好看一点
2.进行回车刷新操作,hash路由会加载到地址栏对应的页面,而history路由一般就404报错了(刷新是网络请求,没有后端准备时会报错)。
3.hash路由支持低版本的浏览器,而history路由是HTML5新增的API。
4.hash的特点在于它虽然出现在了URL中,但是不包括在http请求中,所以对于后端是没有一点影响的,所以改变hash不会重新加载页面,所以这也是单页面应用的必备。
5.history运用了浏览器的历史记录栈,之前有back,forward,go方法,之后在HTML5中新增了pushState()和replaceState()方法(需要特定浏览器的支持),它们提供了对历史记录进行修改的功能,不过在进行修改时,虽然改变了当前的URL,但是浏览器不会马上向后端发送请求。
8. 导航守卫 -——路由的改变会触发导航守卫
组件内部守卫
//定义组件内部守卫
// 5.1组件内部前置守卫
beforeRouteEnter(to, from, next) {
console.log('路由进入之前', to, from);
// 手动调用next()方法,确保路由跳转成功
next()
},
// 5.2组件内部更新守卫
beforeRouteUpdate(to, from, next) {
console.log('路由更新之前', to, from);
this.id = to.params.id;
next()
},
// 5.3组件内部后置守卫
beforeRouteLeave(to, from, next) {
console.log('路由离开之前', to, from);
}
全局守卫
// 5.配置全局守卫
// 5.1配置全局前置守卫
router.beforeEach((to, from, next) => {
console.log('全局前置守卫', to, from);
next()
})
// 5.2配置全局后置守卫
router.afterEach((to, from, next) => {
console.log('全局后置守卫', to, from);
})
路由独享守卫
let router = new VueRouter({
routes: [
{
path: '/user/:id',
component: com1,
name: 'user',
// 5.1配置路由独享守卫
beforeEnter(to, from, next) {
console.log('路由进入之前', to, from);
next()
}
},
{
path: '/b',
component: com2,
name: 'com2'
}
]
})