Vue2之webpack篇(二)Loader
回顾上一篇文章的例子,我们使用webpack来处理我们写的js代码,并且了解webpack会自动处理js之间相关的依赖
在实际项目中不仅仅有js文件,还有css、图片,ES6转化ES5,TypeScript转化ES5代码,将less,scss转化css,将jsx,vue文件转化js文件等
对于webpack本身来说是不具备这些转化功能的,这时候必须使用对应的loader进行处理
一、loader处理css
1、css文件的创建
(1)在工程下创建一个css文件夹==》创建一个index.css文件
body{ background-color: skyblue; }
(2)在main.js文件中引入index.css文件
import indexCss from './css/index.css'
(3)在项目终端进行webpack打包
此时报错提醒,需要我们下载引用css的loader
2、安装css-loader
(1)css-loader@5:5是版本号
npm install --save-dev css-loader@5
(2)通过查看package.json文件,是否安装成功
3、配置
(1)在webpack.config.js文件配置【module】
module.exports = { module: { rules: [ { test: /\.css$/i, use: ["style-loader", "css-loader"], }, ], }, };
(2)小伙伴们可以通过文档,参考操作步骤
4、打包
(1)在项目终端输入webpack
此时发现又报错了,是因为
(2)安装style-loader
npm install --save-dev style-loader@2
(3)再重新webpack
5、最终效果
回到class.html界面启动,会看到index.css渲染的body背景skyblue成功
二、loader处理图片
1、引入图片
(1)创建文件夹image==》引入一张本地图片1.jpg
(2)将index.css修改,注意路径
body{ background-image: url('../image/1.jpg'); }
(3)此时webpack打包一样开始报错
告诉我们需要处理图片的loader,即file-loader
2、安装file-loader
项目终端输入如下代码:
npm install --save-dev file-loader@4
3、配置module
module: { rules: [ { test: /\.css$/i, use: ["style-loader", "css-loader"], }, // 处理css中图片的使用 { test: /\.(png|jpg|git)$/, /* 数组对象形式 */ use: [ { // 使用file loader,解析文件路径 loader: "file-loader", }, ], }, ], },
4、webpack打包
(1)此时又出现了问题,图片无法正常显示,是因为打包后的图片路径问题,因此还要再配置
module: { rules: [ { test: /\.css$/i, use: ["style-loader", "css-loader"], }, // 处理css中图片的使用 { test: /\.(png|jpg|git)$/, /* 数组对象形式 */ use: [ { // 使用file loader,解析文件路径 loader: "file-loader", // 配置 options: { // 指定html中引用图片的相对html文件的路径 publicPath: "./dist/", // 指定文件名,一般会放在一个img相关的文件夹中 name: "imgs/[contenthash].[ext]", }, }, ], }, ], },
注意配置的dist路径
(2)再webpack打包,就成功显示了
三、ES6转ES5
1、介绍
(1)当检查打包后的文件有es6代码,有的浏览器还不支持es6,所以有时候需要将es6的代码转化成es5
(2)例子:定时器箭头函数
①在main.js文件中设置一个定时器
setTimeout(()=>{ console.log(0); },1000)
②终端webpack打包,页面控制台会延迟一秒钟打印0
(3)此时去到项目的dist文件夹下的bundle.js文件,找到我们写的箭头函数
可见此时打包后代码是按照es6来写,如果要将其按照es5来写,需要babel-loader
2、安装babel-loader
npm install @babel/core@7 @babel/preset-env@7 babel-loader@8 babel-preset-env
3、webpack.config.js配置
// 处理es6 { test: /\.js$/, // 除去node_modules文件夹,避免项目依赖包和插件被更改 exclude: /(node_modules)/, use: { loader: 'babel-loader', options: { presets: ['@babel/preset-env'] } } }
4、webpack打包
一样可以正常显示,此时观察dist文件夹下的bundle.js文件
打包完的代码,已经将我们写的es6语法转为es5语法
四、打包Vue
1、下载vue
npm i vue@2
2、引入、使用vue
(1)页面显示msg属性的值,即我是vue
main.js文件
// vue import Vue from "vue"; // new一个vue实例 new Vue({ el:'#app',//对class.html文件有id="app"属性值标签的挂载 data:{ msg:'我是vue' } })
class.html文件
<body> <div id="app">{{msg}}</div> </body>
但是发现msg的值并未正常显示,因此要配置vue
(2)webpack.config.js配置resolve
resolve: { alias: { // 指定使用vue包中的版本 'vue$': 'vue/dist/vue.esm.js' } }
(3)class.html文件的js引入放到标签下面
因为代码运行顺序是从上往下,如果vue实例在标签之前运行,vue实例是找不到绑定id='app'的标签
<body> <div id="app"><h1>{{msg}}</h1></div> <script src="./dist/bundle.js"></script> </body>
(4)webpack打包
五、分离vue
1、分离过程
(1)局部组件的语法糖
new Vue({ el:'#app', template:'<App></App>', components:{ App:{ template:'<h1>{{msg}}</h1>', data(){ return { msg:'我是vue' } } } } })
(2)组件单独出来
const App = { template:'<h1>{{msg}}</h1>', data(){ return { msg:'我是vue' } } } // new一个vue实例 new Vue({ el:'#app',//对class.html文件有id="app"属性值标签的挂载 template:'<App></App>', components:{ App,//增强写法 } })
(3)将组件对象单独写一个App.js文件
main.js文件
import Vue from "vue"; import App from "./App.js" new Vue({ el:'#app',//对class.html文件有id="app"属性值标签的挂载 template:'<App></App>', components:{ App, } })
App.js
export default { template: "<h1>{{msg}}</h1>", data() { return { msg: "我是vue", }; }, };
(4)再分离,将template内容单独分离,引入一个vue文件写
main.js
import Vue from "vue"; import App from "./App.vue" new Vue({ el:'#app', template:'<App></App>', components:{ App, } })
App.vue
<template> <div> <h1>{{msg}}</h1> </div> </template> <script> export default{ data() { return { msg: "我是vue", }; }, } </script>
①webpack打包,此时又开始报错,是因为没有loader处理.vue这种文件类型
②安装vue-loader,终端分别输入下面两个代码
npm i vue-loader@14
npm i vue-template-compiler
③webpack.config.js文件配置modle
// .vue 相关的loader { test: /\.vue$/, use: ['vue-loader'], },
④webpack打包即可
2、设置vue子组件
(1)创建文件夹view==》创建文件login.vue
<template> <div> <div class="box"></div> </div> </template> <script> export default { data(){ return{} } }; </script> <style scoped> /* scoped表示设置的css样式仅适用于当前.vue文件 */ .box{ width: 100px; height: 100px; background-color: red; } </style>
(2)在App父组件注册login子组件,并在页面显示
<template> <div> <h1>{{msg}}</h1> <!-- 子组件login的使用 --> <login></login> </div> </template> <script> import login from "./view/login.vue" export default{ data() { return { msg: "我是vue", }; }, components:{//注册 login }, } </script>
(3)webpack打包
3、父、子组件传参
(1)父组件向子组件传递点击的城市
App.vue文件
<template> <div> <h1>{{msg}}</h1> <ul> <li v-for="item in cityArr" :key="item" @click="cityClick(item)"> <h1>{{ item }}</h1> </li> </ul> <login :cityName="selectCity"></login> </div> </template> <script> import login from "./view/login.vue" export default{ data() { return { msg: "我是vue", cityArr:['重庆','天津','上海','北京'], selectCity:null, }; }, methods:{ cityClick(item){ console.log(item); this.selectCity = item } }, components:{ login }, } </script>
login.vue文件
<template> <div> <div class="box"> <h3>{{ cityName }}</h3> </div> </div> </template> <script> export default { data(){ return{} }, props:{ cityName:{ type:String, default(){ return '默认' } } }, }; </script> <style scoped> /* scoped表示设置的css样式仅适用于当前.vue文件 */ .box{ width: 100px; height: 100px; background-color: red; } </style>
(2)子组件向父组件传递信息
App.vue
<template> <div> <h1>{{msg}}</h1> <ul> <li v-for="item in cityArr" :key="item" @click="cityClick(item)"> <h1>{{ item }}</h1> </li> </ul> <login :cityName="selectCity" @login-btn="btnClick"></login> </div> </template> <script> import login from "./view/login.vue" export default{ data() { return { msg: "我是vue", cityArr:['重庆','天津','上海','北京'], selectCity:null, }; }, methods:{ cityClick(item){ console.log(item); this.selectCity = item }, btnClick(msg){ alert(msg) } }, components:{ login }, } </script>
login.vue
<template> <div> <div class="box"> <h3>{{ cityName }}</h3> <button @click="btnClick">点击</button> </div> </div> </template> <script> export default { data(){ return{ msg:'我是子组件' } }, methods:{ btnClick(){ this.$emit('login-btn',this.msg) } }, props:{ cityName:{ type:String, default(){ return '默认' } } }, }; </script> <style scoped> /* scoped表示设置的css样式仅适用于当前.vue文件 */ .box{ width: 100px; height: 100px; background-color: red; } </style>
(3)父子传参详细步骤的学习,小伙伴们可以参考小编下面的文章
#学习##前端##vue#