Vue组件以及插槽

vue的自定义组件

被vue所管理的标签可以认为是vue的组件。而在项目开发的过程中,经常会用到一些需要复用的标签结构以及相应样式。

vue提供了自定义组件的写法,可以让开发者将一些需要复用的结构、样式、功能组织在一起,作为一个整体存在在项目中。这样,当需要使用这个组件时,直接引用该组件即可,例如:

<div>

     <!-- 该组件就称为一个自定义组件,由开发者自行设计

          标签名自定义,属性自定义,事件自定义 -->

    <person src="图片路径" name="昵称"></person>

</div>

如何设计并实现一个自定义组件

目的:设计一个组件,模仿标签的样式,方便进行使用。

实现步骤:

1、设计一个自定义组件(包括它的外观、功能以及未来如何复用)

2、定义一个组件

      a、在components目录下新建 MyTag.vue。并且在该组件中定义基础样式。

      b、注意:< script >  export  default  { } </script>

3、当需要使用该组件时,需要先引入再使用:

       a、引用 MyTag 组件:

import MyTag from './components/MyTag.vue'

       components: {

// 组件名:组件对象

// 组件名相当于标签名,在页面中可以直接使用

// vue为了使用方便,自动支持将驼峰命名法 改为 短横线命名法

// <MyTag></MyTag> 大驼峰

// <my-tag></my-tag> 短横线

        MyTag: MyTag,

        mytag: MyTag,

        abc: MyTag

}

        b、直接通过标签名,使用该组件:

 

实现步骤:

     1、在子组件中的script 代码段中,通过props 定义自定义属性 ,接收父组件传进来的参数。

export default {

        props:{        //在props中声明当前组件所拥有的组件属性

            color: {

                default : ' 属性的默认值 ',        //设置属性的默认值

                type : 属性的类型,         //指定该属性的类型,此处指定为字符串

                require: true,        //指定该属性是否是必填项,使用时必须包含该属性;false则不是必填项目

                validate :通过正则验证属性值的格式

            },

            avatar  : {

                     type : String ,

                     default : ' '

        }

    }

}

 在此,vue 提供了一种简单的语法来定义属性:

export default { props: [ 'color', 'avatar', 'name' ] }

组件插槽

 平时在设计子组件时,绝大部分布局内容都已完成定义,但是有些布局需要父组件在使用当前子组件时动态设置, 这时就可以使用组件插槽。在设计子组件时,可以在布局中定义插槽位置及基础样式,父组件在使用时通过 slot 来动态赋值。

默认插槽

1. 在设计子组件时,在组件某一个位置添加slot标签(在此处安放一个插槽):

<template>

    < div class="my-tag" >

        <!-- 设计一个插槽,在使用时给插槽动态赋值页面结构 -->

        <slot />

    </div>

</template>

 2. 在父组件中使用子组件时,需要动态设置子组件的默认插槽内容:

     子组件开始标签与结束标签中的内容,将会作为默认插槽,替换子组件的 slot : 

<my-tag>标签</my-tag>

    <my-tag>文本</my-tag>

    <my-tag>

      <img src="/favicon.ico" >小图标

    </my-tag>

 具名插槽

如果在子组件中,有多个地方都需要在父组件引用时动态设置内容,则可以声明多个插槽,每一个插槽赋予一个名 字,称为具名插槽。

在使用该子组件并且为插槽设置内容时,可以使用 < slot name = ' 名称 ' > < /slot >来动态赋值。

案例:模仿后台管理页面的布局。

实现步骤:

       1、当设计一个子组件时,子组件中有多个地方需要插槽来动态赋值时,就可以为 slot 标签添加 name 属性:

    <div>

        <slot  name = "header"/>

        <slot  name = "left"/>

        <slot  name = "right"/>

    </div>

       2、当使用该组件时,通过slot 属性来指定为哪一个插槽设置内容:

       <Layout>

            <!-- slot属性用于指定插槽名字,将当前div放入名字叫header的插槽中 -->

           <div slot="header">header的内容</div>

           <div slot="left">left的内容</div>

           <div slot="right">right 的内容</div>

       </Layout>

案例完整代码:

// 自定义插槽
<template>
  <div>
    <button @click="getDirectors">获取导演列表</button>
    <br><br>
     
     <person v-for="item in directors" :key="item.id"
        :avatar="item.director_avatar"
        :name="item.director_name"></person>
    <!-- <div class="item" 
          v-for="item in directors" :key="item.id">
      <img :src="item.director_avatar" width="100px">
      <span>{{item.director_name}}</span>
    </div> -->

  </div>
</template>

<script>
import myaxios from './http/MyAxios'
import person from './components/person.vue'

  export default {
    components: {
      person,
    },
    data(){
      return {
        directors: [],   //绑定所有的导演
      }
    },
    methods :{
      getDirectors(){
        let url = 'https://web.codeboy.com/bmdapi/movie-directors'
        let params = {page:1, pagesize:100}
        myaxios.get(url,params).then(res=>{
          console.log(res)
          this.directors = res.data.data
        })
      }
    },
  }
</script>

<style lang="scss" scoped>

</style>
// My.axios 文件
import axios from 'axios'
const instance = axios.create()  //创建axios 实例
import qs from 'qs'

const myaxios = {
    
    /*
    用于发送get 请求
    url:请求资源路径
    params:请求参数(Object形式)
    */
    get(url,params){
        return instance({
            url,
            method:'get',
            params
        })
    },

    /* 用于发送post请求
       url :请求资源路径
       params:请求参数(Object)

    */
    post(url,params){
        return instance ({
            url,
            method: 'post',
            data: qs.stringify(params)
        })
    }
}

export default myaxios
// 自定义插槽的person.vue
<template>
<!-- 一般情况下,class类名应与组件名匹配
      组件名:Person.vue        class类:person
      组件名:MyTag.vue         class类:my-tag
 -->
    <div class="person" >
      <img :src="avatar" width="100px">
      <span>{{name}}</span>
    </div>
</template>

<script>
    export default {
        props: {
            avatar: {                //声明属性,指定头像
                type: String,
                default: ""
            },
            name:{                   //声明属性,指定需要显示的昵称
                type: String,
                default: '默认昵称'
            }
        },
    }
</script>

<style lang="scss" scoped>
.person {
  margin: 5px;
  display: inline-block;
  width: 110px;
  padding: 5px;
  border: 1px solid #ccc;
  text-align: center;
}
</style>

默认插槽案例:

<template>
  <div>
    <!-- 测试组件的插槽 slot 121:50 -->
    <!-- 使用my-tag时,需要给组件的插槽动态设置标签结构 -->
    <!-- 在子组件开始标签与结束标签中的内容,将会放入子组件默认插槽里 -->
   <my-tag>标签</my-tag>

    <my-tag>文本</my-tag> 
    <my-tag>
      <img src="/favicon.ico" >小图标
    </my-tag>

  </div>
</template>

<script>

import MyTag from "./components/MyTag.vue"
  export default {
    components :{
      MyTag,
      
    },
  }
</script>

<style lang="scss" scoped>

</style>
//   my tag.vue 文件
<template>
    <div class="my-tag"  :style="`background-color: ${color};`">
        <!-- 自定义组件      compons/MyTag.vue -->
        <!-- 设计一个插槽,在使用时给插槽动态赋值页面结构 -->
        <slot />
    </div>
</template>

<script>
    export default {
        props:{    //在props中声明当前组件所拥有的组件属性
                  // 在此定义一个color属性,并指定属性的默认值
                 // 该属性可能会在父组件使用当前组件时重新赋值
            color: { 
                default:'#f03d37',        //设置属性的默认值
                type:String,         //指定该属性的类型,此处指定为字符串
                require: true,        //指定该属性是否是必填项,使用时必须包含该属性;false则不是必填项目
            }
        }
    };
</script>

<style lang="scss" scoped>
 .my-tag {
    font-size: 0.9em;
    font-family: 宋体;
    margin-right: 10px;
    opacity: 0.9;
    display: inline-block;
    padding: 0px 10px;
    border: 1px solid pink;
    background-color: #ccc;
    color: wheat;
    text-align: center;
    height: 30px;
    line-height: 30px;
    border-radius: 3px;
 }
</style>

具名插槽案例:

<template>
    <div>
        <!-- 使用子组件 Layout.vue -->
        <!-- 只有在使用layout组件时,才可以确定header/main.left/main.right 到底放什么 -->
       <Layout>
            <!-- slot属性用于指定插槽名字,将当前div放入名字叫header的插槽中 -->
           <div slot="header">顶部:首页、文档、导航栏部分</div>
           <div slot="left">左边显示内容</div>
           <div slot="right">主体内容</div>
       </Layout>
    </div>
</template>

<script>
import Layout from './components/Layout.vue'
    export default {
        components :{
            Layout,
        },
    }
</script>

<style lang="scss" scoped>

</style>
// 组件Layout.vue
<template>
    <div class="layout">
        <div class="header">
        <!-- 名字叫header的插槽放在此处 -->
            <slot name="header"/> 
        </div>
        <div class="main">
            <div class="left">
            <!-- 名字叫left的插槽放在此处 -->
              <slot name="left"/> 
            </div>
            <div class="right">
                <!-- 名字叫right的插槽放在此处 --> 
               <slot name="right"/> 
            </div>
        </div>
    </div>

</template>

<script>
    export default {
        
    }
</script>

<style lang="scss" scoped>
.header {
    height: 100px;
    background-color: lightpink;
}
.main {
    display: flex;
    .left {
        width: 200px;
        height: 400px;
        background-color: cadetblue;
    }
    .right {
        flex: 1;
        height: 400px;
        background-color: darksalmon;
    }
}
</style>

 Vue脚手架中的路由系统VueRouter

多页项目的开发:一个大型网站需要由多个页面共同组成,页面之间可以相互跳转。

开发方式分两种:

       1、传统方案:每一个页面都是一个独立的 html 文件,通过超链接标签 a 来实现页面之间的跳转。 特点:先清空之前的页面内容,然后显示新页面 -- 浏览器会闪一下。

       2、.新方案:通过 Ajax 实现局部页面更新。 特点:不需要切换 html 页面(浏览器不会重新加载新的 dom 树),只需要将局部内容更新即可。

VueCli脚手架创建的项目属于新方案

专业一点称为: SPA(Single Page Application) 项目。 单页面应用。意味着 VueCli 脚手架项目无论设计多 少个页面,本质上只有一个 html 。所有的页面内容显示、跳转都将会在这唯一的一个 index.html 页面中完成。 ( public/index.html )

脚手架中路由系统相关的文件:

1. public/index.html 项目中唯一的 html 网页,提供 div#app 。

2. src/main.js 入口 js 文件,将会创建 Vue 对象,管理 div#app 。

3. src/App.vue 页面初始化加载的组件。

4. src/views/HomeView.vue 页面组件。

5. src/router/index.js 定义了 请求资源路径与组件之间的映射关系。

如何为一个页面组件配置路由地址?(访问该地址,可以看到该页面)

 

 路由配置中的懒加载与非懒加载的差异

在 router/index.js 中配置路由时,可以选择标准模式与懒加载模式配置路由:

标准模式:

对于标准模式加载组件,在 import 的时候已经将组件加载到内存中。这样的话,当 Vue 项目初始化时,就会加 载路由系统,从而引入该组件。(虽然还不需要看到这个组件,但是已经下载完毕,在内存中已经存在)

 懒加载模式:

 对于懒加载模式,使用函数的方式引入该组件,这种引入方式将会在使用的时候才会下载资源,真正做到,随用随 下载。

结论:除了首页必须加载的资源使用标准模式之外,其他都可以无脑使用懒加载。

脚手架路由运行流程

 基于路由系统完成页面跳转功能

1、基于组件方式,实现路由跳转

        <router-link to="目标地址"> 连接文本 </router-link>

例如:
        <router-link to="/about"> about页面 </router-link>
        <router-link to="/slot"> 插槽页面 </router-link>

2、编程式跳转

 this. $router.push ( ' 目标地址 ' )

 

案例:

//  App.vue 文件
<template>
    <div>
        <!-- http://localhost:8080 -->
        <router-link to="/"> 首页 </router-link>
        <router-link to="/about"> about页面 </router-link>
        <router-link to="/slot"> 插槽页面 </router-link>

        <button @click="goto('/nameslot')">跳转到具名插槽页面</button>


        <router-view></router-view>
    </div>
</template>

<script>
export default {
    methods:{
        goto(path) {     //该方法用于实现路由跳转,跳转到path路径
            // 编程式跳转
            if (this.$router.path == '/nameslot'){return;}    // 当前地址已经式 /nameslot了,不必跳转了
        }
    },
}
</script>
// index.js文件
import Vue from 'vue'
import VueRouter from 'vue-router'
import HomeView from '../views/HomeView.vue'
import  DirectorView  from '../views/person-view.vue'
import morenView from '../views/morenView.vue'
import nameslotView from '../views/nameslotView.vue';

Vue.use(VueRouter)

const routes = [
  {
    path: '/director',
    name: 'director',
    component: DirectorView
  },
  {
    path: '/slot',
    name: 'slot',
    component: morenView
  },
  {
    path: '/nameslot',
    name :'nameslot',
    component: nameslotView
  },
  {
    path: '/',
    name: 'home',
    component: HomeView
  },
  {
    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/AboutView.vue')
  },
]

const router = new VueRouter({
  mode: 'history',
  base: process.env.BASE_URL,
  routes
})

export default router

注意:出现如下问题就是重复跳转了

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Rolise-hush

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值