VUE学习笔记2
1. 插槽slot
1.1 slot-插槽的基本使用
- 组件的插槽也是为了让我们的封装更加具有扩展性
- 让使用者可以决定组件内部的一些内容到底在展示什么
-
插槽的基本使用 在template标签里面加上
-
插槽的默认值 按钮
-
如果有多个值,同时放到组件替换时,一起作为替换元素
-
用使用时组件里面的代码替换template->slot里面的代码
<div id="app">
<cpn></cpn>
<cpn><span>哈哈哈哈</span></cpn>
<cpn>
<i>呵呵呵呵</i>
<button>按钮</button>
<div>我是div元素</div>
</cpn>
<cpn></cpn>
</div>
<template id="cpn">
<div>
<h2>我是组件</h2>
<p>我是组件,哈哈哈哈</p>
<slot><button>按钮</button></slot>
</div>
</template>
<script src="../js/vue.js"></script>
<script>
const app=new Vue({
el:"#app",
data:{
},
components:{
cpn:{
template:`#cpn`,
}
}
})
</script>
1.2 slot-具名插槽的使用
<div id="app">
<cpn><span slot="center">标题</span></cpn>
<cpn><button slot="left">返回</button></cpn>
</div>
<template id="cpn">
<div>
<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:{
},
components:{
cpn:{
template:`#cpn`,
}
}
})
</script>
1.3 编译作用域
<div id="app">
<!-- 使用vue实例里面的isShow-->
<cpn v-show="isShow"></cpn>
</div>
<template id="cpn">
<div>
<h2>我是子组件</h2>
<p>我是内容,哈哈哈哈哈</p>
<!-- 使用的是子组件里面的isShow,在自己的模板里面进行查找,即自己的作用域 -->
<button v-show="isShow"></button>
</div>
</template>
<script src="../js/vue.js"></script>
<script>
const app=new Vue({
el:"#app",
data:{
isShow:true
},
components:{
cpn:{
template:`#cpn`,
data(){
return {
isShow:false
}
}
}
}
})
</script>
1.4 作用域插槽的使用
作用域插槽的目的:父组件替换插槽里面的标签,但是内容由子组件来提供
<div id="app">
<cpn></cpn>
<cpn>
<!-- 目的是获取子组件中的pLanguage -->
<template slot-scope="slot">
<!-- data名字可以自己随便取 -->
<!-- <span v-for="item in slot.data">{{item}} - </span>-->
<span>{{slot.data.join(' - ')}}</span>
</template>
</cpn>
<!-- <cpn></cpn>-->
</div>
<template id="cpn">
<div>
<slot :data="pLanguage">
<ul>
<li v-for="item in pLanguage">{{item}}</li>
</ul>
</slot>
</div>
</template>
<script src="../js/vue.js"></script>
<script>
const app=new Vue({
el:"#app",
data:{
},
components:{
cpn:{
template:`#cpn`,
data(){
return {
pLanguage:['Java','C++','Python','JavaScript','C#','Go','Swit']
}
}
}
}
})
</script>
2. 模块化开发
2.1 CommonJS
模块化两个核心:导入与导出
// CommonJS的导入
module.exports={
flag:flag,
test(a,b){
return a+b;
},
demo(a,b){
return a*b;
}
}
// CommonJS的导出
let {test,demo,flag}=require('moduleA');
// 等同于
let _mA=require('moduleA');
let test=_mA.test;
let demo=_mA.demo;
let flag=_mA.flag;
2.2 ES6的模块化实现
<body>
<script src="aaa.js" type="module"></script>
<script src="mmm.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. export default
// const address='北京市'
// export default address
export default function (argument){
console.log(argument)
}
// mmm.js
// 1. 导入的{}对象中定义的变量
import {flag,sum} from "./aaa.js";
if(flag){
console.log('小明是天才,哈哈哈');
console.log(sum(20,10))
}
// 2. 直接导入expert中定义的变量
import {num1,height} from "./aaa.js";
console.log(num1);
console.log(height);
// 3. 导入expert的function
import {mul,Person} from "./aaa.js";
console.log(mul(20, 10));
const p=new Person();
p.run();
// 4. 导入expert default中的内容 只能有一个
import addr from "./aaa.js";
console.log(addr)
addr('你好啊');
// 5. 统一全部导入
// import {flag,num1,height,Person,mul,sum} from "./aaa.js"; 不推荐使用
import * as aaa from './aaa.js'
console.log(aaa.flag);
3. webpack的使用
3.1 webpack的介绍
- webpack是一个现代的JavaScript应用的静态模块打包工具
- webpack的核心就是让我们可能进行模块化开发,并且会帮助我们处理模块间的依赖关系
- 不仅仅是JavaScript文件,CSS、图片、JSON文件等都可以在webpack中被当做模块来使用
- 官方文档:https://www.webpackjs.com
grunt/gulp的核心是Task:我们可以配置一系列的task,并且定义task要处理的事务(例如:ES6、ts转化、图片压缩、scss转成css),之后用grunt/gulp来一次执行这些task,而且让整个流程自动化,所以grunt/gulp也被称为前端自动化任务管理工具。
3.2 webpack 的基本使用过程
-
文档框架
-
main.js(导入)
// 1. 使用commonjs的模块化规范 const {add,mul}=require('./js/mathUtils') console.log(add(10,10)); console.log(mul(1,10)); // 2. 使用ES6的模块化规范 import {name,age,height} from "./js/info"; console.log(name); console.log(age); console.log(height);
-
mathUtils.js(导出)
function add(num1,num2){ return num1+num2; } function mul(num1,num2){ return num1*num2; } module.exports={ add,mul }
-
info.js (ES6导出)
const name='why' const age=18 const height=1.88 export {name,age,height}
-
在终端输入如下命令,生成bundule.js文件
-
index.html:导入bundule.js文件
<body> <script src="./dist/bundle.js"></script> </body>
3.3 webpack的配置
-
先创建一个文件webpack.config.js
const path=require('path') module.exports={ entry:'./src/main.js', output:{ path:path.resolve(__dirname,'dist'), filename:'bundle.js' } }
-
然后在终端输入npm init 生成package.json文件
{ "name": "meetwebpack", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "author": "zhiyu", "license": "ISC" }
-
然后在终端输入webpack进行打包
3.4 webpack中使用css文件的配置
loader使用过程:
- 通过npm安装需要使用的loader
- 在webpack.config.js中的modules关键字下进行配置
3.4.1 安装css-loader
-
首先写一个css文件 normal.css
body{ background-color: red; }
-
在main.js文件中导入依赖
// 3. 依赖css文件 require('./css/normal.css')
-
安装loader:https://www.webpackjs.com/loaders/css-loader/
npm install --save-dev css-loader@2.0.2 // 有时候版本太高可能会报错
先在webpack.config.js中加入module模块,然后再次在终端输入 npm run build进行打包
css-loader 只负责将css文件进行加载
3.4.2 安装style-loader
在终端输入 npm install style-loader@0.23.1 --save-dev
官网:https://www.webpackjs.com/loaders/style-loader/
按照下图进行操作
style-loader:负责将样式添加DOM中
使用多个loder时,是从右到左
3.5 webpack-less文件的处理
less-loader
加载和转译 LESS 文件
-
创建less文件:special.less
@fontSize:50px; @fontColor:orange; body{ font-size: @fontSize; color: @fontColor; }
-
在main.js中引入依赖
// 4. 依赖less文件 require('./css/special.less')
-
在终端输入:npm install --save-dev less-loader@4.1.0 less@3.9.0 进行安装less-loader
-
在webpack.config.js中进行下列配置
打包成功:
3.6 webpack-图片的处理
url-loader
像 file loader 一样工作,但如果文件小于限制,可以返回 data URL
-
在normal.css文件中将网站背景设为图片
body{ background: url("../img/test.jpg"); }
-
在终端输入:npm install --save-dev url-loader
-
在webpack.config.js中进行下列配置
-
当加载的图片大于limit时,需要安装file-loader模块进行加载
npm install file-loader@3.0.1 --save-dev
-
加载图片路径问题:需要在webpack.config.j加入如下配置
-
将打包的图片统一放到一个文件夹里面,然后用原来的名字,在加一个hash值:img/[name].[hash:8].[ext]
3.7 webpack-ES6转ES5的babel
babel-loader
加载 ES2015+ 代码,然后使用 Babel 转译为 ES5
-
在终端输入:npm install babel-loader@7 babel-core babel-preset-es2015
-
在webpack.config.js中进行下列配置
3.8 webpack-使用Vue的配置过程
vue-loader
加载和转译 Vue 组件
-
在终端输入:npm install vue --save 进行安装vue
-
在main.js写下导出代码
// 5. 使用vue进行开发 import Vue from 'vue' const app=new Vue({ el:'#app', data:{ message:'hello message', } })
-
使用npm run build之后页面控制台报错
解决办法:在webpack.config.js中进行下列配置
3.9 Vue的使用方案
创建Vue时template和el的区别: 同时有template和el时,template会替换el的全部div
-
在main.js中写如下代码:
// 5. 使用vue进行开发 import Vue from 'vue' // import App from './vue/app' import App from './vue/App.vue' const 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:'hello message', name:'coderwhy' } }, methods:{ btnClick(){ } } }
-
或者创建App.vue文件
<template> <div> <h2 class="title">{{message}}</h2> <button @click="btnClick">按钮</button> <h2>{{name}}</h2> <Cpn></Cpn> </div> </template> <script> import Cpn from './Cpn.vue' export default { name: "App", components:{ Cpn }, data(){ return { message:'hello message', name:'coderwhy' } }, methods:{ btnClick(){ } } } </script> <style scoped> .title{ color:red; } </style>
-
再新建一个Cpn.vue文件
<template> <div> <h2>我是cpn组件的标题</h2> <p>我是cpn组件的内容,哈哈哈哈</p> <h2>{{name}}</h2> </div> </template> <script> export default { name: "Cpn", data(){ return{ name:'cpn组件的name' } } } </script> <style scoped> </style>
-
在index.html中基本没有什么代码
<body> <div id="app"> </div> <script src="./dist/bundle.js"></script> </body>
安装vue-loader:
-
在终端输入:npm install vue-loader@15.4.2 vue-template-compiler@2.5.21 --save-dev
-
在webpack.config.js中进行下列配置
-
运行 npm run build有如下报错
解决办法:
-
设置低于14 版本的vue-loader
在将vue-loader版本调到13.0.0的时候,vue与vue-template-compiler因版本不一致在报错
解决办法:将vue的版本调到与vue-template-compiler一样,重新安装vue,在npm run build即可成功
-
安装插件plugin
-
在引用时省略文件后缀名
解决办法:
3.10 webpack-横幅Plugin的使用
- plugin:是插件的意思,通常是用于对某个现有的框架进行扩展
- loader主要用于转换某些类型的模块,他是一个转换器
- plugin是插件,它是对webpack 本身的扩展,是一个扩展器
plugin的使用过程:
- 通过npm安装需要使用的plugins(某些webpack已经内置的插件不需要安装)
- 在webpack.config.js中的plugins中配置插件
3.10.1 添加版权的plugin
-
该插件叫BannerPlugin,属于webpack自带的插件
-
修改webpack.config.js中的文件
-
重新打包程序:查看bundle.js文件的头部,
3.10.2 HtmlWebpackPlugin的使用
-
该插件可以自动生成一个index.html文件(可以指定模板来生成)
-
将打包的js文件,自动通过script标签插入到body中
-
安装该插件:npm install html-webpack-plugin@3.2.0 --save-dev
-
使用插件,修改webpack.config.js文件中plugins的部分内容
-
现将src目录下的index.html文件修改成如下
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <div id="app"> </div> <!--<script type="text/javascript" src="dist/bundle.js"></script> dist/index可以自动生成,不需要自己导入--> </body> </html>
-
然后在 webpack.config.js文件进行下列修改
-
3.10.3 UglifyjsWebpackPlugin的使用
-
该插件对打包的js文件进行压缩
-
安装:npm install uglifyjs-webpack-plugin@1.1.1 --save-dev
-
修改webpack.config.js文件,使用插件
3.11 webpack-dev-server搭建本地服务器
-
webpack提供了一个可选的本地开发服务器 ,这个本地服务器基于node.js搭建,内部使用express框架,可以实现我们想要的让浏览器 自动刷新显示我们修改后的结果
-
安装:npm install --save-dev webpack-dev-server@2.9.1
-
devserver是作为webpack中的一个选项,选项本身可以设置如下属性
- contentBase:为哪一个本地文件夹提供本地服务,默认是跟文件夹
- port:端口号
- inline:页面实时刷新
- historyApiFallback:在SPA页面中,依赖HTML5的history模式
-
修改webpack.config.js文件
-
再配置一个scripts: --open参数表示直接打开浏览器
"dev": "webpack-dev-server --open"
-
运行:
-
直接运行:./node_modules/.bin/webpack-dev-server
-
在 package.json中配置路径
-
输入命令:npm run dev
-
3.12 webpack-配置文件的分离
-
创建build文件夹,在该文件夹下面新建base.config.js文件,将webpack.config.js里面的内容复制黏贴过去
-
在 上面文件夹新建dev.config.js和prod.config.js文件,将下面内容从base.config.js文件分离出去,放在前面两个文件中
// prod.config.js const UglifyjsWebpackPlugin=require('uglifyjs-webpack-plugin') module.exports={ plugins:[ new UglifyjsWebpackPlugin() ] }
// dev.config.js module.exports={ devServer:{ contentBase:'./dist', inline:true } }
-
安装插件:npm install webpack-merge@4.1.5 --save-dev
-
在prod.config.js,base.config.js中配置
const UglifyjsWebpackPlugin=require('uglifyjs-webpack-plugin') const webpackMerge=require('webpack-merge') const baseConfig=require('./base.config') module.exports=webpackMerge(baseConfig,{ plugins:[ new UglifyjsWebpackPlugin() ] })
const webpackMerge=require('webpack-merge') const baseConfig=require('./base.config') module.exports=webpackMerge(baseConfig,{ devServer:{ contentBase:'./dist', inline:true } })
-
修改package.json路径,删掉原来的webpack.config.js,开始打包运行
-
打包路径问题,修改如下:
-
修改package.json路径,删掉原来的webpack.config.js,开始打包运行
-
打包路径问题,修改如下:
完整base.config.js代码:
const path=require('path')
const webpack=require('webpack')
const HtmlWebpackPlugin=require('html-webpack-plugin')
const UglifyjsWebpackPlugin=require('uglifyjs-webpack-plugin')
module.exports={
entry:'./src/main.js',
output:{
path:path.resolve(__dirname,'../dist'),
filename:'bundle.js',
// publicPath:'dist/'
},
module:{
rules: [
{
test: /\.css$/,
use: [ 'style-loader' , 'css-loader' ]
},
{
test: /\.less$/,
use: [{
loader: "style-loader" // creates style nodes from JS strings
}, {
loader: "css-loader" // translates CSS into CommonJS
}, {
loader: "less-loader" // compiles Less to CSS
}]
},
{
test: /\.(png|jpg|gif|jpeg)$/,
use: [
{
loader: 'url-loader',
options: {
limit: 18000,
name:'img/[name].[hash:8].[ext]'
},
}
]
},
{
test: /\.m?js$/,
exclude: /(node_modules|bower_components)/,
use: {
loader: 'babel-loader',
options: {
presets: ['es2015'],
}
}
},
{
test: /\.vue$/,
use:['vue-loader']
}
]
},
resolve:{
extensions:['.js','.css','.vue'],
alias:{
'vue$':'vue/dist/vue.esm.js'
}
},
plugins:[
new webpack.BannerPlugin('最终版权归栀虞所有'),
new HtmlWebpackPlugin({
template:'index.html'
}),
// new UglifyjsWebpackPlugin()
],
// devServer:{
// contentBase:'./dist',
// inline:true
// }
}