VUE详细版_vue ``-程序员宅基地

技术标签: webpack  VUE  vue.js  

VUE

一、概述

vue特点:
  • 渐进式框架:可以将Vue作为应用的一部分,带来更丰富的交互体验。如Core + Vue + router + Vuex
  • 解耦视图
  • 可复用的组件
  • 前端路由技术
  • 状态管理
  • 虚拟DOM

二、VUE基础

<div id="app">{
  
   {message}}</div>
<script>
	const app = new Vue({
        el: '#app',
        data:{
            message: 'Hello Vue'
        }
    })
</script>
1、vue实例的options对象
  • el

类型:string | HTMLElement , 挂载到元素

const app = new({
	el: '#app'
})
  • data

类型Object | Function (组件中必须是一个函数), Vue实例对应的数据

const app = new({
   
    
	el: '#app',
    data: {
   
    
        msg: 'hello',
        movies: ['fsd', 'dasd']
    }
})
  • methods

类型{[key:string]:Function} , 定义方法

const app = new({
	el: '#app',
    data: {
        msg: 'hello',
        movies: ['fsd', 'dasd']
    },
	methods: {
		add() {...}
		sub:function() {....}
}
})
  • computed

计算属性,使用: 需要将多个数据结合起来进行显示的时候

计算属性会进行缓存,多次使用的话只会计算一次

/* books: [
      {id: 101, name: "JS深入浅出", price: 90},
      {id: 102, name: "ES6深入浅出", price: 120},
      {id: 103, name: "Node深入浅出", price: 142},
      {id: 104, name: "C++深入浅出", price: 36},
   ]
*/ 

computed: {
   totalPrice:function () {
   let s =this.books.reduce((prev, cur) => {
          return prev + cur.price
    }, 0)
    return s
 }
}
// 显示
    <h2>{
  
   {totalPrice}}</h2>

computed存在setter和getter

一般来说不用set,因为我们要拿的是只读属性。

computed:function() {
	set:function(newValue) {
		...
	},
	get:function() {
		return this.firstName + ' ' + this.lastName
	}
}
  • filters

过滤器

/* filters:{
	 showPrice() {
		...
	}
} */
<h2>{
  
   {totalPrice | showPrice}}</h2>
2、vue指令
  • v-for

循环遍历数据

<!-- 获取数组: -->
v-for=“(value,index)”
<!-- 获取对象:-->
v-for=“(value,key,index)”

官方推荐, 使用v-for的时候, 加上一个 key属性
key的作用是为了高效的更新虚拟DOM
key要具有唯一性, 不然就没意义

<li v-for="(item, index) in names" :key="item">{
  
   {index + 1}} - {
  
   {item}}</li>
  • v-on

v-on:click=“ ”;绑定事件,简写:@click

若调用时想要获取event,则写为$event

<button v-on:click="add"></button>

v-on修饰符

修饰符 作用 实际调用
.stop 阻止事件冒泡 event.stopPropagation()
.prevent 阻止默认事件 event.preventDefault()
{keyCode I keyAlias} 监听某个键盘的键帽 -
.native 监听组件根元素的原生事件 -
.once 只触发一次回调 -
    <!-- 1. .stop的使用 -->
    <div @click="clickDiv">
        aaaa
        <button @click.stop="clickBtn">btn</button>
    </div>

    <!-- 2. .prevent的使用 -->
    <form action="baidu">
        <input type="submit" @click.prevent="submit">
    </form>

    <!-- 3. -->
    <input type="text" @keyup.enter="keyup">
  • v-once

后面不需要跟任何表达式
表示元素和组件只渲染一次, 不会随着数据的改变而变化

<h2 v-once>{
  
   {msg}}</h2>
  • v-html

后面往往跟一个string类型
会将string的html解析出来并渲染

// url: '<a href="http://www.baidu.com">baidu</a>'
<h2 v-html="url"></h2>
  • v-text

与Mustache相似, 一般不用, 不灵活

<h2 v-text="message"></h2>
  • v-pre

用于跳过这个元素和它子元素的编译过程, 用于显示原本的Mustache语法

  • v-cloak

在某些情况下, 我们浏览器可能会直接显示出未编译的Mustache标签

  • v-bind

作用: 动态绑定属性

<img v-bind:src="imgURL" alt="">

语法糖简写:

:src 、 :href

动态绑定class:

  1. 对象语法
1. <h2 v-bind:class="{类名1:bool,类名2:bool}">{
   
    {message}}</h2>
2. 实际开发中:
/* data :{
		active:'active'
		isActive:true
} */
<h2 :class="{active: isActive}"></h2>
3. 
/*  getClass() {
        return {active: this.isActive}
   }
*/
<h2 :class="getClass()">{
   
    {message}}</h2>

2)数组语法

1. <h2 v-bind:class="[类名1,类名2]">{
    
     {
    
     message}}</h2>
2.
/*  getClass() {
         return [this.isActive]
    }
    */
<h2 :class="getClass()">{
    
     {
    
     message}}</h2>

动态绑定style属性:

  1. 对象语法
<h2 :style="{fontSize: font + 'px'}"></h2>
  • v-if 、 v-else 、v-else-if

解决复用:使用key,并且key的值不一样

  • v-show

    当条件为false的时
    v-if: 指令的元素, 不会渲染到dom中
    v-show: dom增加一个行内样式display: none

  • v-model

绑定表单

v-model实现双向绑定的原理:v-bind绑定value属性和v-on绑定input事件

<div id="app">
    <input type="text" :value="message" @input="message = $event.target.value">
    {
  
   {message}}
</div>

cosnt app = new Vue({
    el: '#app',
    data: {
        message: '你好'
    }
})
v-model结合radio的使用
<div id="app">
    <label for="male">
        <inout type="radio" id="male" value="男" v-model="sex"></label>
    <label for="male">
        <inout type="radio" id="female" value="女" v-model="sex">nv
    </label>
    <h2>您选择的性别是: {
   
    {
   
    sex}}</h2>
</div>

cosnt app = new Vue({
   
    
    el: '#app',
    data: {
   
    
        sex: '男'
    }
})
v-model结合checkbox的使用
  • 单选框
<div id="app">
    <label for="agree">
        <input type="checkbox" id="agree" v-model="isAgree">同意协议
    </label>
    <button :disabled="!isAgree">下一步</button>
</div>

    const app = new Vue({
        el: '#app',
        data: {
            isAgree: false
        })
  • 多选框
 <input type="checkbox" value="篮球" v-model="hobbies">篮球
 <input type="checkbox" value="乒乓球" v-model="hobbies">乒乓球
 <input type="checkbox" value="羽毛球球" v-model="hobbies">羽毛球球
 <input type="checkbox" value="足球" v-model="hobbies">足球

const app = new Vue({
        el: '#app',
        data: {
            hobbies: []
        })
v-model结合select使用
  • 下拉框单选

v-model绑定的是一个值
当选中option中一个时, 会将它对应的value赋值到mySelect中

<select v-model="mySelect">
    <option value="apple">苹果<option>
    <option value="orange">橘子<option>
    <option value="banana">香蕉<option>
</select>
<p>您最喜欢的水果: {
  
   {mySelect}}</p>
  • 下拉框多选

v-model绑定的是一个数组
当选择多个值时,会将选中的option对应的value添加到数组mySelect中

<select v-model="mySelect" multiple>
    <option value="apple">苹果<option>
    <option value="orange">橘子<option>
    <option value="banana">香蕉<option>
</select>
<p>您最喜欢的水果: {
  
   {mySelect}}</p>
值绑定(推荐)

含义: 动态的给value赋值
1 在前面的value中的值, 都是在定义input的时候直接给定的
2 但真实开发中, input的值可能是从网络获取或定义在data中的
3 可以通过v-bind:value动态的给value绑定值

   <label v-for="item in originFruits" :for="item">
        <input type="checkbox" :value="item" :id="item" v-model="checkFruits">{
  
   {item}}
    </label>

  const app = new Vue({
        el: '#app',
        data: {
            originFruits: ["苹果", "香蕉", "橘子", "榴莲", "荔枝"],
            checkFruits: []
        })
修饰符
  • lazy修饰符

前景: v-model默认是在input事件中实时同步输入框的数据的 (容易同步的过于频繁 )
作用: 可以让数据只有在失去焦点或回车时才会更新

<input type="text" v-model.lazy="输入">
  • number修饰符

前景: 默认情况下, 在输入框中无论输入字母还是数字, 都会被当做字符串类型进行处理
作用: 当做数字类型进行处理

  • trim修饰符

前景: 输入的内容首位容易有空格
作用: 可以过滤掉内容左右两边的空格

3.、MVVM

Model View View Model

在这里插入图片描述

M: Model 数据模型

数据层
数据可能是固定的思数据, 更多的是来自服务器, 从网络上请求下来的数据

V: View 视图模板

视觉层
在前端开发中, 通常是DOM层
作用: 是给用户展示各种信息

VM: View-Model 视图模型

视图模型层
是View和Model沟通的桥梁
一方面实现了Data Binding (数据绑定), 讲Model的改变实时的反应到View中
另一方面实现了DOM Listener (DOM监听), 当DOM发生一些时间 (点击, 滚动, touch等) 时, 可以监听到, 并在需要的情况下改变对应的Data

4、Vue的生命周期

在这里插入图片描述

5、插值操作-mustache语法
mustache语法可以进行运算
  • Mustache语法 (双大括号)
  • 可以直接写变量
  • 可以写简单的表达式
<h2>{
  
   {firstName + ' ' + lastName}}</h2>
<h2>{
  
   {firstName}} {
  
   {lastName}}</h2>
<h2>{
  
   {counter * 2}}</h2>

三、组件化开发

组件的使用三步骤:
1. 创建组件构造器

调用Vue.extend( ) 方法

2. 注册组件(全局注册、局部注册)

Vue.component( ) 方法

Vue.component(‘组件标签名’,组件构造器)

3. 使用组件

在Vue实例的作用范围内使用

<组件名></组件名>

<!-- 3. 组件的使用 -->
<div id="app">
    <my-cpn></my-cpn>
</div>

<script>
	// 1. 创建组件构造器对象
    const cpnConstructor = Vue.extend({
        template: `
            <div>
                <h2>我是标题</h2>
                <p>我是内容,哈哈哈哈</p>
            </div>`
    })
    // 2. 注册组件
    // Vue.component('组件标签名',组件构造器)
    Vue.component('my-cpn',cpnConstructor)
</script>

创建组件构造器时有语法糖:

Vue为了简化注册组件的过程, 提供了注册的语法塘, 省去了调用Vue.extend()的步骤. 而是可以直接使用一个对象来代替

// 全局组件
Vue.component('xxx', {
    template: '
    <div>
        哈哈哈哈
    </div>
    '
})

// 内部会自动调用Vue.extend()


// 局部组件
const app = new Vue({
    el: '#app',
    data: {
        meassage: '哈哈哈'
    },
    components: {
        'cpn': {
            template: '
                <div>
                    哈哈哈哈
                </div>
            '
        }
    }
})

全局组件和局部组件

  • 全局组件(意味着可以在多个vue实例中使用)
上述代码
  • 局部组件(用的最多)

    在vue实例的options里面添加一个components

    components: {

    ​ 标签名:构造器名

    }

    <div id="app">
        <cpn></cpn>
    </div>
    
    const cpnC = Vue.extend({
            template: `
                <div>
                    <h2>Hello World</h2>
                </div>
            `
        })
    
    const app = new Vue({
            el: '#app',
            data: {
    
            },
            components: {
                // cpn使用组件时的标签名, cpnC是组件构造器
                cpn: cpnC
            }
    	})
    

父与子组件

在父组件中注册组件并使用组件

<!-- 子组件 -->
const cpnC1 = Vue.extend({
        template: `
            <div>
                <h2>我是标题</h2>
                <p>我是内容,哈哈哈哈</p>
            </div>
        `
    })

<!-- 父组件 -->
const cpnC2 = Vue.extend({
        template: `
            <div>
                <h2>我是标题2</h2>
                <!-- 父组件中使用 -->
                <cpn1></cpn1>
                <p>我是内容,呵呵呵呵</p>
            </div>
        `,
		<!-- 父组件中注册 -->
        components: {
            cpn1: cpnC1
        }
    })

父子组件的错误用法: 以子标签的形式在Vue实例中使用

  1. 因为当子组件注册到父组件的components时, Vue会编译好父组件的模块
  2. 该模块的内容已经决定了父组件将要渲染的HTML (相当于父组件中已经有子组件中的内容了)
父传子通信props
  • 写法一:数组方式(不推荐)
<div id="app">
  <cpn :books1="books"></cpn>
</div>

<template id="cpn1">
    <div>
        <h2>这是标题</h2>
        <h3>{
  
   {books1[0]}}</h3>
    </div>
</template>

const cpn = Vue.extend({
        template: '#cpn1',
        props: ['books1']
    })

    const app = new Vue({
        el: '#app',
        data: {
            books:["钢铁是怎样炼成的", "朝花夕拾", "su"]
        },
        components: {
            cpn
        }
    })
  • 写法二
<div id="app">
    // 在使用组件的时候绑定
    // 不支持驼峰命名  cMovies要写成c-movies
    <cpm :c-movies="movies" :c-message="message"></cpn>
</div>

<template id="cpn">
    <div>
        <li v-for="item in cMovies">{
  
   {item}}</li>
        <h2>{
  
   {cMessage}}</h2>
    </div>
</template>


const cpn = {
    template: '#cpn',
    // 把数组里的当变量来看了
    props: {
        // 类型限制 
        // cMovies: Array,
        // cMeesage: String,
        
        // 类型限制 + 提供一些默认值 or  required表示必传值,不然报错
        cMessage: {
            type: String,
            default: '哈',
            required: true
        },  
        cMovies: {
            type: Array, // 对象or数组类型的时候, 默认值必须是个函数
            default() {
                return {}
            }
        }
    }
    data () {
        return {}
    }
}

const app = new Vue({
    el: '#app',
    data: {
        meassage: '哈哈哈',
        movies: ['哈喽', '嗨', '哟哟']
    },
    components: {
        cpn
    }
})
子传父自定义事件

this.$emit 发射事件

// 父组件模板
<div id="app">
    // 2.父组件监听一个事件
    // 不能写驼峰
    <cpm @itemclick="cpnClick"></cpn>
</div>

// 子组件模板
<template id="cpn">
    <div>
        <button v-for="item in categories" 
                @click="btnClick(item)">
            {
  
   {item.name}}
        </button>
    </div>
</template>


// 子组件
const cpn = {
    template: '#cpn',
    data() {
        return {
            categories: [
                {id: 'aaaa', name: '热门推荐'},
                {id: 'bbbb', name: '手机数码'},
                {id: 'cccc', name: '家用家电'},
                {id: 'dddd', name: '电脑办公'},
            ]
        }
    },
    methods: {
        btnClick(item) {
            // 要把item传给父组件
            // 1. 发送一个事件 (自定义事件)
            // 会把item当成默认的传到父组件去
            this.$emit('itemclick', item)
        ]
    }
}

// 父组件
const app = new Vue({
    el: '#app',
    data: {
        meassage: '哈哈哈'
    },
    components: {
        cpn
    },
    methods: {
        // 3. 父组件监听的事件 
        cpnClick(item) {
            console.log('成功了', item);
        }
    }
父子组件通信-双向绑定
<div id="app">
    <cpn :number1="num1" :number2="num2" @num1change="num1change"></cpn>
</div>

<template id="cpn">
    <div>
        <h2>{
  
   {number1}}</h2>
        <input type="text" :value="dnumber1" @input="numqInput">
        <h2>{
  
   {dnumber1}}</h2>
    </div>
</template>

const app = new Vue({
        el: '#app',
        data: {
            num1: 1,
            num2: 0
        },
        methods: {
            num1change(value) {
                this.num1 = parseInt(value)
            }
        },
        components: {
            cpn: {
                template: '#cpn',
                props: {
                    number1: Number,
                    number2: Number
                },
                data() {
                    return {
                        dnumber1: this.number1,
                        dnumber2: this.number2
                    }
                },
                methods: {
                    numqInput(event) {
                        this.dnumber1 = event.target.value
                        this.$emit('num1change', this.dnumber1)
                    }
                }
            }
        }
    })

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rUOOskdz-1630630927158)(C:\Users\HeJingWang\Desktop\秋招准备\vue\无标题.png)]

可以通过watch监听,watch和data并列

watch(newValue, oldValue) {
   
    
    ...
}
父访问子
  • $children: 拿所有子组件
  • $refs: 拿指定的子组件
<div id="app">
    // 必须加一个 ref="名字"
    <cpn ref="aaa"></cpn>
    <button @click="btnClick">按钮</button>
</div>

const app = new Vue({
        el: '#app',
        data: {
            message: '你好呀'
        },
        methods: {
            btnClick() {
                // 1. 通过$children 调用了showMessage方法
                this.$children[0].showMessage()
                // 2. 使用$refs(推荐) => 默认是一个空对象
             	this.$refs.aaa.showMessage()
            }
        },
        components: {
            cpn: {
                template: '#cpn',
                methods: {
                    showMessage() {
                        console.log('showMessage')
                    }
                }
            }
        }
    })
子访问父
  • $parent: 上一级父组件
  • $root: 根组件
<div id="app">
    <cpm></cpn>
</div>

<template id="cpn">
    <div>
        <ccpn></ccpn>
    </div>
</template>

<template id="ccpn">
    <div>
        <h2>我是子组件</h2>
        <button @click="btnClick">按钮</button>
    </div>
</template>

const app = new Vue({
    el: '#app',
    data: {
        meassage: '哈哈哈'
    },

    components: {
        cpn: {
            template: "#cpn",
            data() {
               return {
                   name: '我是cpn的name'
               } 
            },
            conmponents: {
                ccpn: {
                    template: '#ccpn',
                    btnClick() {
                        // 1. 访问父组件$parent
                        // 不建议这么写, 一层套一层 复用性太差
                        console.log(this.$parent);  
                        console.log(this.$parent.name);  // 我是cpn的name
                        
                        // 2. 访问根组件 $root
                        console.log(this.$root.meassage);   // 哈哈哈
                    } 
                }
            }
        }
    }
})

插槽slot

组件的插槽为了让封装的组件更加具有扩展性。

抽取共性,保留不同。

基本使用
  1. 插槽的基本使用
  2. 插槽的默认值 button 按钮
  3. 如果有多个值同时放入到组件进行替换时, 一起作为替换元素
<div id="app">
    <!-- 使用默认值替换 -->
    <cpn></cpn>
    <!-- 插槽替换的元素 -->
    <cpn><span>这是替换的内容呀</span></cpn>
    <!-- 多个元素 -->
    <cpn>
        <div>第一个元素</div>
        <p>第二个元素</p>
    </cpn>
</div>

<template id="cpn">
    <div>
        <div>这个是标题</div>
        <p>这个是内容</p>
        <!-- 放入插槽 -->
        <slot>默认值元素</slot>
    </div>
</template>

const app = new Vue({
    el: '#app',
    data: {
        meassage: '哈哈哈'
    },
    components: {
        cpn: {
            template: '#cpn'
        }
    }
})
具名插槽

在多个插槽的情况下, 替换制定插槽的内容

<div id="app">
    <cpn><span slot="center">sususu</span></cpn>
</div>

<template id="cpn">
    <div>
       <h2>我是组件</h2>
        <slot name="left"><span>left</span></slot>
        <slot name="center"><span>center</span></slot>
        <slot name="right"><span>right</span></slot>
    </div>

</template>
作用域插槽

父组件替换插槽的标签,但是内容由子组件来提供。

需求: 
1. 子组件中包括一组数据, num: ['1', '2', '3', '4', '5']
2. 需要在多个界面展示 
   某些界面是以水平方向展示
   某些界面是以列表形式展示
   某些界面直接展示一个数组 
3. 内容在子组件, 希望父组件告诉我们如何展示, 怎么办?
   利用slot作用域插槽就行了
   
<div id="app">
    <cpm></cpn> 
    <cpm>
        // 2. 获取子组件中的num
        <template slot-scope="slot">
            // 根据之前的起名来取  如 slot.aaa
            <span  v-for="item in slot.data">{
  
   {item}}</span>
        </template>
    </cpn> 
    <cpm></cpn> 
</div>

<template id="cpn">
    <div>
        // 1. slot定义  'data'可以随便起名 如 :aaa="num"
        <slot :data="num">
            <ul>
                <li v-for="item in num">{
  
   {item}}</li>
            </ul>
        </slot>
    </div>
</template>

const app = new Vue({
    el: '#app',
    data: {
        message: '哈哈哈'
    },
    components: {
        cpn: {
            template: '#cpn',
            data() {
                return {
                    num: ['1', '2', '3', '4', '5']
                }
            }
        }
    }
})

四、模块化

常见的模块化规范:CommonJS、AMD、CMD、ES6里的Modules

CommonJS:
   // 导出
   module.exports = {
   
    
       flag: true,
       test(a, b) {
   
    
           return a + b
       }
   }
   // 导入
   let {
   
    flag, test} = require('./aaa.js')
   let _ma = require('./aaa.js')
   let flage = _ma.flag
ES6模块化:

exportimport

注意:script标签内需要设置属性

// 导出
<script type="Module">
    let flag = true
	function sum(num1, num2) {
   
    
        return num1 + num2
    }
	// 方式一
    export {
   
    flag, sum}
    // 方式二
    export let height = 1.88
    // 方式三
    export function  sum(num1, num2) {
   
    
       return num1 + num2
    }
	// export defaule(只能有一个,导入者自己命名)
	const address = '北京市'
    export address
    // 此时的导入
    import add from '../add.js'
</script>

// 导入
<script>
    import {
   
    flag} from './aaa.js'
	// 统一全部导入
	import * as aaa from './aaa.js'
</script>

五、webpack

概述

webpack是一个静态模块化打包工具。

webpack依赖于node.js,node自带了软件包管理工具。

和grunt/glup对比

grunt/glup核心是task, 如果工程模块化简单,则使用进行简单的合并、压缩。

grunt/gulp更强调的是前端流程的自动化,模块化不是它的核心。

webpack更加强调模块化开发管理,而文件压缩合并、预处理等功能,是他附带的功能。

webpack安装

node版本:10.13.0

  • webpack全局安装和卸载

webpak安装:npm install [email protected] -g

webpack卸载:npm uninstall webpack -g

  • webpack局部安装
npm install webpack@3.6.0 --save-dev

–save-dev 是开发时依赖,项目打包后不需要继续使用。

webpack使用

webpack ./src/main.js ./dist/bundle.js
  • 创建文件目录,src 和 dist,打包后的文件放在dist文件夹内
  • 使用模块化导入导出,最后的html文件只需要引入dist文件夹内打包好的就可。

webpack配置

  1. 创建webpack.config.js文件
// 为了动态获取打包后的路径, path 在node包里面 -- 看下面一段代码 装包
const path = require('path')

moudle.exports = {
   
    
    // 入口和出口
    entry: './src/main.js',
    output: {
   
    
        // path:动态获取路径
        path: path.resolve(__dirname, 'dist'),
        filename: 'bundle.js'
    }
}
  1. node包
// 初始化--生成
npm init

// 生成的文件可能有中文 / 符号  可以改名 
meetwebpack 

... 后面全部回车, 一路通过. OK就行  
... 生成 package.json文件

// package.json文件里面也有依赖的文件  

在这里插入图片描述在这里插入图片描述

  1. package.json文件
"version" -- 版本号  

// 本地安装webpack (之前是全局安装)  -- 开发时依赖  运行时依赖
npm install webpack@3.6.0 --save-dev

// 开发时依赖 (本地安装webpack后, 重新打开package.json文件会出现)
"devDependencies": {
   
      
    "webpack": "^3.6.0"  
}

// 使用vue之后, 会有 (运行时依赖)
"dependencise": {
   
    
    "webpack": "^3.6.0"  
}

---

// 执行脚本的配置
"scripts": {
   
    
    "test": '',    
    "build": "webpack" 
}

npm run test
npm run build	// 执行本地的webpack

CSS Less Img ES6转Es5 Vue 处理

loader使用过程:

  1. 使用npm安装
  2. 在webpack.config.js中的module关键字下进行配置
  • CSS的loader

main.js

// 1. 使用commonjs的模块化规范  
const {
   
    add, mul} = require('./js/mathUtils.js')

// 2. 使用ES6的模块化的规范 
import {
   
    name, age} from "./js/info"

// 3. 依赖CSS文件  
require('./css/normal.css')

终端安装css-loader

npm install css-loader@2.0.2 --save-dev

webpack.config.js

const path = require('path')

module.exports = {
   
    
    // 入口和出口
    entry: './src/main.js',
    output: {
   
    
        // path:动态获取路径
        path: path.resolve(__dirname, 'dist'),
        filename: 'bundle.js'
    },
    // 添加如下内容
    module: {
   
    
        rules: [
            {
   
    
                test: /\.css$/,
                // css-loader只复制加载不负责解析
                use: [ 'css-loader' ]
            }
        ]
    }
}

然后再次打包!发现还是没有背景,因为css-loader只复制加载不负责解析

再次去官方安装style-loader

npm install style-loader@0.23.1 --save-dev

然后在刚才添加的module里面添加

    module: {
   
    
        rules: [
            {
   
    
                test: /\.css$/,
                // style-loader负责将样式添加到DOM中
                // 这里添加,使用多个loader时,是从右向左
                use: [ 'style-loader','css-loader' ]
            }
        ]
    }
  • less文件处理

main.js

// 1. 使用commonjs的模块化规范  
const {
   
    add
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/weixin_47777489/article/details/120073972

智能推荐

jquery实现截取pc图片_jquery 图片截取工具jquery.imagecropper.js-程序员宅基地

文章浏览阅读341次。除了jquery,本插件还引用了UI库,包括ui.draggable.jsImageCropper 演示需要asp.net支持。测试通过ImageCropper 下载 https://www.jb51.net/jiaoben/25688.html插件用法:var imageCropper = $('#imgBackground').imageCropper();要注意的是此插件只应用在有src属性..._jquery image crop shield

ucl介绍_交换机的ucl是什么东西-程序员宅基地

文章浏览阅读1.4k次。目录1、概述2、global configuration3、update command list3.1、UCL的格式:3.2、host commands3.3、firmware commands3.4、条件执行3.5、使用变量1、概述UCL是Update Command List的简称。从《mfgtools工作流程概述》这个文章中知道对目标单板的具体烧写过..._交换机的ucl是什么东西

idea html设置字体大小,intellij idea设置(字体大小、背景)-程序员宅基地

文章浏览阅读1.8k次。1. 配置信息说明Intellij Idea: 2017.2.52.具体设置<1> 设置主题背景、字体大小File---->Settings----->Appearance & Behavior------>Appearance,主题背景:Theme: Darcula,Intellij,Windows主题字体大小:Override default fonts ..._idea的html标签字体大小

【目标检测】RCNN算法详解_rcnn算法思想-程序员宅基地

文章浏览阅读2.3k次。reference link:https://blog.csdn.net/u011534057/article/details/51218250一、相关理论&amp;nbsp; &amp;nbsp;本篇博文主要讲解2014年CVPR上的经典paper:《Rich feature hierarchies&amp;nbsp;for&amp;nbsp;Accurate Object Detection and Segmentat..._rcnn算法思想

金陵科技学院专转本计算机书,2021金陵科技学院五年一贯制专转本计算机科学与技术考试大纲(最新)...-程序员宅基地

文章浏览阅读766次。2021年金陵科技学院五年一贯制专转本计算机科学与技术专业考试内容包括《计算机网络基础》和《计算机应用基础》两部分,具体考试大纲如下《计算机网络基础》考试大纲一、参考书目:《计算机网络技术与应用(第2版)》,段标、张玲主编,电子工业出版社.二、考试形式:闭卷,考试时间90分钟三、考试内容和要求(一)考试要求1.计算机网络理论知识● 掌握计算机网络的定义、计算机网络的组成、功能与应用● 掌握计算机网..._计算机科学与技术转本那两本专业书

ShellExecute失败,返回ERROR_NO_ASSOCIATION(1155)的处理方案_shellexecute 1155-程序员宅基地

文章浏览阅读2.6k次,点赞2次,收藏2次。DWORD TryShellWithParam(CString strParam){ DWORD dwErrorOld = GetLastError(), dwErrorNew = ERROR_SUCCESS; if (ERROR_SUCCESS != dwErrorOld) { if (ERROR_NO_ASSOCIATION == dwErrorOld) { ShellExe..._shellexecute 1155

随便推点

华为鸿蒙osbeta用户体验,华为Mate40鸿蒙OS手机Beta版-程序员宅基地

文章浏览阅读184次。华为Mate40鸿蒙OS手机Beta版现在华为手机系统最新升级的一个版本,相信很多用户这几天已经尝试到了最新的系统操作,感受非常的智能和特别和以往的各种系统来说,更加具有智能性,而且操作起来也更加的流畅,在很多小细节方面上也进行了优化,处处都充满了惊喜,让整个华为手机操作起来,更加具有娱乐性。华为Mate40鸿蒙OS手机Beta版特色:1、华为全新推出的一个专属系统,会与人们常用的安卓系统存在很大..._华为 mate40 退出系统beta

kafka分区及副本在broker的分配_topic 分区分配 brokearray-程序员宅基地

文章浏览阅读2.1k次。转自:https://blog.csdn.net/jediael_lu/article/details/77097361 kafka分区及副本在broker的分配@(KAFKA)[kafka, 大数据]部分内容参考自:http://blog.csdn.net/lizhitao/article/details/41778193下面以一个Kafka集群中4个Broker举例,创建1个t..._topic 分区分配 brokearray

虚拟机安装VMwareTools_vmware tools iso-程序员宅基地

文章浏览阅读1k次。在VMware虚拟机中安装VMwareTools_vmware tools iso

〖产品思维训练白宝书 - 核心竞争力篇⑥〗- 产品经理核心竞争力解读之执行力_产品经理执行能力定义-程序员宅基地

文章浏览阅读2.9w次,点赞15次,收藏9次。该章节的内容是针对 "产品经理" 的 "执行力" 进行讲解,"执行力" 作为 "初级产品经理" 的必备技能,看起来似乎很容易,只要把领导交代的任务完成就可以了,其实不然。真的想执行的顺利、执行的到位,肯定是要花一番功夫的。所以这一章节,就为各位小伙伴讲解一下 "执行力" 的概念、意义以及 "产品经理" 在 "执行力" 上的执行动作对于我们普通人而言都有哪些参考价值。_产品经理执行能力定义

llinux简单部署一下_llinux 部署简单的策略-程序员宅基地

文章浏览阅读143次。Linux下的简单开发环境部署一.安装JDK8①下载解压方式②yum安装方式二.Mysql①下载解压方式②Yum安装方式一.安装JDK8安装之前首先需要进行检查一下系统里,看是否有已经有的open-jdk命令为:rpm -qa |grep javarpm -qa |grep jdkrpm -qa |grep gcj若已经有安装的,进行批量卸载;rpm -qa | grep java | xargs rpm -e --nodeps①下载解压方式下载jdk8登录网址:http://www.o_llinux 部署简单的策略

去掉所有字符里面的空格换行符等_kotlin 将换行符替换成空-程序员宅基地

文章浏览阅读3.3k次。有时候需要去掉字符串中的所有的字符空格,或者其他空格换行等,string里面的trim方法只能去掉字符串中前后的 空格,去不掉里面的,这么一来可就恶心了,上次用到了一个挺不错的,(网上查到的)其实就是利用的是简单的正则去掉匹配所有一致的字符替换为一个没有空格的空字符串,废话就到这里了,下边才是最重要的 /* String str = trim.replaceAll("\\s*", _kotlin 将换行符替换成空

推荐文章

热门文章

相关标签