组件使用的基本步骤:(可直接看2.4 组件注册写法简化)
创建组件构造器
注册组件
<html>
<head>
<meta charset="utf-8">
<title>title>
<script src="../js/vue.js">script>
head>
<body>
<div id="app">
{
{message}}
<my-con>my-con>
div>
<script>
//1、创建组件构造器
let cpnContruction = Vue.extend({
template:'我是标题
'
});
//2、注册组件
Vue.component('my-con',cpnContruction);
let vue = new Vue({
el:'#app',
data:{
message:'haooo'
},
methods:{
},
});
script>
body>
html>
全局组件:可以在多个vue实例中使用。
<script>
//1、创建组件构造器
let cpnContruction = Vue.extend({
template:'我是标题
'
});
//2、注册全局组件
Vue.component('my-con',cpnContruction);
let vue = new Vue({
el:'#app',
data:{
message:'haooo'
},
methods:{
},
});
script>
局部组件
<script>
//1、创建组件构造器
let cpnContruction = Vue.extend({
template:'我是标题
'
});
//2、注册全局组件
// Vue.component('my-con',cpnContruction);
let vue = new Vue({
el:'#app',
data:{
message:'haooo'
},
//2、注册局部组件
components:{
mycon:cpnContruction
},
methods:{
},
});
script>
let cpnc2 = Vue.extend({
template:'<div><h2>我是标题2h2><cpn1>cpn1>div>',
//组件中注册组件
components:{
cpn1:cpnc1
}
});
<html>
<head>
<meta charset="utf-8">
<title>title>
<script src="../js/vue.js">script>
head>
<body>
<div id="app">
{
{message}}
<cpn2>cpn2>
div>
<script>
//1、创建组件构造器
let cpnc1 = Vue.extend({
template:'我是标题1
'
});
let cpnc2 = Vue.extend({
template:'我是标题2
',
//组件中注册组件
components:{
cpn1:cpnc1
}
});
let vue = new Vue({
el:'#app',
data:{
message:'haooo'
},
//注册局部组件
components:{
cpn2:cpnc2
},
methods:{
},
});
script>
body>
html>
<html>
<head>
<meta charset="utf-8">
<title>title>
<script src="../js/vue.js">script>
head>
<body>
<div id="app">
<cpn1>cpn1>
<cpn2>cpn2>
div>
body>
<script>
// 全局注册
Vue.component('cpn1',{
template:'1111111111'
});
var vue = new Vue({
el:'#app',
//局部注册
components:{
cpn2:{
template:'2222222',
},
},
});
script>
html>
方式一:使用script
标签(不常用)
<html>
<head>
<meta charset="utf-8">
<title>title>
<script src="../js/vue.js">script>
head>
<body>
<div id="app">
<cpn1>cpn1>
div>
body>
<script type="text/x-template" id="component">
<div>
<h2>1111111</h2>
</div>
script>
<script>
let vue = new Vue({
el:'#app',
components:{
cpn1:{
template:'#component'
},
}
});
script>
html>
方式二:使用tempalte
标签
<html>
<head>
<meta charset="utf-8">
<title>title>
<script src="../js/vue.js">script>
head>
<body>
<div id="app">
<cpn1>cpn1>
div>
body>
<template id="component">
<div>
<h2>2222222222h2>
div>
template>
<script>
let vue = new Vue({
el: '#app',
components: {
cpn1: {
template: '#component'
},
}
});
script>
html>
组件内部不可以访问Vue实例中的data,组件有自己的数据data,也有methods等属性。
data:function(){
return{
msg:'组件的数据'
}
},
<html>
<head>
<meta charset="utf-8">
<title>title>
<script src="../js/vue.js">script>
head>
<body>
<div id="app">
<cpn1>cpn1>
div>
body>
<template id="component">
<div>
<h2>222222h2>
<h3>{
{msg}}h3>
div>
template>
<script>
let vue = new Vue({
el:'#app',
components:{
cpn1:{
template:'#component',
data:function(){
return{
msg:'组件的数据'
}
},
},
}
});
script>
html>
(1)父组件的data
el:'#app',
data:{
movies:['海贼王','蜡笔小新','小猪佩奇','海尔兄弟'],
msg:'vue实例的数据传递给组件'
},
(2)子组件使用props定义子组件中需要的属性。props:['cmovies','cmsg']
//局部组件
components:{
cpn1:{
template:'#component',
props:['cmovies','cmsg'],
data:function(){
return{
}
},
},
}
(3)在组件(template)中使用props中的属性。
<template id="component">
<div>
<h2>{
{cmsg}}h2>
<ul>
<li v-for="(item) in cmovies">{
{item}}li>
ul>
div>
template>
(4)在使用组件时向组件props中的属性传递数据
<div id="app">
<cpn1 v-bind:cmovies="movies" :cmsg="msg">cpn1>
div>
<html>
<head>
<meta charset="utf-8">
<title>title>
<script src="../js/vue.js">script>
head>
<body>
<div id="app">
<cpn1 v-bind:cmovies="movies" :cmsg="msg">cpn1>
div>
body>
<template id="component">
<div>
<h2>{
{cmsg}}h2>
<ul>
<li v-for="(item) in cmovies">{
{item}}li>
ul>
div>
template>
<script>
let vue = new Vue({
el:'#app',
data:{
movies:['海贼王','蜡笔小新','小猪佩奇','海尔兄弟'],
msg:'vue实例的数据传递给组件'
},
//局部组件
components:{
cpn1:{
template:'#component',
props:['cmovies','cmsg'],
data:function(){
return{
}
},
},
}
});
script>
html>
//1、数组
props:['cmovies','cmsg'],
//2、对象
props:{
//2.1、类型限制
// cmovies:Array,
// cmsg:String,
//2.2、提供默认值
cmsg:{
type:String,
default:'默认值',
required:true,
},
//类型是一个数组或者对象时,默认值必须是一个函数
cmovies:{
type:Array,
default:function(){
return ['111','222']
},
},
},
props:{
//1、基础的类型检查(null:匹配任何类型)
propA:Number,
//2、多个可能的类型
propB:[String,Number],
//3、必填的字符串
propC:{
type:String,
required:true,
},
//4、带有默认值的数字
propD:{
type:Number,
default:100,
},
//5、带有默认值的对象
propE:{
type:Object,
default:function(){
return {
message:'helle'}
}
},
//6、自定义验证函数
propF:{
validator:function(value){
//这个值必须匹配下列字符串中的一个
return ['success','warning'].indexOf(value) !== -1
}
}
}
如果props中的属性是驼峰命名cMovies
,在传递数据的时候应该写成:c-movies="movies"
<html>
<head>
<meta charset="utf-8">
<title>title>
<script src="../js/vue.js">script>
head>
<body>
<div id="app">
<cpn1 :c-msg="msg" :c-movies="movies">cpn1>
div>
body>
<template id="component">
<div>
<h2>{
{cMsg}}h2>
<ul>
<li v-for="(item) in cMovies">{
{item}}li>
ul>
div>
template>
<script>
let vue = new Vue({
el:'#app',
data:{
movies:['海贼王','蜡笔小新','小猪佩奇','海尔兄弟'],
msg:'vue实例的数据传递给组件'
},
//局部组件
components:{
cpn1:{
template:'#component',
//1、数组
props:['cMovies','cMsg'],
data:function(){
return{
}
},
},
}
});
script>
html>
(1)子组件发射自定义事件
methods:{
btnClick:function(item){
console.log("子组件发射:" + item);
//1、子组件发射事件
this.$emit("item-click",item);
},
}
(2)子组件绑定点击事件
<template id="component">
<div>
<button v-for="item in categories" @click="btnClick(item)">{
{item}} button>
div>
template>
(3)父组件接收事件
methods:{
//3、 父组件接收事件
cnpClick:function(item){
console.log("父组件接收:" + item);
}
},
(4)组件使用时绑定事件
<cpn1 v-on:item-click="cnpClick">cpn1>
<html>
<head>
<meta charset="utf-8">
<title>title>
<script src="../js/vue.js">script>
head>
<body>
<div id="app">
<cpn1 v-on:item-click="cnpClick">cpn1>
div>
body>
<template id="component">
<div>
<button v-for="item in categories" @click="btnClick(item)">{
{item}}button>
div>
template>
<script>
let vue = new Vue({
el:'#app',
//局部组件
components:{
cpn1:{
template:'#component',
data:function(){
return{
categories:['海贼王','蜡笔小新','小猪佩奇','海尔兄弟']
}
},
methods:{
btnClick:function(item){
console.log("子组件发射:" + item);
//1、子组件发射事件
this.$emit("item-click",item);
},
}
},
},
methods:{
//3、 父组件接收事件
cnpClick:function(item){
console.log("父组件接收:" + item);
}
}
});
script>
html>
$children:结果是一个数组,通过遍历数组来获取子组件。
methods:{
getSubCpn:function(){
// 访问子组件的属性和方法
console.log(this.$children);
for (let var1 of this.$children) {
//访问子组件的属性
console.log(var1.subMsg);
//访问子组件的方法
var1.subMethod();
}
}
},
<html>
<head>
<meta charset="utf-8">
<title>title>
<script src="../js/vue.js">script>
head>
<body>
<div id="app">
<cpn>cpn>
<button @click="getSubCpn">通过$children访问子组件button>
div>
body>
<template id="component">
<div>
<h2>子组件h2>
div>
template>
<script>
let vue = new Vue({
el:'#app',
methods:{
getSubCpn:function(){
// 访问子组件的属性和方法
console.log(this.$children);
for (let var1 of this.$children) {
//访问子组件的属性
console.log(var1.subMsg);
//访问子组件的方法
var1.subMethod();
}
}
},
components:{
cpn:{
template:'#component',
data:function(){
return {
subMsg:'子组件属性'
}
},
methods:{
subMethod:function(){
console.log("子组件的方法");
}
}
}
}
});
script>
html>
$refs:获取的是一个对象,需要在使用组件时添加属性:ref=“cpn1”
<div id="app">
<cpn ref="cpn1">cpn>
<cpn ref="cpn2">cpn>
<button @click="getSubCpn">通过$children访问子组件button>
div>
methods:{
getSubCpn:function(){
//2、$refs:获取的是一个对象,需要在使用组件时添加属性:ref="cpn1"
console.log(this.$refs.cpn2.subMsg);
}
},
<html>
<head>
<meta charset="utf-8">
<title>title>
<script src="../js/vue.js">script>
head>
<body>
<div id="app">
<cpn ref="cpn1">cpn>
<cpn ref="cpn2">cpn>
<button @click="getSubCpn">通过$children访问子组件button>
div>
body>
<template id="component">
<div>
<h2>子组件h2>
div>
template>
<script>
let vue = new Vue({
el:'#app',
methods:{
getSubCpn:function(){
// // 1、$children:访问子组件的属性和方法
// console.log(this.$children);
// for (let var1 of this.$children) {
// //访问子组件的属性
// console.log(var1.subMsg);
// //访问子组件的方法
// var1.subMethod();
// }
//2、$refs:获取的是一个对象,需要在使用组件时添加属性:ref="cpn1"
console.log(this.$refs.cpn2.subMsg);
}
},
components:{
cpn:{
template:'#component',
data:function(){
return {
subMsg:'子组件属性'
}
},
methods:{
subMethod:function(){
console.log("子组件的方法");
}
}
}
}
});
script>
html>
子组件访问父组件。
components:{
cpn:{
template:'#component',
methods:{
btnClick:function(){
//访问父组件的数据
console.log(this.$parent.message);
}
}
}
}
<html>
<head>
<meta charset="utf-8">
<title>title>
<script src="../js/vue.js">script>
head>
<body>
<div id="app">
<cpn>cpn>
div>
body>
<template id="component">
<button @click="btnClick">访问父组件的数据button>
template>
<script>
let vue = new Vue({
el:'#app',
data:{
message:'父组件的数据'
},
components:{
cpn:{
template:'#component',
methods:{
btnClick:function(){
//访问父组件的数据
console.log(this.$parent.message);
}
}
}
}
});
script>
html>
子组件访问根组件(Vue实例)。
<html>
<head>
<meta charset="utf-8">
<title>title>
<script src="../js/vue.js">script>
head>
<body>
<div id="app">
<cpn>cpn>
div>
body>
<template id="component">
<cpn1>cpn1>
template>
<template id="component1">
<button @click="btnClick">访问根组件的信息button>
template>
<script>
let vue = new Vue({
el:'#app',
data:{
message:'根组件信息'
},
components:{
cpn:{
template:'#component',
components:{
cpn1:{
template:'#component1',
methods:{
btnClick:function(){
console.log(this.$root);
}
}
}
}
}
}
});
script>
html>
组件的插槽是为了让封装的组件更有扩展性。
插槽的基本使用:
1、在模板中使用slot标签,可设置name属性,在使用插槽时用v-slot:×××
来标识向哪个插槽中添加内容。
2、可以在slot中添加标签提供默认值
3、在使用组件标签时,在组件标签中添加标签,替换或者添加插槽中的内容。非默认插槽必须
具名插槽slot1
(1)v-slot:×××
必须使用在template
上。特殊情况
(2)具名插槽的缩写:#插槽名
<html>
<head>
<meta charset="utf-8">
<title>title>
<script src="../../js/vue.js">script>
head>
<body>
<div id="app">
<cpn>
<template #slot1>
<h3>具名插槽slot1缩写h3>
template>
<template v-slot:default>
<h3>具名插槽defaulth3>
template>
<template v-slot:slot2>
<h3>具名插槽slot2h3>
template>
cpn>
div>
body>
<template id="component">
<div>
<h2>插槽的基本使用:h2>
<h3>1、在模板中使用slot标签,可设置name属性,在使用插槽时用v-slot:××来标识向哪个插槽中添加内容h3>
<h3>2、可以在slot中添加标签提供默认值h3>
<h3>3、在组件标签中添加标签,替换或者添加插槽中的内容h3>
<slot name="slot1"><h3>插槽1h3>slot>
<slot>默认插槽slot>
<slot name="slot2">slot>
div>
template>
<script>
let vue = new Vue({
el:'#app',
components:{
cpn:{
template:'#component'
}
}
});
script>
html>
作用:父组件替换插槽中的标签,并且数据由子组件来提供。
(1)在slot中使用v-bind:user="user"
定义插槽prop。也就是向上传递子组件的user数据。
<slot name="slot1" v-bind:user="user">slot>
(2)使用插槽时用v-slot:slot1="userProp"
,这里的userProp就是slot向上传递的子组件的user数据。
<template v-slot:slot1="userProp">
<h3>{
{userProp.user.firstname}}h3>
template>
<html>
<head>
<meta charset="utf-8">
<title>title>
<script src="../../js/vue.js">script>
head>
<body>
<div id="app">
<cpn>
<template v-slot:slot1="userProp">
<h3>{
{userProp.user.firstname}}h3>
template>
<template v-slot:slot2="languageProp">
<ul>
<li v-for="item in languageProp.language">{
{item}}li>
ul>
template>
cpn>
div>
body>
<template id="component">
<div>
<slot name="slot1" v-bind:user="user">slot>
<slot name="slot2" v-bind:language="language">slot>
div>
template>
<script>
let vue = new Vue({
el:'#app',
components:{
cpn:{
template:'#component',
data:function(){
return{
user:{
username:'zhaowendi',
firstname:'zhao',
lastname:'wendi'
},
language:['C++','Java','C#']
}
}
}
}
});
script>
html>
(1)在html中引入js文件时,type必须是module。
<html>
<head>
<meta charset="utf-8">
<title>title>
head>
<body>
<script src="./aaa.js" type="module">script>
<script src="./bbb.js" type="module">script>
body>
html>
(2)导出方式:导出aaa.js中的变量、类或者方法。使用export
或者export default
导出。
export可以在需要导出的对象定义后使用
var flag = true;
function sum(sum1,sum2){
return sum1+sum2;
}
if(flag){
console.log(name + ": " + sum(20,30));
}
// 导出方式一:
export{
flag,
sum,
}
export也可以在定义变量、函数或者类的时候使用
//导出方式二-变量
export var height = 180;
//导出方式二-函数
export function mul(num1,num2){
return num1 * num2;
}
//导出方式二-类
export class Person{
run(){
console.log("类中的方法")
}
}
export default导出方式:export default在同一模块中不允许同时存在多个。
//导出方式三:export default
// var dft = 'export default';
// export default dft;
// function dft(){
// console.log('export default');
// }
// export default dft;
export default function(){
console.log('export default');
}
var name = '小明';
var age = 18;
var flag = true;
function sum(sum1,sum2){
return sum1+sum2;
}
if(flag){
console.log(name + ": " + sum(20,30));
}
// 导出方式一:
export{
flag,
sum,
}
//导出方式二-变量
export var height = 180;
//导出方式二-函数
export function mul(num1,num2){
return num1 * num2;
}
//导出方式二-类
export class Person{
run(){
console.log("类中的方法")
}
}
//导出方式三:export default
// var dft = 'export default';
// export default dft;
export default function(){
console.log('export default');
}
(3)导入方式:使用import…from 导入。
//1、导出方式为export的导入方式
import{
flag, sum} from "./aaa.js";
import * as aa from "./aaa.js";
//2、导出方式为export default的导入方式,接收参数可自己命名
import dftVar from "./aaa.js";
//1、导出使用export的导入方式。{}中是导出时的命名
import{
flag, sum} from "./aaa.js";
var name = '小红';
if(flag){
console.log(name + ": " + sum(100,300));
}
import{
Person} from "./aaa.js";
var prsn = new Person();
prsn.run();
//2、统一全部导入
import * as aa from "./aaa.js";
console.log(aa.height);
console.log("sum: " + aa.sum(1,2));
//3、导出方式为 export default,的导入方式,接收参数可自己命名
import dftVar from "./aaa.js";
// console.log(dftVar);//变量
dftVar();//方法
webpack安装首先需要安装Node.js,Node.js自带了软件包管理工具npm
查看自己的node版本
node -v
全局安装webpack(这里指定安装的版本号是3.6.0,vue cli2依赖该版本)
npm install webpack@3.6.0 -g
局部安装webpack(暂时不安装)
cd 对应目录
npm install webpack@3.6.0 --save-dev
为什么全局安装后,还需要局部安装呢?
CLI是Command-Line-Interfave,翻译为命令行界面,但是俗称脚手架。
Vue CLI是一个官方发布vue.js项目脚手架。
使用vue-cli可以快速搭建Vue开发环境以及对应的webpack配置。
脚手架使用的前提:安装node.js。vue脚手架安装
//以App作为template替换挂载#app中的内容。效果等同于下方的写法。运行周期为 render->vdom->ui;此性能更高
new Vue({
render: h => h(App),
}).$mount('#app')
// //效果等同于上面写法:运行周期为template->ast->render->vdom->ui
// new Vue({
// el:'#app',
// template:' ',//替换#app
// components:{App}
// })
vue-router官方文档
vue-router是基于路由和组件的:
(1)导入路由对象,并且调用Vue.user(VueRouter)
(2)创建路由实例,并且传入路由映射配置。
(3)在Vue实例中挂载创建的路由实例。
首先安装好插件,然后在src/router/下生成index.js文件。内容如下:
import Vue from 'vue'
import VueRouter from 'vue-router'
import Home from '../views/Home.vue'
//1、通过Vue.use安装插件
Vue.use(VueRouter)
const routes = [
{
path: '/',
name: 'Home',
component: Home
},
{
path: '/about',
name: 'About',
// route level code-splitting
// this generates a separate chunk (about.[hash].js) for this route
// which is lazy-loaded when the route is visited.
component: () => import(/* webpackChunkName: "about" */ '../views/About.vue')
}
]
//2、配置路由和组件之间的映射关系:一个url对应一个组件
const router = new VueRouter({
routes
})
//3、将router对象导出,并使用到Vue的实例中。
export default router
在main.js中挂载路由
import Vue from 'vue'
import App from './App.vue'
import router from './router'
Vue.config.productionTip = false
//以App作为template替换挂载#app中的内容。效果等同于下方的写法。运行周期为 render->vdom->ui;此性能更高
new Vue({
router,//使用路由
render: h => h(App)
}).$mount('#app')
// //效果等同于上面写法:运行周期为template->ast->render->vdom->ui
// new Vue({
// el:'#app',
// template:' ',//替换#app
// components:{App}
// })
第一步:创建路由组件。在components目录下创建Home.vue和About.vue两个文件
我是首页
我是相关页面
第二步:配置路由映射:组件和路劲映射关系。在router/index.js 下添加映射
import Vue from 'vue'
import VueRouter from 'vue-router'
import Home from '../components/Home.vue'
import About from '../components/About.vue'
//1、通过Vue.use安装插件
Vue.use(VueRouter)
const routes = [
{
path: '/home',
component: Home
},
{
path: '/about',
component: About
// component: () => import(/* webpackChunkName: "about" */ '../views/About.vue')
}
]
//2、配置路由和组件之间的映射关系:一个url对应一个组件
const router = new VueRouter({
routes
})
//3、将router对象导出,并使用到Vue的实例中。
export default router
第三步:使用路由:通过和。在App.vue中使用路由。
首页
关于
运行:npm run serve
{
//默认路由
path:'',
// component:Home,//问题:显示首页的时候路径并不是首页的路径
redirect:'/home'
},
改变路径的方式有两种:url的hash、html5的history。
默认情况下,改变路径使用的是hash。
//2、配置路由和组件之间的映射关系:一个url对应一个组件
const router = new VueRouter({
routes,
mode:'history'//默认为hash,在路径前面会有#号
})
to:用于指定跳转的路径。
tag:可以指定之后渲染成什么标签,默认渲染为标签。
<router-link to="/home" tag="button" replace>首页 router-link>
<router-link to="/about" tag="li" replace>关于router-link>
active-class(没什么用):对应路由匹配成功后,自动给当前元素设置一个router-link-active的class。
首页
关于
使用active-class
给classrouter-link-active
重新命名。
首页
关于
动态路由
案例:在首页点击用户,跳转到用户组件,并且携带参数,在用户组件中再获取参数。
首先添加一个User.vue组件:this.$route
获取当前活跃的路由。
我是用户页面: {
{getUserId}}
将组件添加到路由:path: '/user/:userId'
,在路由地址中添加动态参数
import User from '../components/User.vue'
{
path: '/user/:userId',
component: User
},
import Vue from 'vue'
import VueRouter from 'vue-router'
import Home from '../components/Home.vue'
import About from '../components/About.vue'
import User from '../components/User.vue'
//1、通过Vue.use安装插件
Vue.use(VueRouter)
const routes = [
{
//默认路由
path:'',
// component:Home,//问题:显示首页的时候路径并不是首页的路径
redirect:'/home'
},
{
path: '/home',
component: Home
},
{
path: '/about',
component: About
// component: () => import(/* webpackChunkName: "about" */ '../views/About.vue')
},
{
path: '/user/:userId',
component: User
},
]
//2、配置路由和组件之间的映射关系:一个url对应一个组件
const router = new VueRouter({
routes,
mode:'history',//默认为hash,在路径前面会有#号
linkActiveClass:'active'
})
//3、将router对象导出,并使用到Vue的实例中。
export default router
在App.vue中进行路由跳转
用户
data:function(){
return {
userId:'zhaowendi'
}
},
首页
关于
用户
在User.vue中使用:this.$route.params.userId
获取传递过来的参数。
路由懒加载
首先路由中通常会定义很多不同的页面。这些页面最后被打包到哪里呢?一般情况下,是放在一个js文件中。但是这么多页面放到一个js文件中,必然会造成这个页面非常的大。
如果我们 一次性从服务器请求这个页面,可能会花费一定的时间,甚至用户的电脑上还会出现短暂空白的情况。如何避免这种情况呢?使用路由懒加载就可以了。
路由懒加载做了什么:路由懒加载的主要作用就是将路由对应的组件打包成一个个的js代码块,只有在这个路由被访问的时候,才加载对应的组件。
//使用路由懒加载
const Home = () => import('../components/Home.vue')
const About = () => import('../components/About.vue')
const User = () => import('../components/User.vue')
import Vue from 'vue'
import VueRouter from 'vue-router'
// import Home from '../components/Home.vue'
// import About from '../components/About.vue'
// import User from '../components/User.vue'
//使用路由懒加载
const Home = () => import('../components/Home.vue')
const About = () => import('../components/About.vue')
const User = () => import('../components/User.vue')
//1、通过Vue.use安装插件
Vue.use(VueRouter)
const routes = [
{
//默认路由
path:'',
// component:Home,//问题:显示首页的时候路径并不是首页的路径
redirect:'/home'
},
{
path: '/home',
component: Home
},
{
path: '/about',
component: About
// component: () => import(/* webpackChunkName: "about" */ '../views/About.vue')
},
{
path: '/user/:userId',
component: User
},
]
//2、配置路由和组件之间的映射关系:一个url对应一个组件
const router = new VueRouter({
routes,
mode:'history',//默认为hash,在路径前面会有#号
linkActiveClass:'active'
})
//3、将router对象导出,并使用到Vue的实例中。
export default router
嵌套路由
实现嵌套路由有两个步骤:
(1)创建对应的子组件,并且再路由映射中配置对应的子路由。
(2)在组件内部使用
在.vue文件中,template中的标签用div包裹。
创建两个组件HomeMessage.vue、HomeNews.vue。
首页消息
- 消息1
- 消息2
- 消息3
- 消息4
首页新闻
- 新闻1
- 新闻2
- 新闻3
- 新闻4
配置路由。将HomeNews和HomeMessage嵌套在Home路由下。
注意children
:下的path写法,前面不用加斜杠
//使用路由懒加载
const Home = () => import('../components/Home.vue')
const HomeMessage = () => import('../components/HomeMessage.vue')
const HomeNews = () => import('../components/HomeNews.vue')
{
path: '/home',
component: Home,
//路由嵌套
children:[
{
path:'',
redirect:'message'
},
{
//不能写成 `/message`
path:'message',
component:HomeMessage
},
{
path:'news',
component:HomeNews
}
]
},
在Home.vue组件中使用HomeMessage和HomeNews。
我是首页
消息
新闻
该参数传递见6-6.4动态路由
参数传递方式:
<router-link :to="{path:'/profile',query:{name:'kobo',age:12,height:188}}">档案 router-link>
参数接收方式:$route.query
<h4>{
{$route.query.name}}h4>
<h4>{
{$route.query.age}}h4>
<h4>{
{$route.query.height}}h4>
档案页面
{
{$route.query.name}}
{
{$route.query.age}}
{
{$route.query.height}}
配置Profile路由:
const Profile = () => import('../components/Profile.vue')
{
path:'/profile',
component:Profile
}
在App.vue中访问路由
档案
路由配置不变(path: '/user/:userId',path:'/profile'
),接收方式不变($route.params
,$route.query
)。
btnUser:function(){
this.$router.replace('/user/' + this.userId);
},
btnProfile:function(){
this.$router.replace({
path:'/profile',
query:{
name:'kobo',age:18,height:198}
})
}
导航守卫
生命周期函数:
create:创建组件实例时回调
mounted:组件创建后,将template挂载到dom中时回调
updated:页面每刷新一次就会回调。
在页面跳转之前修改页面的title属性。
首先在路由中添加meta元数据。路由元信息
const routes = [
{
path: '/about',
component: About,
meta:{
title:'关于'
}
// component: () => import(/* webpackChunkName: "about" */ '../views/About.vue')
},
{
path: '/user/:userId',
component: User,
meta:{
title:'用户'
}
},
{
path:'/profile',
component:Profile,
meta:{
title:'档案'
}
}
]
添加前置守卫
//前置守卫:在跳转之前调用
router.beforeEach((to,from,next) => {
// console.log(to)
console.log("++++++++++++")
//从from跳转到to
document.title = to.meta.title;
//必须调用next
next();
})
//后置钩子(hook):在跳转后调用
router.afterEach((to,from) => {
console.log("------------")
})
路由独享守卫 组件内的守卫
keep-alive
keep-alive是Vue内置的一个组件,可以使被包含的组件保留状态,或避免重新渲染。
属性:
include:字符串或正则表达式,只有匹配的组件会被缓存。
exclude:字符串或正则表达式,任何匹配的组件都不会被缓存。
方法:activated、deactivated。在获得状态和失去状态时触发。
环境:Vue CLI4
1、在assets下创建 img/tabbar,然后存放需要用到的图标(8个)
2、在components下创建tabbar目录,并创建TabBarItem.vue以及TabBar.vue两个组件。
TabBarItem.vue
TabBar.vue
3、创建router-view中需要显示的页面。
内容如下:
首页
4、配置上述4个页面的路由
import Vue from 'vue'
import VueRouter from 'vue-router'
const Home = () => import('../views/home/Home.vue')
const Category = () => import('../views/category/Category.vue')
const Cart = () => import('../views/cart/Cart.vue')
const Profile = () => import('../views/profile/Profile.vue')
//1、通过Vue.use安装插件
Vue.use(VueRouter)
const routes = [{
path: '',
redirect: '/home'
},
{
path: '/home',
component: Home
},
{
path: '/category',
component: Category
},
{
path: '/cart',
component: Cart
},
{
path: '/profile',
component: Profile
}
]
//2、配置路由和组件之间的映射关系
const router = new VueRouter({
mode: 'history',
// base: process.env.BASE_URL,
routes
})
//3、导出路由
export default router
在App.vue中使用TabBar、TabBarItem组件,以及使用进行路由之间的跳转和显示。
首页
分类
购物车
我的
补充:还可以将App.vue中的内容抽取出来作为一个组件。
Vuex
官方解释:Vuex是一个专为Vue.js应用程序开发的状态管理模式。
它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。
Vuex也集成到Vue的官方调试工具devtools extension
,提供了诸如零配置的time-travel调试,状态快照导入导出等高级调试功能。
状态管理是什么? 可以简单的将其看成把需要多个组件共享的变量全部存储在一个对象里面。然后将这个对象放在顶层的Vue实例中,让其它组件可以使用。
哪些状态需要在多个组件之间共享呢?比如用户的登录状态、用户名称、头像、地理位置等等。这些状态信息都可以放在统一的地方,对它进行保存和管理,而且它们还是响应式的。
使用环境:创建项目时安装Vuex插件、在浏览器中安装devTools插件(可以跟踪Vuex中的属性)
import Vue from 'vue'
import Vuex from 'vuex'
//1、安装Vuex
Vue.use(Vuex)
//2、创建Vuex对象store
const store = new Vuex.Store({
//共享变量
state:{
count:1000
},
//同步操作的方法
mutations:{
increment:function(state){
state.count++;
},
decrement:function(state){
state.count--;
}
},
//异步操作的方法
actions:{
},
// getters:{},
// modules:{}
});
//3、导出store
export default store;
在components下创建HelloVuex.vue组件。
HelloVuex内容
{
{$store.state.count}}
App.vue
访问Vuex中的state属性$store.state.count
调用Vuex中的mutations方法$store.commit('increment');
App的内容
{
{$store.state.count}}
类似于组件中的计算属性computed。将state中的数据经过处理后再使用。
//相当于组件的computed
getters: {
powerCount: function(state) {
return state.count * state.count;
},
//1、默认参数state
more20Stu: function(state) {
return state.students.filter(stu => stu.age > 20);
},
//2、默认参数getters
more20Length:function(state,getters){
return getters.more20Stu.length;
},
//3、调用getters时传入参数;通过返回一个函数来实现
moreStu:function(state){
return function(age){
return state.students.filter( stu => stu.age >= age);
}
}
},
getters的使用:
1、默认参数state,getters
{
{$store.getters.more20Stu}}
{
{$store.getters.more20Length}}
2、向getters中传入自定义参数,通过在getters中返回一个函数来实现
{
{$store.getters.moreStu(28)}}
全部代码:
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
count: 100,
students: [
{
id: 100,name: 'cobo',age: 28
},
{
id: 101,name: 'curry',age: 10
},
{
id: 102,name: 'windy',age: 23
},
]
},
mutations: {
increment: function(state) {
state.count++;
},
decrement: function(state) {
state.count--;
}
},
actions: {
},
//相当于组件的computed
getters: {
powerCount: function(state) {
return state.count * state.count;
},
//默认参数state
more20Stu: function(state) {
return state.students.filter(stu => stu.age > 20);
},
//默认参数getters
more20Length:function(state,getters){
return getters.more20Stu.length;
},
//调用getters时传入参数;通过返回一个函数来实现
moreStu:function(state){
return function(age){
return state.students.filter( stu => stu.age >= age);
}
}
},
modules: {
}
})
App中的内容
{
{$store.state.count}}
getters的使用:
1、默认参数state,getters
{
{$store.getters.more20Stu}}
{
{$store.getters.more20Length}}
2、向getters中传入自定义参数,通过在getters中返回一个函数来实现
{
{$store.getters.moreStu(28)}}
Vuex的store状态(state)的更新的唯一方式:提交mutation
mutations: {
increment: function(state) {
state.count++;
},
decrement: function(state) {
state.count--;
},
//携带参数
incrementCount:function(state,cnt){
state.count += cnt;
}
},
mutations的使用:
1、不传参数,使用默认的state参数
2、携带参数
methods: {
add: function() {
this.$store.commit('increment');
},
sub: function() {
this.$store.commit('decrement');
},
//携带参数的写法
addCount: function(cnt) {
this.$store.commit('incrementCount', cnt);
}
}
//1、普通提交形式
// this.$store.commit('incrementCount', cnt);
//2、特殊的提交形式
this.$store.commit({
type:'incrementCount',
cnt:cnt,
age:18
});
//携带参数
incrementCount:function(state,cnt){
//1、普通提交的接收参数的方式
// state.count += cnt;
//2、特殊形式提交 接收参数的方式,cnt是一个对象:{ type: "incrementCount", cnt: 5, age: 18 }
console.log(cnt);
state.count += cnt.cnt;
}
mutations遵循Vue的响应规则,详看mutation-需遵守-vue-的响应规则
最好提前在你的 store 中初始化好所有所需属性。
info:{
name:'cobo',
age:19
}
add:function(state){
// state.info['address'] = "遵义";//该方式做不到响应式
//响应式的增加元素
Vue.set(state.info,'address','遵义');
//响应式的删除元素
Vue.delete(state.info,'name');
console.log(state.info);
}
mutations的类型常量:将mutations的方法名定义为常量,在使用时使用常量来减少错误。
首先在store下创建 mutation-types.js文件,在里面定义常量并导出
export const INCREMENT = 'increment'
在store的mutations中使用常量
import {
INCREMENT} from './mutation-types.js'
mutations: {
[INCREMENT]: function(state) {
state.count++;
},
}
在App.vue中调用该mutations方法。
methods: {
add: function() {
this.$store.commit(INCREMENT);
},
}
actions
modules
安装:npm install axios --save
1、get请求的参数拼接:也可以直接拼接在地址中。如果是post,则是data
axios({
url:'',
method:'get'
params:{
userid:'123'
}
}).then({
res => {
console.log(res);
}
})
2、发送并发请求:
//2、axios发送并发请求
axios.all([axios(), axios()])
.then(results => {
//并发请求的请求结果:数组results[0],results[1]
})
axios.all([axios(), axios()])
.then(axios.spread((res1, res2) => {
//已将结果进行分割成两个变量
}))
4、上述的配置都是全局的,对于每一请求都有用。创建Axios实例
//4、axios实例
const instance1 = axios.create({
baseURI:'localhost:8080',
timeout:5000,
headers:{
}
});
instance1({
url:'/home'
}).then({
res => {
console.log(res);
}
});
方式一:request.js,需要传递三个参数。一个config,其他两个是函数。
import axios from 'axios'
export function request(config,success,failure){
//1、创建axios的实例
const instance = axios.create({
baseURL:'http://123.207.32.32:8000',
timeout:5000
});
//2、发送请求
instance(config)
.then(res => {
// console.log(res);
success(res);
})
.catch(err => {
// console.log(err);
failure(err);
})
}
//其他不同配置的请求的封装
export function instance2(){
}
调用方式:
//请求axios的封装
import {
request} from './network/request.js'
request({
url: '/home/multidata'
}, res => {
console.log(res);
}, err => {
console.log(err);
})
方式二:只用传递一个config参数,直接将请求结果返回。
import axios from 'axios'
// export function request(config,success,failure){
// //1、创建axios的实例
// const instance = axios.create({
// baseURL:'http://123.207.32.32:8000',
// timeout:5000
// });
// //2、发送请求
// instance(config)
// .then(res => {
// // console.log(res);
// success(res);
// })
// .catch(err => {
// // console.log(err);
// failure(err);
// })
// }
export function request(config){
//1、创建axios的实例
const instance = axios.create({
baseURL:'http://123.207.32.32:8000',
timeout:5000
});
//2、发送请求
return instance(config);
}
//其他不同配置的请求的封装
export function instance2(){
}
调用方式:
request({
url: '/home/multidata'
}).then( res => {
console.log(res);
}).catch( err => {
console.log(err);
})
//2、axios的拦截器
//2.1请求拦截
instance.interceptors.request.use( config => {
//请求成功
console.log(config);
return config;
}, err => {
//请求失败
console.log(err);
});
//2.2响应拦截
instance.interceptors.response.use( res =>{
//响应成功
//可以对结果进行处理后再返回
return res;
}, err => {
//响应失败
console.log(err);
})
import axios from 'axios'
export function request(config){
//1、创建axios的实例
const instance = axios.create({
baseURL:'http://123.207.32.32:8000',
timeout:5000
});
//2、axios的拦截器
//2.1请求拦截
instance.interceptors.request.use( config => {
//请求成功
console.log(config);
return config;
}, err => {
//请求失败
console.log(err);
});
//2.2响应拦截
instance.interceptors.response.use( res =>{
//响应成功
//可以对结果进行处理后再返回
return res;
}, err => {
//响应失败
console.log(err);
})
//3、发送请求
return instance(config);
}
//其他不同配置的请求的封装
export function instance2(){
}
ce1 = axios.create({
baseURI:‘localhost:8080’,
timeout:5000,
headers:{}
});
instance1({
url:’/home’
}).then({
res => {
console.log(res);
}
});
### 5、axios的封装:首先在src下创建:network/request
+ 方式一:request.js,需要传递三个参数。一个config,其他两个是函数。
```js
import axios from 'axios'
export function request(config,success,failure){
//1、创建axios的实例
const instance = axios.create({
baseURL:'http://123.207.32.32:8000',
timeout:5000
});
//2、发送请求
instance(config)
.then(res => {
// console.log(res);
success(res);
})
.catch(err => {
// console.log(err);
failure(err);
})
}
//其他不同配置的请求的封装
export function instance2(){
}
调用方式:
//请求axios的封装
import {
request} from './network/request.js'
request({
url: '/home/multidata'
}, res => {
console.log(res);
}, err => {
console.log(err);
})
方式二:只用传递一个config参数,直接将请求结果返回。
import axios from 'axios'
// export function request(config,success,failure){
// //1、创建axios的实例
// const instance = axios.create({
// baseURL:'http://123.207.32.32:8000',
// timeout:5000
// });
// //2、发送请求
// instance(config)
// .then(res => {
// // console.log(res);
// success(res);
// })
// .catch(err => {
// // console.log(err);
// failure(err);
// })
// }
export function request(config){
//1、创建axios的实例
const instance = axios.create({
baseURL:'http://123.207.32.32:8000',
timeout:5000
});
//2、发送请求
return instance(config);
}
//其他不同配置的请求的封装
export function instance2(){
}
调用方式:
request({
url: '/home/multidata'
}).then( res => {
console.log(res);
}).catch( err => {
console.log(err);
})
//2、axios的拦截器
//2.1请求拦截
instance.interceptors.request.use( config => {
//请求成功
console.log(config);
return config;
}, err => {
//请求失败
console.log(err);
});
//2.2响应拦截
instance.interceptors.response.use( res =>{
//响应成功
//可以对结果进行处理后再返回
return res;
}, err => {
//响应失败
console.log(err);
})
import axios from 'axios'
export function request(config){
//1、创建axios的实例
const instance = axios.create({
baseURL:'http://123.207.32.32:8000',
timeout:5000
});
//2、axios的拦截器
//2.1请求拦截
instance.interceptors.request.use( config => {
//请求成功
console.log(config);
return config;
}, err => {
//请求失败
console.log(err);
});
//2.2响应拦截
instance.interceptors.response.use( res =>{
//响应成功
//可以对结果进行处理后再返回
return res;
}, err => {
//响应失败
console.log(err);
})
//3、发送请求
return instance(config);
}
//其他不同配置的请求的封装
export function instance2(){
}