Vue.js第三篇:组件和路由

一、组件(最基本的能力)

1、vue组件的定义

在页面引入的组件同时也是Vue的实例(如:

  • 什么是模块化:模块化从代码角度出发,分析项目,把项目中功能类似的代码抽离为一个个小的模块,为了以相同的方式去封装模块,于是就创造了模块化的规范(CommonJS规范)
  • 优点:方便项目的开发,方便后期的维护和扩展 ,提高开发效率
  • 什么是组件化:从UI的角度出发,把页面上有重用性的UI结构和样式,单独抽离出来,封装为一个单独的组件(封装的是HTML元素),每个组件是一个自定义的元素
  • 优点:随着项目的发展,组件会越来越多,今后一个界面的UI几乎都可以从现成的组件拼接出来,方便项目的开发和维护
  • 注意:组件也有自己的生命周期函数,这些函数与vm实例的生命周期一致
  • 最常用.vue文件来使用组件(单独一个组件文件,实现组件化)

2、全局组件定义的方式

第一种:

(1)使用Vue.component注册一个组件:

// Vue.component的第二个参数,即接收一个组件的构造函数,也接收一个对象
Vue.component('mycom2',{
	template:'

这是直接使用Vue.component创建出的组件

'
});

(2)把注册好的全局组件标签以标签的形式引入到页面中

<div id="app">

    <mycom1>mycom1>
div>
第二种:

(1)使用template标签定义一个模板的代码结构:


<template id="tmpl">
    <h3>哈哈哈,这是在外界定义的组件UI结构h3>
template>

注意:

  • template标签应该放在与id='app’的盒子平级的地方
  • template如果放在#app里面,则组件会被注册两次,元素会被渲染两次
  • 如果直接写为下面这样,则没有效果(因为组件已经不在Vue实例vm控制的区域内)
<mycom3>mycom3>
<template id="tmpl">
    <h3>哈哈哈,这是在外界定义的组件UI结构h3>
template>

(2)使用Vue.component注册组件:

Vue.component('mycom3',{
    template:'#tmpl'
})

(3)把注册好的全局组件标签以标签的形式引入到页面中

3、定义私有组件

(1)在Vue实例中的定义私有组件(包含组件的名称和组件的结构):

components:{  // 定义实例中的私有组件  包含组件的名称和组件的结构
    'mycom4':{
        template:"
这是定义的私有组件
"
} }

(2)把注册好的全局组件标签以标签的形式引入到页面中

4、在组件中定义私有数据和方法(组件中展示数据和响应事件)

Vue.component('mycom',{
     template:"

这是自定义的组件{{msg}}

"
, data:function(){ return { msg:'hhh' } }, methods:{ show(){ console.log('触发了组件的show方法'); } } })

注意:

  • 添加data属性时,data必须定义为function且必须返回一个对象
  • 为什么必须定义成function呢?
    因为这样的话,每当我们在页面中引用一次组件,必须会先调用这个data:function,从而得到一个当前组件私有的数据对象(保证每个组件的data是私有的)
  • 为什么必须返回一个对象?
    每创建一个实例时调用function,返回一个新对象,新对象与之前创建的实例指向的对象无关系。如果返回的是在全局定义的对象,则每次创建的实例都会指向这个对象,即共用一个返回对象,其中一个实例的指向的对象的值改变时,所有实例指向的对象的值都会随之改变(数据联动)

5、组件的切换

1.两个组件的简单切换:
使用v-ifv-else、标识符、布尔值结合实现两个组件的切换
2.多个组件的切换

6、父组件与子组件传值问题

1.父组件向子组件传递普通数据:

(1)把要传递给子组件的数据作为自定义属性,通过v-bind绑定到子组件身上:

<com1 :msg="parentMsg">com1>

(2)在子组件中不能直接使用父组件传递过来的数据,需要使用props将数据接收一下:

// 要传递的数据:
data:{
     parentMsg:"哈哈哈,你是想笑死我,然后继承我的蚂蚁花呗吗?"
},
components:{
     'com1':{   // 在Vue中默认子组件无法直接获取父组件中的数据
         template:`

这是子组件中的标题{{msg}}

`
, // 在数组中定义一下msg props:['msg'] // 在Vue中只有props是数组,其他以-s结尾的是对象 } }

注意:

  • 在接收父组件传递过来props时候,接受的名称一定要和父组件传递过来的自定义属性名称保持一致
2.父组件向子组件传递对象:
  • props:['msgobj']接收
3.父组件向子组件传递方法:
  • this.$emit('func')接收

注意:

  • 如果要向子组件传递data中的数据,则使用属性绑定的形式v-bind
  • 如果要向子组件传递methods中的数据,则使用事件绑定的形式v-on
4.子组件向父组件传值:

子组件向父组件传值,本质上,还是调用了父组件传递过来的方法(show方法),只不过,子组件在调用的时候,把数据当作参数传给了这个方法(show方法)
(1)把要传递给子组件的方法作为事件,通过v-on绑定到子组件身上:

<com1 @func='show'>com1>  

(2)为子组件添加自己的触发事件,并传值给父组件:

// 父组件要传递给子组件的方法:
methods:{
    show(){
        console.log("有人调用了父组件中的show方法");
    }
},
components:{
    'com1':{
         template:`
`
, data:function(){ return{sonMsg:"这是子组件中的值"} } methods:{ this.$emit('func',sonMsg); // 第二个位置后面的是子组件向父组件传递的值 } } } }

(3)父组件接收这个参数(值):

data:{
   msgFromSon:''
},
methods:{
   show(arg1){
      // 把子组件传递过来的数据,保存到父组件的data中
      this.msgFromSon = arg1;
      console.log(this.msgFromSon);
   }
},
5.在Vue组件中data和props的区别:
  • 1、data在组件要定义成function并返回一个对象
  • 2、props在组件中定义成数组,数组的值都是字符串名,表示父组件传递过来的数据
  • 3、props的数据不要直接拿来修改,如果想要修改,必须在data上重新顶一个属性,然后把属性的值从this.props拿过来修改
  • 4、data上的数据都是组件私有的,data上的数据都是可读可写的
  • 5、props上的数据都是外界传过来的数据,只能读不能写

二、路由

1、什么是路由?

  • 1、对于普通的网站,所有的超链接都是URL地址,所有的URL地址都对应服务器上对应的资源
  • 2、对于单页面的程序来说,主要通过URL中的hash(#号)来实现不同页面之间的切换,同时,hash有一个特点:HTTP请求中不会包含hash相关的内容,所以,单页面程序中的页面跳转主要用hash实现
  • 3、在单页面程序中,这种通过hash改变来切换页面的方式,称作前端路由(区别于后端路由)
  • 4、前端路由就是根据不同的hash地址展示不同的组件
  • 5、后短路由:把后端地址URL地址与处理函数之间做一层对应关系
  • 6、#叫做hash,不会刷新页面,也不会发起新的HTTP请求,只是实现客户端页面的定位的(因为#后面的值不会传给服务端)
  • 7、#可以修改浏览器端的历史访问记录

2、Vue中的路由:v-router

路由的基本使用:
(1)在导入vue包后导入vue-router的包:

<script src="./lib/vue-router-v3.0.1.js"></script>

(2)创建对应的组件:

const login = {
    template:'

登陆组件

' } const reg = { template:'

注册组件

' }

注意:

  • 不能再利用之前的方法创建组件了,因为之前创建的组件的组件名仅限于以标签的形式引入页面中,不能用于匹配路由规则,所以把对象单独拎出来

(3)创建路由对象:

const router = new VueRouter({
    routes:[
       {path:"/login", component:login},  // 路由规则
       {path:"/reg", component:reg}  
    ]
})

注意:

  • routes:是固定属性,表示路由规则数组----把hash值和组件做对应关系,且每个对象都表示一个路由规则
  • 对象中的属性:path 表示要匹配的hash值,component 表示对应的hash要展示的组件对象
  • component的属性不能传字符串,只能传一个对象
  • 匹配到的路由组件如果想要展示在页面上,需要在页面上放一个标签router-view(路由的坑)

(4)将路由对象挂载在Vue实例中
(5)利用路由的坑(容器),将对应的路由组件填到坑中:

<div id="app">
        <router-link to="/login">登录router-link>
        <router-link to="/reg">注册router-link>
        <router-view>router-view>
div>

注意:

  • router-link:路由链接,默认渲染为a标签,也有tag属性
  • router-view:默认不会被渲染为元素

总结:
路由匹配过程:点击不同的路由标签修改hash值,hash值被修改后,被路由规则监听到,然后匹配对应的路由规则
路由的目的:监听hash值的改变,根据路由规则,匹配对应的路由规则,展示对应的路由组件

3、在路由中传参

(1)query传参:优点:不需要修改路由规则
<router-link to="/login?id=10">登录router-link>

获取参数:

template:'<h3>登陆组件----{{$route.query.id}}h3>',
(2)/ 传参:需要修改路由规则,与node的express的传参和获取参数一致
<router-link to="/login/10/zs">登录router-link>

修改路由规则:

{path:'/login/:id/:name', component: login}

获取参数:

template:'<h3>登陆组件----{{$route.params.id}}----{{$route.params.name}}h3>',
(3)/传参时为了方便使用props获取参数:

在组件中使用$route会使参数和对应的路由形成高度的耦合
使用props解耦:

const login = {
    props:['id','name'],
    template:'

登陆组件----{{id}}----{{name}}

'
, } const router = new VueRouter({ routes:[ {path:'/login/:id/:name', component:login, props:true}, // 此写法与express完全一致

4、vue-router的重点内容

  • v-router是实现前端路由的
  • 什么是前端路由:根据不同的hash地址,在页面上切换不同的组件(hash地址和组件的对应关系)
  • 什么是后端路由:是URL地址和处理函数之间的对应关系
  • 前端路由的目的:为了做单页面应用程序(Single Page Application)
  • 学习前端框架的主要目的:就是利用这些现成的框架,方便我们快速进行单页面程序的开发【实现单页面应用程序的基本前提:要有vue的路由、组件】

5、使用路由规则的children属性实现路由和组件的嵌套

实现路由组件的嵌套:

(1)在父路由的组件中创建子路由链接和子路由容器

const account = {
   template:``
        }

(2)创建account路由规则的子路由规则:

const router = new VueRouter({
	routes:[
        {path:'/account', component:account, children:[
             {path:'login',component:login},  // account路由规则的子路由规则
             {path:'reg',component:reg},
             // 注意:使用children属性创建的路由规则。path的值前面不要加/
        ]},  // 展示账号组件的路由匹配规则
   ]
})

注意:

  • 如果账号组件和登陆组件的路由规则是平级的,则会在页面的同一个路由的容器中显示,不会形成嵌套
    如:
 routes:[
    {path:'/account',component:account},  // 展示账号组件的路由匹配规则
    {path:'/account/login',component:login},  // 展示登陆组件的路由匹配规则
  • 通过路由规则的children属性,实现路由规则的嵌套,这样,组件之间也有了嵌套关系

6、命名视图

  • 为什么需要命名视图:在之前的路由规则,当匹配带一个路由规则时,只能在页面的路由的容器中放置唯一一个组件(因为一个路径无法展示多个组件),此时需要命名视图,在一个URL地址中展示多个组件
  • 什么时候用到命名视图:当在一层路由规则中需要展示多个组件时

(1)使用components

{path:'/',components:{
     // 组件名称:组件对象
     'top':header,
     'left':sidebar,
     'right':content,
     'bottom':footer
}}

(2)在router-view中使用name属性为不同组件命名:


<router-view name='top'>router-view>
   <div class="container">
       <router-view name='left'>router-view>
       <router-view name='right'>router-view>
   div>
<router-view name='bottom'>router-view>
}}

(2)在router-view中使用name属性为不同组件命名:


<router-view name='top'>router-view>
   <div class="container">
       <router-view name='left'>router-view>
       <router-view name='right'>router-view>
   div>
<router-view name='bottom'>router-view>

你可能感兴趣的:(前端,vue.js)