Vue组件
组件 (Component) 是 Vue.js 最强大的功能之一。
组件可以扩展 HTML 元素,封装可重用的代码。是可复用的Vue实例。
组件的注册
// html 代码
<div id="app">
<my-component></my-component>
</div>
// js 代码
Vue.component(‘my-component‘, {
template: ‘<div>A component!</div>‘
})
var app = new Vue({
el: ‘#app‘,
data: {
}
});
全局注册
// html 代码
<div id="app">
<my-component></my-component>
</div>
// js 代码
// 组件中的data必须是个函数
var Child = {
template: ‘<div>A component!</div>‘,
data: function() {
return {
name: "gao",
}
}};
new Vue({
// ...
components: {
// <my-component> 将只在父组件模板中可用
‘my-component‘: Child
}
})
局部注册
// js 代码
Vue.component(‘child‘, {
template: `<div><button @click="on_click()">{{msg}}</button></div>`,
data: function () {
return {
msg: "点我",
}
},
methods: {
on_click(){
alert(123)
}
}
});
new Vue({
el: "#app",
})
组件中的data methods
<script>
var my_component = {
template: `<div><h1>{{msg}}</h1></div>`,
data(){
return{
msg: "这是子组件"
}
}
};
var global_component = {
template: `<div>
<h1>{{msg}}</h1>
<button @click="on_click">点我</button>
<my_component></my_component>
</div>`,
data(){
return {
msg: "全局组件"
}
},
methods: {
on_click() {
alert("123")
}
},
components:{
my_component:my_component,
}
};
const app = new Vue({
el: "#app",
data: {
},
components: {
global_component: global_component,
// my_component: my_component,
}
});
</script>
子组件的注册
组件之间的通信
我们的组件在任何地方用的时候都要是一个样子么~
可不可以我们给组件传个参数~让组件在不同的地方表现不同的状态~
我们之前说过博客评论@某某某,点击用户名可以跳转到该用户站点。
这样一个小功能,我们每次@的时候都要写,我们可以封装成组件,传值即可~~
// html 代码
<div id="app">
<child username="gaoxin"></child>
</div>
// js 代码
Vue.component(‘child‘, {
template: `<a :href="‘/user/‘+ username">{{username}}</a>`,
props: ["username"],
});
var app = new Vue({
el: "#app",
data:{
name: "@gaoxin"
}
});
父子通信
app.$on(event, callback) 监听当前实例上的自定义事件,事件由$emit触发,回调函数接收事件触发器额外参数。
app.$emit(event, [args....]) 触发当前实例上的事件,额外参数传给监听器的callback回调函数。
// html 代码
<div id="app">
<parent></parent>
</div>
// js 代码
Vue.component(‘parent‘,{
template: `
<div>
<child @show_balance="show"></child>
<p v-if="active">您的余额998</p>
</div>
`,
data: function () {
return {
active: false,
}
},
methods: {
show: function(data){
this.active=true;
console.log(data)
}
}
});
Vue.component(‘child‘, {
template: `<div><button @click="on_click()">{{msg}}</button></div>`,
data: function () {
return {
msg: "显示余额",
}
},
methods: {
on_click(){
// alert(123)
this.$emit(‘show_balance‘, {q:1,b:2})
}
}
});
子父通信
平行组件之间的通信,喊话需要一个中间调度器,在组件加载完成之后去监听调度器事件,回调函数接收数据。
// html 代码
<div id="app">
<whh></whh>
<shh></shh>
</div>
// js 代码
var Event = new Vue()
Vue.component(‘whh‘,{
template: `
<div>
我说: <input @keyup="on_change" v-model="i_said">
</div>
`,
data: function () {
return {
i_said: ‘‘,
}
},
methods: {
on_change: function () {
Event.$emit("whh_said_something", this.i_said)
}
}
});
Vue.component(‘shh‘, {
template: `
<div>
花花说:{{whh_said}}
</div>
`,
data: function () {
return {
whh_said: ‘‘,
}
},
mounted: function () {
var me = this
Event.$on(‘whh_said_something‘, function (data) {
me.whh_said = data
})
}
});
非父子组件通信
混合Mixins
重复功能和数据的储存器,可以覆盖Mixins的内容。
// 点击显示和隐藏 提示框的显示和隐藏
// html 代码
<div id="app">
<PopUp></PopUp>
<ToolTip></ToolTip>
</div>
// js 代码
var base = {
data: function () {
return {
visible: false,
}
},
methods: {
show: function () {
this.visible = true
},
hide: function () {
this.visible = false
}
}
}
Vue.component(‘popup‘, {
template:`
<div>
<button @click="show">PopUp show</button>
<button @click="hide">PopUp hide</button>
<div v-if="visible"><p>hello everybody</p></div>
</div>
`,
mixins: [base],
data: function () {
return {
visible: true,
}
}
});
Vue.component(‘tooltip‘, {
template: `
<div>
<div @mouseenter="show" @mouseleave="hide">ToolTip</div>
<div v-if="visible"><p>ToolTip</p></div>
</div>
`,
mixins: [base]
});
new Vue({
el: "#app",
})
Mixins
插槽 Slot
插槽是一套内容分发的API,在组件中,<slot>作为内容承载分发的出口
// html 代码
<div id="app">
<panel>
<div slot="title"> HELLO</div>
<div slot="content">hello</div>
</panel>
<panel></panel>
<panel></panel>
</div>
<template id="panel-tpl">
<div class="panel">
<div class="title">
<slot name="title"></slot>
</div>
<div class="content">
<slot name="content"></slot>
</div>
<!--<div class="content">Failure is probably the fortification in your pole. It is like a peek your wallet as the thief, when you are thinking how to spend several hard-won lepta,</div>-->
<div class="footer">
<slot name="footer">更多信息</slot>
</div>
</div>
</template>
// js 代码
Vue.component(‘panel‘, {
template: ‘#panel-tpl‘,
});
new Vue({
el: "#app",
})
Slot
vue-router是什么~~
vue-router是Vue的路由系统,定位资源的,我们可以不进行整页刷新去切换页面内容。
vue-router的安装和基本配置
vue-router.js 可以下载 也可以用cdn,基本配置信息看如下代码~~~
// html 代码
<div id="app">
<div>
<router-link to="/">首页</router-link>
<router-link to="/about">关于我们</router-link>
</div>
<div>
<router-view></router-view>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script src="https://unpkg.com/vue-router/dist/vue-router.js"></script>
<script src="../js/router_demo.js"></script>
// js 代码
var routes = [
{
path: "/",
component: {
template: `<div><h1>首页</h1></div>`
}
},
{
path: "/about",
component: {
template: `<div><h1>关于我们</h1></div>`
}
}
]
var router = new VueRouter({
routes: routes,
// 路由去掉#
// mode: ‘history‘,
});
var app = new Vue({
el: ‘#app‘,
router: router,
});
vue-router demo
路由的一些方法
路由传参以及获取参数~~
// html 代码
<div id="app">
<div>
<router-link to="/">首页</router-link>
<router-link to="/about">关于我们</router-link>
<router-link to="/user/琴女?age=20">琴女</router-link>
<router-link to="/user/提莫">提莫</router-link>
</div>
<div>
<router-view></router-view>
</div>
</div>
// js 代码
var routes = [
{
path: "/",
component: {
template: `<div><h1>首页</h1></div>`
}
},
{
path: "/about",
component: {
template: `<div><h1>关于我们</h1></div>`
}
},
{
path: "/user/:name",
component: {
template: `<div>
<h1>我是:{{$route.params.name}}</h1>
<h1>我年龄是:{{$route.query.age}}</h1>
</div>`,
}
}
]
var router = new VueRouter({
routes: routes,
});
var app = new Vue({
el: ‘#app‘,
router: router,
});
传参以及获取参数
命名路由~ 注意router-link里to一定要v-bind~~
// html代码
<div id="app">
<div>
<router-link to="/">首页</router-link>
<router-link :to="{name: ‘about‘}">关于我们</router-link>
<router-link to="/user/gaoxin?age=19">gaoxin</router-link>
</div>
<div>
<router-view></router-view>
</div>
</div>
// js代码
let routes = [
{
path: ‘/‘,
component: {
template: `<h1>这是主页</h1>`
}
},
{
path: "/about",
name: "about",
component: {
template: `<h1>关于我们</h1>`
}
},
{
path: "/user/:name",
component: {
template: `<div>
<h1>我是{{$route.params.name}}</h1>
<h2>我的年龄是{{$route.query.age}}</h2>
</div>
`
}
}
];
let router = new VueRouter({
routes: routes,
mode: "history"
});
const app = new Vue({
el: "#app",
router: router,
mounted(){
console.log(this.$route)
console.log(this.$router)
}
})
命名路由
子路由~~ 以展示详细为例~~
// 添加子路由变化的只有父级路由
// 基于上面的例子增加
// js 代码
{
path: "/user/:name",
component: {
template: `<div>
<h1>我是:{{$route.params.name}}</h1>
<h1>我年龄是:{{$route.query.age}}</h1>
<router-link to="more" append>更多信息</router-link>
<router-view></router-view>
</div>`,
},
children: [
{
path: "more",
component: {
template: `<div>
{{$route.params.name}}的详细信息
</div>`,
}
}
]
},
子路由
手动访问路由,以及传参~~
// 基于上面例子追加
// html 代码
<div id="app">
<div>
<router-link to="/">首页</router-link>
<router-link to="/about">关于我们</router-link>
<router-link to="/user/琴女?age=20">琴女</router-link>
<router-link to="/user/提莫">提莫</router-link>
// 添加一个button按钮
<button @click="on_click">旅游</button>
</div>
<div>
<router-view></router-view>
</div>
</div>
// js 代码
// 注意路由name的使用 这是在原例子追加
var app = new Vue({
el: ‘#app‘,
router: router,
methods: {
on_click: function () {
setTimeout(function () {
this.$router.push(‘/about‘)
setTimeout(function () {
this.$router.push({name: "user", params:{name: "琴女"},query:{age: 20}})
}, 2000)
}, 2000)
}
}
});
手动路由~以及传参
命名路由视图 router-view
当我们只有一个<router-view></router-view>的时候~所有内容都展示在这一个面板里面~
如果是content 和 footer 就需要同时显示并且不同区域~这就需要对视图进行命名~
// html 代码
<div id="app">
<div>
<router-link to="/">首页</router-link>
</div>
<div>
<router-view name="content" class="content-view"></router-view>
<router-view name="footer" class="footer-view"></router-view>
</div>
</div>
// js 中的主要代码
var routes = [
{
path: "/",
components: {
content: {
template: `<div><h1>首页</h1></div>`,
},
footer: {
template: `<div><h1>关于我们</h1></div>`,
}
}
},
]
命名路由视图
错误路由的重定向~~
let routes = [
{
path: "**",
redirect: "/"
}
]
redirect
$route以及$router的区别~~
-- $route为当前router调转对象,里面可以获取name, path, query, params等~
-- $router为VueRouter实例,有$router.push方法等~~
路由的钩子
路由的生命周期就是从一个路由跳转到另一路由整个过程,下面介绍两个钩子~
router.beforeEach() router.afterEach() 详情请看代码~~
// html 代码
<div id="app">
<router-link to="/">首页</router-link>
<router-link to="/login">登录</router-link>
<router-link to="/user">用户管理</router-link>
<div>
<router-view></router-view>
</div>
</div>
// js 代码
var routes = [
{
path: "/",
component: {
template: "<h1>首页</h1>"
}
},
{
path: "/login",
component: {
template: "<h1>登录</h1>"
}
},
{
path: "/user",
component: {
template: "<h1>用户管理</h1>"
}
}
];
var router = new VueRouter({
routes: routes
});
router.beforeEach(function (to,from,next) {
// console.log(to)
// console.log(from)
// console.log(next)
// next(false)
if(to.path=="/user"){
next("/login")
}
else {
next();
}
});
router.afterEach(function (to, from) {
console.log(to)
console.log(from)
});
var app = new Vue({
el: ‘#app‘,
router: router
});
路由钩子
next:function 一定要调用这个方法来resolve这个钩子函数。
执行效果依赖next方法的调用参数
next() 什么都不做继续执行到调转的路由
next(false) 中断当前导航 没有跳转 也没有反应
next("/") 参数是路径 调转到该路径
next(error) 如果next参数是一个Error实例 导航终止该错误
会传递给router.onError()注册过的回调中
next 参数详解
上面的例子~~如果/user下面还有子路由的情况下会怎么样呢~????
// 匹配子路由 改一下匹配方法就可以~
// js 改动代码
router.beforeEach(function (to,from,next) {
// console.log(to)
// console.log(from)
// console.log(next)
// next(false)
if(to.matched.some(function (item) {
return item.path == "/post"
})){
next("/login")
}
else {
next();
}
});
// 元数据配置 改动代码
// html 部分
{
path: "/user",
meta: {
required_login: true,
},
component: {
template: `
<div>
<h1>用户管理</h1>
<router-link to="vip" append>vip</router-link>
<router-view></router-view>
</div>
`
},
children: [{
path: "vip",
meta: {
required_login: true,
},
component: {
template: ‘<h1>VIP</h1>‘
}
}]
}
// js 部分
router.beforeEach(function (to,from,next) {
// console.log(to)
// console.log(from)
// console.log(next)
// next(false)
if(to.meta.required_login){
next("/login")
}
else {
next();
}
});
匹配子路由以及元数据配置