【Vue学习】基础语法(五)

九.组件化高级

1.插槽slot
  • 作用:让封装的组件更加具有扩展性,使用者可以决定组件内部的一些展示内容。
1.1 插槽的基本使用
  • 可设置默认值button
  • 如果有多个值,同时放入到组件进行替换时,会将其一起作为替换元素。
<div id="app">
    <cpn></cpn>   
    <cpn><span>哈哈哈</span></cpn>   
    <cpn><i>hehehe</i></cpn>   
</div>

<template id="cpn">
    <div>
        <h2>我是组件</h2>
        <p>-----</p>
        <!-- 插槽,预留位置,可设置默认值 -->
        <!-- <slot></slot> -->
        <slot><button>按钮</button></slot>
    </div>
</template>

<script src="../js/vue.js"></script>
<script>
    const app = new Vue({
        el: '#app',
        data: {
            message : '你好啊',
        },
        components: {
            cpn: {
                template: '#cpn',
            }
        }
    })
</script>
1.2 具名插槽的使用
  • 给slot元素一个name属性即可
<div id="app">
	<!-- 仅覆盖某一个插槽 -->
    <cpn><span slot="center">标题</span></cpn>    
</div>

<template id="cpn">
    <div>
        <!-- 设置name可控制某一个插槽 -->
        <slot name="left"><span></span></slot>
        <slot name="center"><span></span></slot>
        <slot name="right"><span></span></slot>
    </div>
</template>

<script src="../js/vue.js"></script>
<script>
    const app = new Vue({
        el: '#app',
        data: {
            message : '你好啊',
        },
        components: {
            cpn: {
                template: '#cpn',
            }
        }
    })
</script>
1.3 编译作用域
  • 父组件模板的所有东西都会在父级作用域内编译;子组件模板的所有东西都会在自己作用域内编译。
<div id="app">
    <!-- 此时isShow为true,作用域为Vue实例内,可渲染 -->
    <cpn v-show="isShow"></cpn>
</div>

<template id="cpn">
    <div>
        <h2>我是子组件</h2>
        <p>hahhahah</p>
        <!-- 此时isShow为false,作用域为该组件内,不可渲染 -->
        <button v-show="isShow"></button>
    </div>
</template>

<script src="../js/vue.js"></script>
<script>
    const app = new Vue({
        el: '#app',
        data: {
            message : '你好啊',
            isShow: true
        },
        components: {
            cpn: {
                template: '#cpn'
            },
            data() {
                return {
                    isShow: false
                }
            }
        }
    })
</script>
1.4 作用域插槽
  • 父组件替换插槽的标签,但是内容由子组件来提供。
<div id="app">
    <cpn></cpn>  
    <!-- 实现效果:中间用-分割  -->
    <cpn>
        <!-- 此时拿不到pLanguages中的数据(作用域,父组件拿不到子组件中的数据) -->
        <!-- <span v-for="item in pLanguages"></span> -->

        <!-- 目的:获取子组件中的pLanguages -->
        <template slot-scope="slot">
            <!-- <span v-for="item in slot.data">{{item}} - </span> -->
            <span>{{slot.abc.join(' - ' )}}</span>
        </template>
    </cpn>    
    <cpn></cpn>    
</div>

<template id="cpn">
    <div>
    	<!-- abc可由自己命名 -->
        <slot :abc="pLanguages">
            <ul>
                <li v-for="item in pLanguages">{{item}}</li>
            </ul>
        </slot>
    </div>
</template>

<script src="../js/vue.js"></script>
<script>
    const app = new Vue({
        el: '#app',
        data: {
            message : '你好啊',
        },
        components: {
            cpn: {
                template: '#cpn',
                data() {
                    return {
                        pLanguages: ['JavaScript','c++','Java', 'Python', 'Go']
                    }
                }
            }
        }
    })
</script>

十.模块化开发

1.为什么要有模块化?
  • 不同文件命名相互冲突 => 解决办法: 匿名函数(闭包) => 坏处:代码复用性降低,之前定义的数据及函数无法使用 => 使用模块作为出口 (在匿名函数内部定义一个对象,给它添加各种需要暴露到外面的属性和方法,最后返回这个对象,并且在外面使用ModuleA接收,每个人只需要使用属于自己模块的属性和方法即可)
    模块化最基础的封装
2. CommonJS(了解)
  • 模块化有两个核心: 导出和导入
  • CommonJS的导出(export):
module.exports = {
    flag : true,
    test(a, b) {
        return a + b
    },
    demo(a, b) {
        return a * b
    }
}
  • CommonJS的导入(require):
let { test, demo, flag } = require('moduleA');
3. ES6的模块化实现
<-- index.html -->
<body>
    <script src="aaa.js" type="module"></script>
    <script src="bbb.js" type="module"></script>
    <script src="ccc.js" type="module"></script>
</body>
//aaa.js
var name = '小明'
var age = 18
var flag = true

function sum(num1, num2) {
    return num1 + num2
}

if (flag) {
    console.log(sum(20,30))
}

//1.导出方式一(先定义再导出):
export {
    flag, sum
}

//2.导出方式二(边定义边导出):
export var num1 = 1000;
export var height = 1.88;

//3.导出函数/类
export function mul(num1, num2) {
    return num1 * num2
}

export class Person {
    run() {
        console.log('在奔跑');
    }
}

//4.导出默认值
const address = '上海'

export default address
//bbb.js
import {sum} from "./aaa.js"

var name = '小红'
var flag = false
console.log(sum(100,200))
//ccc.js
//1.导入export{}中定义的变量
import {flag, sum} from "./aaa.js";

if (flag) {
    console.log('小明是天才,哈哈哈');
    console.log(sum(23,34));
}

//2.直接导入export定义的变量
import { num1,height } from "./aaa.js";

console.log(num1);
console.log(height);

//3.导入 export的function/class
import {mul,Person} from "./aaa.js";

console.log(mul(45,56));

const p = new Person();
p.run();

//4.导入的是默认值,同一模块内不允许存在多个(导入者可以自己来命名)
import addr from "./aaa.js";

console.log(addr);

//5.统一全部导入
import * as aaa from "./aaa.js";

console.log(aaa.flag);

十一. webpack

1. webpack 相关介绍
1. 1 webpack模块化
  • webpack 其中一个核心就是让我们能进行模块化开发,并且帮助我们处理模块之间的依赖关系。不仅仅是JavaScript文件,我们的CSS,图片,json 文件等在 webpack 中都可以当成模块来使用。
1.2 webpack的打包
1.2.1 含义
  • 将 webpack中的各种资源模块进行打包,合并成一个或多个包(Bundle)。并且在打包的过程中,还可以对资源进行处理,比如压缩图片,将scss转成css,将ES6语法转成ES5语法,将TypeScript转成JavaScript等操作。
1.2.2 和 grunt/gulp的对比
  • grunt/gulp的核心是Task,我们可以通过配置一系列的task,并且定义task要处理的事务(例如ES6, ts转化,图片压缩等),之后让grunt/gulp来依次执行这些task,而且让整个流程自动化,所以grunt/gulp也被称为前端自动化任务管理工具。
  • 如果工程模块依赖非常简单,甚至没有用到模块化的概念,或者只需要进行简单的合并,压缩,使用grunt/gulp即可。如果整个项目使用了模块化管理,而且相互依赖非常强,就可以使用webpack。
  • grunt/gulp更加强调的是前端流程的自动化,模块化并不是它的核心。而webpack更加强调模块化开发管理,而文件压缩合并、预处理等功能是其附加功能。
2. webpack安装及基本使用
2.1 安装
  • 安装 webpack 前首先要安装 Node.js,它自带了软件包管理工具npm
  • 查看自己的node版本,在终端输入node -v 即可查看
  • 全局安装 webpack(这里我们先指定版本号3.6.0,因为 vue cli2依赖该版本),输入 npm install webpack@3.6.0 -g
  • 局部安装 webpack(后续才会使用,–save-dev是开发时依赖,项目打包后不需要继续使用),先 cd 对应目录,再输入 npm install webpack@3.6.0 --save-dev
    • 在终端直接执行webpack命令,使用的是全局安装webpack
    • 当在package.json中定义了scripts时,其中包含了webpack命令,使用的则是局部webpack
  • 安装完成后可通过 webpack --version 查看版本号
2.2 准备工作
2.2.1 创建相关文件夹

相关文件夹

2.2.2 文件和文件夹解析
  • dist文件夹:用于存放之后打包的文件
  • src文件夹:用于存放我们写的源文件
    • main.js : 项目的入口文件
    • mathUtils.js : 定义了一些数学工具函数,可以在其他地方应用并且使用。
  • index.html : 浏览器打开时展示的首页html
  • package.json : 通过 npm init 生成的,npm包管理的文件
//mathUtils.js
function add(num1, num2) {
    return num1 + num2
}

function mul(num1, num2) {
    return num1 * num2
}

//CommonJS规范,直接引用该文件时浏览器不支持
module.exports = {
    add,
    mul
}
//main.js
const { add, mul} = require('./mathUtils.js')
// const math = require('./mathUtils')

// console.log(math.add(10,20));
console.log(add(10,20));
console.log(mul(10,20))
2.2.3 使用webpack打包
  • 步骤:
    • cd 对应文件夹,如: cd 01-webpack的起步
    • 将src文件夹中写好的源文件main.js打包至dist文件夹中,打包后生成文件为bundle.js,输入 webpack ./src/main.js ./dist/bundle.js
      成功显示
  • 注意:
    • 首次使用webpack打包时,报错:webpack : 无法加载文件 C:\Users\XXX\AppData\Roaming\npm\webpack.ps1,因为在此系统上禁止运行脚本。有关详细信息,请参阅 https:/go.microsoft.com/fwlink/?LinkID=135170 中的 about_Execution_Policies。
    • 原因:powershell对于脚本的执行有着严格的安全限制 ,默认是不载入配置文件的, 因而报错,可使用Set-ExecutionPolicy指令来修改PowerShell中执行策略的用户首选项。
    • 解决方式:①以管理员权限打开PowerShell;②输入Set-ExecutionPolicy RemoteSigned命令,将脚本执行权限修改为RemoteSigned;③输入Y以确认
    • 拓展:共有四个权限等级可选择:
Restricted不载入配置文件 不执行脚本【默认该权限等级】
AllSigned所有配置文件和脚本必须通过信任的出版商签名 这里的脚本页包括在本地计算机上创建的脚本
RemoteSigned所有从互联网上下载的脚本必须通过信任的出版商签名
Unrestricted载入所有的配置文件和脚本,如果运行了一个从互联网上下载且没有数字签名的脚本 在执行前会提示是否执行
3. webpack的相关配置
3.1 webpack.config.js
  • 实现:只要在相应文件终端中输入webpack,即可将文件打包好
    • 需要用到node相关包(如path)时,在终端中输入 npm init,完成后会生成一个package.json文件
    • 安装相关依赖,输入npm install
//webpack.config.js
const path = require('path')

module.exports = {
	//入口
    entry : './src/main.js',
    //出口
    output : {
        // 只能写绝对路径,此时需要动态获取
        path : path.resolve(__dirname, "dist"),
        filename : 'bundle.js',
    },
}
3.2 package.json
  • 实现:相关命令的映射,在相应文件终端中输入 npm run bulid,即可实现对应命令webpack。
  • 方法:在 package.json文件的脚本“scripts”中添加一行: “build”: “webpack”
  • 注意:package.json中的scripts脚本在执行时,会按照一定顺序寻找命令对应位置。
    • 首先,会寻找本地的node_modules/.bin路径中对应的命令,如果没有找到,才会到全局的环境变量中寻找。
3.3 局部安装webpack
  • 在终端中使用的webpack往往是全局的,而每个项目依赖特定的webpack版本,可能与全局的版本不一致,从而导致打包出现问题。所以,通常一个项目都有自己局部的webpack。
  • 步骤:
      1. 项目中安装自己的局部webpack: npm install webpack@3.6.0 --save-dev
      1. 启动webpack打包: node_modules/.bin/webpack
  • 安装完成后会生成一个node_modules文件夹
4. webpack使用相关文件
  • 大部分loader都可以在 webpack官网中找到,并且学习对应用法
    • 步骤一:通过 npm 安装需要使用的 loader
    • 步骤二: 在 webpack.config.js中的module关键字下去进行配置
4.1 webpack中使用css文件的配置
4.1.1 给webpack扩展对应的 loader(css-loader, style-loader)
  • 注意: 由于我们之前安装的webpack版本是3.6.0,此时安装的css loader或style loader由于版本太高会报错。故此时我们用的是
    • npm install --save-dev css-loader@2.0.2
    • npm install style-loader@0.23.1 --save-dev
module: {
        rules: [
            {
              // 正则表达式,\表示转义,$表示结束,匹配以.css结尾的文件使用以下loader
              test: /\.css$/,
              // css-loader只负责将css文件进行加载
              // style-loader负责将样式添加到DOM中
              // 使用多个loader时,从右向左读取
              use: [ 'style-loader','css-loader' ]
            }
          ]
    }
4.1.2 遇到的小bug:
ERROR in ./src/main.js
Module not found: Error: Can't resolve './info.js' in 'D:\Desktop\前端\learnVueJs\06-webpack的使用\03-webpack的loader\src'

解析:由报错信息知,系统无法找到资源,一般这种bug无非两种情况,一是路径写错了,二是资源不存在。查阅自己原码,资源存在,路径正确,那么到底是哪里出了问题,找了半天,终于发现,在引入资源的时候,单引号写成了双引号
- 正确引入:
- import * as info from './js/info'

4.2 webpack中对less文件的处理
  • 先给webpack 安装对应的 loader(less-loader)及less
  • 这里我们安装的版本
    npm install --save-dev less-loader@4.1.0 less@3.9.0
//special.less
@fontSize: 50px;
@fontColor: orange;

body {
    font-size: @fontSize;
    color: @fontColor;
}
  • 再在 webpack.config.js中的module关键字下去进行配置
  • 再在main.js中设置依赖,才会将它进行打包
//4.依赖less文件
require('./css/special.less')
document.writeln('<h2>你好啊,张万森!</h2>')
4.3 webpack中对图片文件的处理
  • 引入图片需要用到url,故给webpack 安装 url-loader
    npm install --save-dev url-loader@1.1.2
  • 在 webpack.config.js中的module关键字中的rules进行配置
//url-loader的配置
 {
   test: /\.(png|jpg|gif|jpeg)$/,
   use: [
     {
       loader: 'url-loader',
       options: {
         // 当加载的图片小于limit时,会将图片编译成base64字符串形式
         // 当加载的图片大于limit时,需要使用file-loader模块进行加载
         limit: 54000
       }
     }
   ]
 },
  • 给webpack 安装 file-loader

npm install --save-dev file-loader@3.0.1

  • 图片处理-修改文件名称(在module的options内设置)
    name: 'img/[name].[hash:8].[ext]'
    修改名称
4.4 webpack中对ES6语法的处理
  • webpack打包好的js文件中,写的ES6语法并没有转成ES5,意味着可能一些对ES6不支持的浏览器无法很好的运行我们的代码
  • 之前说过,想要将ES6语法转成ES5,需要使用babel
  • 而在webpack中,直接使用babel对应的loader即可
4.4.1 安装对应loader(babel-loader)

npm install --save-dev babel-loader@7 babel-core babel-preset-es2015

4.4.2 配置 webpack.config.js文件
//babel-loader的配置
  {
    test: /\.js$/,
    exclude: /(node_modules|bower_components)/,
    use: {
      loader: 'babel-loader',
      options: {
        presets: ['es2015']
      }
    }
  }
  • 重新打包,查看bundle.js文件,发现其中的内容变成了ES5的语法
4.5 webpack中使用Vue的配置
4.5.1 引入vue.js
    1. 安装
      npm install vue --save
      npm install vue@2.5.21 --save
//main.js
//5.使用Vue进行开发
import Vue from 'vue'

new Vue({
    el: '#app',
    data: {
        message: 'Hello Webpack'
    }
})
<body>
    <div id="app">
        <h2>{{message}}</h2>
    </div>

    <script src="./dist/bundle.js"></script>
</body>
    1. 报错,无法解析vue代码
    • vue在构建最终发布版本时,构建了两类版本
runtime-only代码中,不可以有任何的template
runtime-compiler代码中,可以有template,因为compiler可以用来编译template
    1. 解决方案
    • 修改 webpack.config.js 中的相关配置,在module.exports中添加以下代码,从而使用不同版本
resolve: {
      //alias:别名
      alias: {
        'vue$': 'vue/dist/vue.esm.js'
      }
    }
4.5.2 创建Vue时template和el的关系
  • 写好的html模板在之后的开发中,不希望被频繁修改
    • 解决方法:定义template属性
    • 当Vue中既有el又有template时,解析时会用template的模板替换index.html中挂载的
      内模块
//main.js
new Vue({
    el: '#app',
    template: `
    <div>
        <h2>{{message}}</h2>
        <button @click="btnClick">按钮</button>
        <h2>{{name}}</h2>
    </div>
    `,
    data: {
        message: 'Hello,张万森',
        name: '林北星',
    },
    methods: {
        btnClick() {
        }
    }
})
4.5.3 Vue的终极使用方案(Vue组件化开发引入)
  1. 递进方案
    • 为防止Vue中内容繁琐,我们将其封装成App组件,新建一个app.js 文件,将Vue中的主要内容写在app.js 文件中。在main.js中导入该组件即可。
//main.js

//5.使用Vue进行开发
import Vue from 'vue'
import App from './vue/app'

new Vue({
    el: '#app',
    template: `<App/>`,
    components: {
        App
    }   
})
//app.js
export default{
    template: `
    <div>
        <h2>{{message}}</h2>
        <button @click="btnClick">按钮</button>
        <h2>{{name}}</h2>
    </div>
    `,
    data() {
        return {
            message: 'HelloWebpack',
            name: '林北星',
        }
    },
    methods: {
        btnClick() {
        }
    }
}
  1. 最终方案(分离化)
    • 将template,script,style全部分离
    • 新建一个App.vue文件,最后在main.js中导入(import App from ‘./vue/App.vue’)
<template>
    <div>
        <h2 class="title">{{message}}</h2>
        <button @click="btnClick">按钮</button>
        <h2>{{name}}</h2>
    </div>
</template>

<script>
    export default {
        name: "App",
        data() {
            return {
                message: 'HelloWebpack',
                name: '林北星',
            }
        },
        methods: {
            btnClick() {
            }
        },
    }
</script>

<style scoped>
    .title {
       color: green;
    }
</style>
  • 此时,这个特殊的文件及特殊格式并不能被正确的加载,需要 vue-loader 及 vue-template-compiler 来进行处理。
    • 安装 vue-loader 及 vue-template-compiler
      npm install vue-loader vue-template-compiler --save-dev
      npm install --save-dev vue-loader@13.0.0 vue-template-compiler@2.5.21
    • 修改webpack.config.js配置文件
 //vue-loader的配置
 {
   test:/\.vue$/,
   use: ['vue-loader']
 }
  • 注意: 文件路径如果想省略后缀名,可在webpack.config.js文件中module.exports的resolve内添加extensions: ['.js', '.css', '.vue'],
5. plugin的使用
5.1 认识plugin
  1. plugin是什么?

    plugin是插件的意思,通常是用于对某个现有框架进行扩展,webpack中插件,就是对webpack现有功能的各种扩展,如打包优化,文件压缩等。

  2. loader和plugin的区别

    loader主要用于转换某些类型的模块,是一个转换器;
    plugin是插件,是对webpack本身的扩展,是一个扩展器。

  3. plugin的使用过程

    ①通过npm 安装 需要使用的plugins(某些webpack已经内置的插件不需要安装);
    ②在webpack.config.js中的plugins中 配置插件。

5.2 添加版权的plugin
  • (BannerPlugin,属于webpack自带插件)

  • 修改webpack.config.js配置文件

  • 重新打包程序(npm run build),查看bundle.js文件的头部,会看到添加的版权信息

//webpack.config.js
  //导入时会自动去node_modules中寻找
const webpack = require('webpack')

module.exports = {
	...
	plugins: {
      new webpack.BannerPlugin('最终解释权归橙点点所有')
    }
}
5.3 打包html的plugin
  • 真实发布项目时,发布的是dist文件夹中的内容,故我们需要将index.html文件打包到dist文件夹中,这时就需要使用HtmlWebpackPlugin插件

  • 该插件会自动生成一个index.html文件(可指定模板),并将打包到js文件自动通过script标签插入到body中

  • 安装HtmlWebpackPlugin插件
    npm install html-webpack-plugin --save-dev
    npm install html-webpack-plugin@3.2.0 --save-dev

  • 修改plugins相关配置

const webpack = require('webpack')
const HtmlWebpackPlugin = require('html-webpack-plugin')
module.exports = {
	...
    plugins: {
      new webpack.BannerPlugin('最终解释权归橙点点所有'),
      new HtmlWebpackPlugin({
        template: 'index.html'
        //表示根据什么模板生成index.html,此时需要删除之前在output中添加的publicPath属性,否则插入的script标签中的src可能会出问题
      }),
    }
}
5.4 js压缩的plugin
  • 在项目发布前,必然要对js等文件进行压缩处理,使用第三方插件uglifyjs-webpack-plugin,并且指定版本号1.1.1,和CLI2保持一致。
    npm install uglifyjs-webpack-plugin@1.1.1 --save-dev

  • 修改webpack.config.js文件

const uglifyJsPlugin = require('uglifyjs-webpack-plugin');
module.exports = {
	plugins: [
      new uglifyJsPlugin()
      }
]
  • 查看打包后的bundle.js文件,已经被压缩。

  • bug:使用vscode始终报错,打包不成功。(版本不要太高)
    webpack用plugin打包html文件时报错npm ERR! Failed at the meetwebpack@1.0.0 build script. npm ERR!..
    原因plugins:[...]必须使用[ ],不能使用 {}

6. 搭建本地服务器
  • 这个本地服务器基于node.js搭建,内部使用express框架,可以实现让浏览器自动刷新来显示修改后的结果。

  • 是一个单独模块,在webpack中使用前需要先安装
    npm install --save-dev webpack-dev-server@2.9.1

  • webpack.config.js文件配置修改如下:

module.exports = {
	...
	devServer: {
	      contentBase: './dist',
	      inline: true,
	    }
}
  • 注释:
    注释

  • 可再配置另外一个scripts:
    "dev": "webpack-dev-server --open"

    • –open参数表示直接自动打开浏览器
7. 配置文件的分离
  • 生产配置,开发配置,公共配置(base.config.js)进行分离
    配置分离
  • 想要实现配置文件的合并,需要安装webpack–merge
    npm install webpack-merge --save-dev
    npm install webpack-merge@4.1.5 --save-dev
    • 《注意版本号,版本太高会报错》
    • 报错
//prod.config.js
//生产时的配置:base + prod
const uglifyJsWebpackPlugin = require('uglifyjs-webpack-plugin');
const webpackMerge = require('webpack-merge');
const baseConfig = require('./base.config');

module.exports = webpackMerge(baseConfig,{
    plugins: [
      new uglifyJsWebpackPlugin()
    ],
})
  • 此时webpack.config.js已经被完全分离,可以被删除,但需要修改package.json中的scripts脚本内容
    "build": "webpack --config ./build/prod.config.js", "dev": "webpack-dev-server --open --config ./build/dev.config.js"
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值