VUE – 6-2 VUE 脚手架

使用脚手架搭建工程

vue-cli

vue-cli集成了许多前端技术,包括但不限于:

  • webpack
  • babel
  • eslint
  • http-proxy-middleware
  • typescript
  • css pre-prosessor
  • css module
  • ...
    这些工具大部分都依赖于node环境和npm

vue-cli 使用

使用以下命令,根据提示创建即可

vue creat 项目名称

项目结构

bili-app
├─ .gitignore 
├─ babel.config.js
├─ jsconfig.json
├─ node_modules
│  └─ ...
├─ package-lock.json
├─ package.json
├─ public
│  ├─ favicon.ico
│  └─ index.html
├─ README.md
├─ src
│  ├─ App.vue
│  ├─ assets
│  │  └─ logo.png
│  ├─ components
│  │  └─ HelloWorld.vue
│  └─ main.js
└─ vue.config.js

开发

芝士

插槽

<template>
    <div class="item">
        <slot></slot>
    </div>
</template>

<item>
    <h1>Hello Bilibili</h1>
</item>

item标签中的内容会被放到slot标签处。

具名插槽

<template>
    <div class="item">
        <div class="left">
            <slot name="title"></slot>
        </div>
        <div class="right">
            <slot name="icon"></slot>
        </div>
    </div>
</template>

<item>
    <template v-slot:title>xxx</template>
    <template v-slot:icon><img src="" /></template>
</item>

动态绑定类样式

<template>
    <div class="item" :class="{active: isActive}">
        <slot></slot>
    </div>
</template>

通过给:class传入一个对象,属性名是需要动态添加的样式,属性值的truefalse影响属性名的样式是否添加,如果属性值结果为true则添加对应类样式。

<template>
    <div class="item" :class="isExpand ? 'style1' : 'style2'">
        <slot></slot>
    </div>
</template>

也可通过三目表达式

动态绑定style

<template>
    <div class="item" :style="{
        width: width + 'px',
        height: height + 'px'
    }">
        <slot></slot>
    </div>
</template>

当然也可以写一个计算属性返回一个对象:

<template>
    <div class="item" :style="style">
        <slot></slot>
    </div>
</template>

若属性名含有"-"之类的比如margin-top,将其使用引号包裹

export default {
    computed: {
        style() {
            return {
                'margin-top': '3px',
                width: width + 'px',
                height: height + 'px'
            }
        }
    }
}

约束属性

如何避免向使用组件时传入其他类型的数据,如何保证传入对应数据呢?

export default {
    props: {
        isActive: {
            type: Boolean, // 约束属性类型
            required: true, // 约束属性是否必须传递
            //default: false, // 默认值
        },
    }
};

若传入的值不是Boolean类型,将会得到以下警告:

[Vue warn]: Invalid prop: type check failed for prop "isActive". Expected Boolean, got String with value "true".

若默认值为对象,必须使用函数,函数的返回值为对象。
我们在配置data时同样使用函数,函数返回一个对象。
原因,组件可能被使用多次,若不写成函数,那么多个组件之间会共享一个对象,因此需要使用函数,数据来着函数调用,返回的不是同一个对象,保证组件之间独立。

图标库,图标组件

<template>
    <i class="iconfont" :class="iconClass"></i>
</template>

<script>
// 映射关系
let iconMap = {
    'big-left': 'icon-chevron_big_left',
    'big-right': 'icon-chevron_big_right',
    'big-up': 'icon-chevron_big_up',
    'big-down': 'icon-chevron_big_down',
    ...

};

export default {
    props: {
        type: {
            type: String,
            required: true,
        }
    },
    computed: {
        iconClass() {
            return iconMap[this.type];
        }
    }
};
</script>

<style scoped>
// 引入css
@import "//at.alicdn.com/t/c/font_4633489_dx291zwcocm.css";
</style>

使用

<icon :type="'big-right'"></icon>

问题

类样式冲突

当我们开发组件时如何防止类样式冲突

<template>
    <div class="item">item components</div>
</template>

<style scoped>
.item {
    cursor: pointer;
}

.item:hover {
    background: #f4f4f4;
}
</style>

我们给style加上一个scoped标签后,生成的元素如下

<div data-v-186c01a3 class="item">item components</div>

对应的css选择器如下

.item[data-v-186c01a3] {
    cursor: pointer;
}

会生成一个唯一的自定义属性,避免类样式冲突,借鉴于CSS module的做法。

盒子宽高如何处理

外部使用组件时可能会使用不同的宽高,针对这个问题,将组件的设置为撑满父元素

.item {
    width: 100%;
    height: 100%;
}

事件与数据

数据是父组件的,事件是子组件的,父子组件之间需要通信
子组件可以抛出事件:

export default {
    methods: {
        handleClick() {
            // 通知父组件
            // this.$emit("事件名", ...参数)
            this.$emit("active") 
        }
    }
};

父组件接收事件

<item :isActive="curActive === 'A'" @active="curActive = 'A'"> A </item>

也可以是函数,函数的参数为子组件传递的参数。

开发环境解决跨域问题

在vue.config.js中添加内容:

// vue-cli的配置文件,大部分都是webpack的配置

const { defineConfig } = require("@vue/cli-service");

// commonjs规范
// webpack在加载配置时是node.js环境,node.js环境默认支持commonjs规范
// webpack在运行打包的时候是webpack环境,webpack环境默认都支持
module.exports = defineConfig({
  transpileDependencies: true,
  devServer: {
    proxy: {
      // 配置代理
      "/x": { // 以/x开头的请求都会被代理
        target: "https://api.bilibili.com",
        changeOrigin: true,
        onProxyReq(proxyReq) {
          // 添加请求头
          proxyReq.setHeader("origin", "https://www.bilibili.com");
          proxyReq.setHeader("referer", "https://www.bilibili.com/v/channel");
        }
      }
    },
  },
});

给子组件设置样式

通常我们希望组件独立,而不受其他影响,因此不建议直接给子组件设置样式,可通过属性传递方式,将样式传递给子组件。

<template>
    <i class="iconfont" :class="[iconClass, extraClass]"></i>
</template>

<script>
let iconMap = {
    ...
};

export default {
    props: {
        type: {
            type: String,
            required: true,
        },
        extraClass: {
            type: String,
            default: "",
        }
    },
    computed: {
        iconClass() {
            return iconMap[this.type];
        }
    }
};
</script>

<style scoped>
@import "//at.alicdn.com/t/c/font_4633489_dx291zwcocm.css";
</style>

使用

<icon :type="'search'" extraClass="red"></icon>
<style scoped>
.red {
    color: red;
}
</style>
啊哈,这里是小尾巴~
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇