vuejs、vue CLI、webpack笔记
一、vue.js语法
1. 开始操作
1.1 安装vue.js
官网 下载js文件,添加到项目文件夹中
1.2 使用vue
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>title</title>
</head>
<body>
<div id='app'>{{message}}</div> <!-- 双括号mustache(胡须)语法 -->
<script src='../js/vue.js'></script>
<script>
//声明式编程,区别于document.getElementById('app')这种命令式编程
const app = new Vue({
el:'#app',//用于挂载要管理的元素
data:{//初始化数据
message:'vue 我来了'
}
})
</script>
</body>
</html>
2. 标签
2.1 v-if
作用:
v-if:'data',若data数值为真就渲染组件,否则不渲染。
2.2 v-else-if
作用:
与v-if结合使用,效果类似。
2.3 v-show
v-show='data',若data数值为真就显示组件,否则不显示,不显示效果等同于display:none;区别于v-if的不渲染。
2.4 v-pre
作用:
跳过这个元素和它的子元素的编译过程。一些静态的内容不需要编辑加这个指令可以加快编辑。
2.5 v-once
作用:
如果显示的信息后续不需要再修改,使用v-once,这样可以提高性能。
2.6 v-bind
作用:
动态将数据和属性(style,class...)标签进行绑定。
简写:':'
2.7 v-cloak
2.7.1 语法格式
<div v-cloak>{{data}}</div>
作用:
在网络延迟高时,可能会在页面突兀的显示代码: {{data}},加上v-cloak(斗篷)在data还没有完全加载出来前可以掩藏 {{data}}。
2.8 v-for
作用:
遍历数组或者对象元素,遍历出来的数据绑定组件逐个渲染。
示例
<!-- 根据实际开发中的重要性,先value,最后index;value,key,index名字可以自定义 -->
<div v-for='(value, key, index) in object'>
<div>{{index}} {{key}} {{value}} </div>
</div>
2.9 v-on
作用
绑定事件函数,示例:v-on:click = 'clickFunction' 等同于 on-click = 'clickFunction'
修饰符
- stop:停止向上冒泡
- once:使绑定的事件只响应一次
- prevent:阻止组件的默认行为,比如form表格的默认active行为
- {keyCode|keyAlias}:对按键事件的过滤,例如:v-on:key.enter = 'functionName' 只有按下enter建才进行回调
- native:监听组件根元素的原生事件
简写:'@'
2.10 v-model
作用:
实现数据与表单的双向绑定。
原理
<input v-model="message" value="message">
<!-- 上面代码效果等同于下面-->
<input v-bind:value="message" @input="message=$event.target.value"/>
v-model 结合单选按钮
<body>
<div id='app'>
<input value='男' type='radio' name='radio-group' v-model="sex"/>男
<input value='女' type="radio" name='radio-group' v-model='sex'/>女
<h3>{{sex}}</h3>
</div>
<script src='../js/vue.js'></script>
<script>
const app = new Vue({
el:'#app',
data:{
sex:'男'
}
})
</script>
</body>
v-model 结合复选框
复选框单选对应 bool值,多选对应数组[]
<body>
<div id='app'>
<input type="checkbox" v-bind:value='agree' v-model='agree' />同意协议
<h3>{{agree}}</h3>
</div>
<script src='../js/vue.js'></script>
<script>
const app = new Vue({
el:'#app',
data:{
agree:false
}
})
</script>
</body>
<body>
<div id='app'>
<div v-for='(hobby,index) in hobbies'>
<input v-bind:value='hobby' type='checkbox' name='index' v-model="selectedHobbies"/>{{hobby}}
</div>
<h3>{{selectedHobbies}}</h3>
</div>
<script src='../js/vue.js'></script>
<script>
const app = new Vue({
el:'#app',
data:{
hobbies:['游泳','跑步','看书','绘画'],
selectedHobbies:[]
}
})
</script>
</body>
v-model 结合select
<!-- 若想实现多选 添加标签:multiple -->
<select name='abc' v-model='fruit'>
<option value='苹果'>苹果</option>
<option value='香蕉'>香蕉</option>
<option value='葡萄'>葡萄</option>
<option value='榴莲'>榴莲</option>
</select>
修饰符:
- lazy:对于绑定的组件,只在其失去焦点或按下回车才更新vue实例中的数据。
- number:传入vue实例中的数据为Number对象
- trim:除去数据中的前后空格
3. 组件中的key属性
3.1 作用:
唯一确定组件,使组件能不随意更新。通俗讲可以让组件更好复用或不复用。
3.2 示例:若不加入key,js内核会复用input组件,造成组件中的值会保留。
<body>
<div id='app'>
<div v-if='flag'>
<input key='account'/>账号登录
</div>
<div v-else>
<input key='email'/>邮箱登录
</div>
<button @click="btnClick">{{login}}</button>
</div>
<script src='../js/vue.js'></script>
<script>
const app = new Vue({
el:'#app',
data:{
flag:true,
login:'切换邮箱登录'
},
methods:{
btnClick(){
if(this.flag){
this.flag = !this.flag;
this.login = '切换账号登录';
}else{
this.flag = !this.flag;
this.login = '切换邮箱登录'
}
}
}
})
</script>
</body>
4. 响应式函数
4.1 响应式操作
修改vue实例中数据,绑定vue实例中数据的组件/属性会实时更新。通过函数实现的响应式操作即为响应式函数。
4.2 关于数组操作的响应式函数
- push('') 最后加多元素
- pop() 删最后一个
- shift() 删第一个
- unshift('') 最开头添加多个元素
- splice('','','') start, length ,item 它可以进行删除元素,插入元素,替换元素
- reverse 数组反转
4.3 非响应式操作
通过索引改变数组!!!
5. Vue实例中的过滤器对象
5.1 作用
将数据按照一定的规则转化为另外一个数据返回。
5.2 示例:将price作为参数传入priceFilter中,返回修改后的price
<body>
<div id='app'>
<!-- 使用过滤器 ,默认将price作为参数传入给priceFilter-->
<h4>价格:{{price | priceFilter}}</h4>
</div>
<script src='../js/vue.js'></script>
<script>
const app = new Vue({
el:'#app',
data:{
price:12.3
},
filters:{ //在vue实例中加入filter对象,在filter对象里面定义过滤器(函数)
priceFilter(price){
//保留小数2位:Number.toFixed(2)
return '¥' + price
}
}
})
</script>
</body>
6. js中高阶函数 (很多高级语言中都会有)
6.1 filter()
result = array.filter(callback(n){}) 回调函数返回的必须为一个bool值,若为true自动 将n加入内部数组,否则不加入
6.2 map()
result = array.map(callback(n){}) 回调函数的返回值为新数值返回
6.3 reduce()
result = array.reduce(callback(n1,n2){},0) 第二个参数为第一个值的初始值, 对两个值进行操作,返回操作后的结果作为下一组传入的第一个值。
7. 组件化
7.1 自定义第一个组件 (创建构造器,注册组件,使用组件)
<body>
<div id='app'>
<!-- 使用组件 -->
<my-component></my-component>
</div>
<script src='../js/vue.js'></script>
<script>
//创建组件构造器
creater = Vue.extend({
//tab键上面的那个符号在ES6中可以实现内部内容任意换行圈成一个整体
name:'cmp',
template:`
<div>
<h4>我的第一个组件</h4>
</div>
`
})
//注册组件 (此方法注册的组件为全局组件,所有vue实例挂载的元素中都可以使用)
Vue.component('my-component',creater)
const app = new Vue({
el:'#app'
})
</script>
</body>
7.2 全局组件注册的简写(语法糖)
//Vue.compontent会自动将第二个参数{}传给Vue.extend()
Vue.component('my-component',{
template:`<div></div>`
})
7.3 局部组件注册 (确立一个概念:Vue实例本身是个组件)
<body>
<div id='app'>
<cpn></cpn>
</div>
<div id='app2'>
<!-- <cpn></cpn> 试图引用app实例的局部组件,报错! -->
</div>
<script src='../js/vue.js'></script>
<script>
const cpnC = Vue.extend({
template:'<div>局部组件</div>'
})
const app = new Vue({
el:'#app',
components:{
cpn:cpnC
}
})
const app2 = new Vue({
el:'#app2'
})
</script>
</body>
7.4 组件中的模板(template)分离写法
1.通过脚本分离:
<script type='text/x-template' id='temp'>
<div>
在类型为'text/x-template'的script中定义
</div>
</script>
<script >
//通过id引用
Vue.component('my-component',{template:'#temp'})
</script>
2.通过组件模板分离
<template id='#temp'>
<div>
在template组件中定义模板
</div>
</template>
<script>
Vue.component('my-component',{template:'#temp'})
</script>
7.5 向组件中存放数据
<!-- 使用组件中message数据 -->
<cpn>{{message}}</cpn>
--------------------------------------------------
<script>
Vue.component('cpn',
{
template:'#cpn',
data() //这个对象必须为函数
{
return {message:'abc'}
}
}
)
</scirpt>
7.6 思考:组件中data为什么是函数?
这可以保证数据作用域仅限于当前组件,而不会作用于其他相同的组件!
7.8 创建父子组件
<body>
<div id='app'>
<!-- 使用组件 -->
<cpn2></cpn2>
</div>
<script src='../js/vue.js'></script>
<script>
const cpnC = Vue.extend({
template:'<div>子组件</div>'
})
Vue.component('cpn2',{
template:'<div>父组件<cpn></cpn></div>',
components:{
cpn : cpnC //*这里只能是一个组件构造器,若为一个组件就报错找不到
}
}
)
const app = new Vue({
el:'#app'
})
</script>
</body>
7.9 父子组件的通信
需求:子组件不能引用父组件或者Vue实例的数据,但是实际开发中却需要父子组件相互通信!
Vue提供的方法:
通过props(properts 简写)向子组件传递数据;
通过事件($emit Events)向父组件发送数据。
1. 父组件向子组件传递数据:
<body>
<div id='app'>
<!-- 父组件向子组件传递数据 -->
<cpn v-bind:movies='movieList'></cpn>
</div>
<template id="temp">
<div>
<ul>
<!-- 遍历显示组件中的movies数据 -->
<li v-for='movie in movies'>{{movie}}</li>
</ul>
</div>
</template>
<script src='../js/vue.js'></script>
<script>
const app = new Vue({
el:'#app',
data:{
movieList:['三傻大闹宝莱坞','我不是药神','唐人街探案']
},
components:{
cpn:{
template:'#temp',
props:['movies'] //这里的movies在上面被当成一个变量属性
}
}
})
</script>
</body>
1.1 props的一些可选操作
-
数据类型限制:
props: -
带默认值:(对象中 required 表示 是否必须传数据)
props:
{movies:
{
type:Array,
default:[''],
required:true
}
}
上面的语法有个错误,default默认值为数组或对象类型时default必须为一个函数:default(){return []}
- 自定义数据类型:
props:
1.2 props中数据变量驼峰命名问题:
props:{moviesName:Array} //声明时为驼峰
<cpn v-bind:movies-name='moviesName'/> //使用时要以-连接
2.子组件向父组件传递数据:($emit发射的事件同样不能用驼峰命名法)
<!-- 触发流程:btnClick -->cpn-event -->getCpnData -->
<body>
<div id='app'>
<cpn @cpn-event='getCpnData'></cpn>
<h2>子组件传来的数据:{{cpnData}}</h2>
</div>
<template id="temp">
</template>
<script src='../js/vue.js'></script>
<script>
const app = new Vue({
el:'#app',
data:{
cpnData:''
},
methods:{
getCpnData(item){
this.cpnData = item
}
},
components:{
cpn:{
template:`
<div>
<button @click="btnClicked">子组件按钮</button>
</div>
`,
data(){
return {item:'子组件数据'}
},
methods:{
btnClicked(){
return this.$emit('cpn-event',this.item)
}
}
}
}
})
</script>
</body>
扩展知识
<!-- component watch 对象 监听数据改变;
watch中的函数名 和 data 返回的变量名相同 -->
data(){
return {number1:123}
},
watch:{
number1(newValue, oldValue){
this.number1 = newValue;
this.$emit('numb1change',this.number1)
}
}
7.10 父子组件互相访问
1.父组件访问子组件
$children 或者 $refs (reference)
this.$children[0].function()
this.$children[1].name
在实际开发中一般不使用this.$children ,组件数量随时会变,下标取值不稳定
this.$refs.aaa 父组件中访问子组件,refs默认为空,在组件中需要加ref
<cpn ref='aaa'> </cpn> 组件中加入ref使用
2.子组件访问父组件
his.$parent //在子组件中访问父组件
this.$root //在子组件中访问vue实例
7.11 slot 插槽
作用
使组件内部具有更好可扩展性。使得我们可以给自定义组件中添加中添加其他html内容。
使用方法
<!-- 1.在模板中定义slot -->
<template id="temp">
<div>自定义组件
<slot></slot>
</div>
</template>
<!-- 2.使用带有slot的模板的组件 -->
<!-- h2 和 button 会替换组件中的slot,可以将slot理解为一个占位符 -->
<cpn>
<h2>给自定义组件添加html元素</h2>
<button>按钮</button>
</cpn>
slot常见几种情形
<!-- 1.带默认值slot -->
<!-- 若不给自定义组件中添加html内容,默认显示button;若添加了就替换button -->
<slot><button>按钮</button></slot>
<!-- 2.具名(带name)slot -->
<template id='barTemp'>
<slot name='left'></slot>
<slot name='center'></slot>
<slot name='right'></slot>
</template>
<!-- 使用:(指名道姓替换组件中某个插槽) -->
<cpn><button slot='left'>返回</button></cpn>
<cpn><span slot='center'>标题</span></cpn>
<cpn><button slot='right'>搜索</button></cpn>
<!-- 3.作用域slot :父组件替换插槽的标签,但是内容由子组件来提供-->
<!-- 需求:内容在子组件,希望父组件告诉我们如何展示,怎么办? -->
<template>
<slot v-bind:data='子组件数据'></slot>
</template>
<!-- 重点是:slot-scope='slot' -->
<cpn>
<template slot-scope='slot'>
<div v-for='item in slot.data'>{{item}}</div>
</template>
</cpn>
二、模块化和webpack
1. 模块化规范
1.1 常见模块化规范:
CommonJS(node采用的该规范)、AMD、CMD、ES6的Modules
1.2 CommonJS 的导出
请在node 环境下使用
a.js文件:
flag = true
sum(a,b){
return a+b
}
<!-- 重点:module.exports -->
module.exports = {
flag:flag,
sum:sum
}
2.2 CommonJS 的导入
b.js文件
<!-- 重点:require -->
var obj = require('a.js')
console.log(obj.flag)
console.log(obj.sum(1,2))
2.3 脚本标签中的 module 类型
作用:
将每个js文件作为独立的模块,避免了js文件间命名冲突。
演示
a.js文件中:
var flag = true
if(flag){console.log('a.js文件')}
b.js文件中:
if(flag){console.log('b.js文件')}
index.html 文件中
<!-- 加入type='module' 后会报错 ,
因为type='module' 可以保证多个文件共同引用不会出现命名冲突-->
<script src='a.js' type='module'></script>
<script src='b.js' type='module'></script>
思考:一个js文件想引用另外一个js文件中的数据ES6中怎么实现?
ES6 标准中的export,import 的运用。
2.4 ES6 的导出
a.js文件中 export演示
var name = '鲤鱼的探险历程'
getName()
{
return name
}
//方式一:对象形式导出
export {name, getName}
//方式二:直接导出
export var name2 = 'vue coder'
//方式三:匿名导出
const email = '123@126.com'
export default email //同一个模块(文件)中只能存在一个
2.5 ES6 的导入
b.js文件中 import演示
//对应方式一:
import {name, getName} from 'a.js'
//对应方式二:
import {name2} from 'a.js'
//对应方式三:
import my_email from 'a.js' //导入者自己命名变量
应用于除了匿名导出的其他方式:
//‘* as ’的作用:给导入对象命名,避免 1.导入变量和当前文档中的变量相同产生冲突,2.导入数据过多的问题
import * as aaa from '../aa.js'
console.log(aaa.val)
2. webpack的使用
webpack官网
webpack中文
2.1 webpack 的安装
全局安装
npm install webpack -g
本地(局部)安装
npm install webpack --save
2.2 建立项目
目录结构
- dist //保存打包后的文件
- src //源代码文件夹
* main.js //在该文件引用所有js文件
* a.js
* b.js - index.html //项目入口文件
2.3 打包文件
把终端(cmd)路径换成当前项目路径,然后键入(4.x.x版本):
webpack ./src/main.js -o ./dist/bundle.js
webpack3.x.x的版本使用:
webpack ./src/main.js ./dist/bundle.js
解释:将main.js以及它所引用的所有js文件打包到bundle.js文件;
若是webpack 5.x.x会在dist/bundle.js 的文件夹中生成打包后的main.js
思考:怎么精简:webpack ./src/main.js ./dist/bundle.js ?
需要对webpack进行配置。
配置流程:
- 当前项目中建立文件:webpack.config.js
- webpack.config.js中添加内容:
const path = require('path') //导入node的path包
module.exports = {
entry:'./src/main.js',
//output中的路径必须为绝对路径
output:{
//__dirname 为node中上下文全局变量,值为当前路径,
//path.resolve 进行路径拼接
path:path.resolve(__dirname,'dist'),
filename:'bundle.js'
},
mode:'development' //不加这条代码,在4.x.x以上的webpack默认打包为压缩后的代码
}
//概括:将src下的main.js文件打包到当前路径下的dist文件夹的bundle.js文件中
思考:这里引用了nodo的path包,那么就需要配置一个package.json文件,该文件如何配置?
1. 在当前项目路径下运行终端命令:npm init
2. 按照提示进行配置,配置完后项目中就会生成 package.json 文件
<!-- package.json 文件内容 -->
{
"name": "webpacktest",
"version": "1.0.0",
"description": "",
"main": "index.js",//随便填的入口文件
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC"
}
- 以后在终端直接输入:webpack ,即可起到相同打包效果。
2.4 npm 运行 webpack
思考:若配置文件很多webpack命令就会又变得很长,怎么解决?
用 npm run ... 代替。
怎么用npm run build 代替 webpack ?
在 package.json 的scripts中添加:"build":"webpack"
运行npm run build 时,会默认先从局部(本地)找webpack,再找全局
这里面存在一个问题:若项目中需要低版本的webpack怎么办?
安装局部(本地)webpack : npm install webpack@3.6.0 --save-dev //有-dev意思为开发时依赖
在终端使用webpack命令会使用全局的webpack. 想访问本地需要输入 ./node_module/.bin/webpack
2.5 webpack.loader
loader作用
将 less-->css ,TypeScript --> js ...
总的一句话:将其他文件打包为css、js、html这种浏览器认识的基本类型
loader的使用
步骤一:npm 安转需要使用的loader;(不同文件打包,对应不同loader)
步骤二:在webpack.config.js 中的module关键字下进行配置
2.5.1 打包CSS
1.npm install --save--dev css-lodeer style-loader
2.webpack.config.js 文件配置:
module:{
rules:[
{
test:/\.css$/,
use:['style-loader','css-loader']
//css-loader 负责加载css文件,style-loader负责编译
//为什么css-loader写在后面,因为node数据加载默认从右至左
}
]
}
2.5.2 打包less
1.npm install --save-dev less-loader less //less负责转换less-->css
2.{test:/.less$/, use['style-loader','css-loader','less-loader']}
2.5.3 打包图片
1.npm install --save-dev url-loader
2.webpack.config.js文件中:
module:{
rules:[
{
test:/\.(png|jpg|jpeg)$/,
use:[
{
loader:'url-loader',
options:{limit:8192}
//小于limit大小的图片会被base64编码后替换图片url
//当加载大于limit的图片时需要file-loader 模块
}
]
}
]
}
3.若image的大小有大于limit限制的才有这步骤:
npm install --save-dev file-loader
!!!若运行程序入口网页index.html不在dist包中,可能会报路径加载错误
原因:file-loader会将照片文件加载到打包文件中,这样源代码中的路径就会有问题。
解决方法:使打包照片路径时候自动添加上dist路径,在webpack.config.js的output中加上:publicPath:'dist/'
file-loader会用hash值命名图片,若需求希望打包后的文件有一定的规范:
希望放在img文件夹中,原来文件名+hash的前8位+文件类型
(为什么不直接用文件名字,在实际开发中项目中可能存在相同名字的图片被同时加载到img文件夹)
操作:options中加上:name:'img/[name].[hash:8].[ext]'
2.5.4 ES6代码转为ES5代码
1.npm install --save-dev babel-loader@7 babel-core babel-preset-es2015
2.{test:/.js$/, exclude:/(node_modules|bower_components)/,use:{loader:'babel-loader',options:{presets:['es2015']}}}
2.6 配置vue环境
1.npm install --save vue //安装运行时依赖,非开发时依赖!
2.导入vue: import Vue from 'vue'
再运行 :npm run build 可能会报错
原因:在使用vue的文件中存在 const app = new Vue({}),会被当作编译template,而runtime-only 版本不支持template
解决方法:使用 runtime-compiler 的vue版本。
操作:在webpack.config.js中配置中加入 resolve:{alias:{'vue$':'vue/dist/vue.esm.js'}}
原理:将import Vue from 'vue'中的vue引入了另一个文件,vue.esm.js相当于使用runtime-compile
打包.vue文件
1.npm install vue-loader vue-template-compiler --save-dev
2.{test:/\.vue$/,user:['vue-loader']}
打包时可能报错:vue-loader 缺少一个插件,14版本上的webpack需要配置一个插件
解决方法:在package.json中修改 'vue-loader':'^13.0.0' 版本限制在13-14间,再执行 npm install
怎么省略输入文件类型?
在webpack.config.js的module.export中加入:
resolve:{//用来解决路径问题
"extensions":['.js','.css','.vue']
}
2.7 plugin 插件的使用
步骤一:通过npm安转需要应用的插件
步骤二:在webpack.config.js中的plugins中配置插件
loader和plugin区别:loader像一个加载器、转换器;plugin是一个扩展器。
plugin常用的有:给js添加一个版权声明,代码压缩(丑化)
·版权声明操作:
在webpack.config.js文件中
const path = require('path')
const webpack = require('webpack')
module.exports = {
entry:'./src/main.js',
output:{
//__dirname 为node中上下文全局变量,值为当前路径,
//path.resolve 进行路径拼接
path:path.resolve(__dirname,'dist'),
filename:'bundle.js'
},
mode:'development',
resolve:{//用来解决路径问题
"extensions":['.js','.css','.vue']
},
plugins:[
new webpack.BannerPlugin('我的版权')
]
}
·打包html的plugin
真实发布项目时,发布的dist文件夹中的内容需要index.html文件
执行:npm install html-webpack-plugin --save-dev
const HtmlWebpackPlugin = require(html-webpack-plugin)
--------------------------------------------------
plugins:[
new HtmlWebpackPlugin(
{template:'index.html'})//根据模板生成index.html
]
打包成功后会在dist文件夹下生成index.html文件
文件中自动加入 <script type='text/javascript' src='dist/bundle.js'>
这里存在一个问题:此时的bundle.js是和index.html同级的,所以我们需要去掉 配置文件中的publicPath
·js压缩
操作:npm uglifyjs-webpack-plugin@1.1.1 --save-dev //版本 一般采纳于后面使用的脚手架
const Uglify = require('uglifyjs-webpack-plugin')
--------------------------------------------------
new Ugligy()
2.8 webpack-dev-server 搭建本地服务器
执行:npm install --save-dev webpack-dev-server@2.9.3 //版本和webpack有对应的关系的
在webpack.config.js中:
devServer:{
contentBase:'./dist' , //服务的文件夹
inline:true , //是否实时更新
/*port:8080 ,*/
/*historyApiFallback*/
}
终端中执行指令:./node_modules/.bin/webpack-dev-server
也可以在 package.json中scripts中加入‘dev’:'webpack-dev-server',这样在终端可以:npm run dev
如何自动打开浏览器呢?
修改:‘dev’:'webpack-dev-server --open'
2.9 配置文件抽离
需求:有些配置开发时需要,有些配置运行时需要,若写在一起就很混乱
建立文件夹/文件:
- build:
* base.config.js
* prod.config.js
* dev.config.js //分别公共 生产 开发
抽离webpack.config.js(下面仅为部分示例)
dev.config.js:
module.exports:{
devSevers:{
contentBase:'./dist' , //服务的文件夹
inline:true
}
}
prod.config.js:
const Uglify = requrie('uglifyjs-webpack-plugin')
module.exports:{
plugins:[new Ugligy()]
}
为了配置文件合并,需要安装 webpack-merge:
npm install webpack-merge --save-dev
操作:在prod.config.js文件中:
const webpackMerge = require('webpack-merge')
const Uglify = requrie('uglifyjs-webpack-plugin')
const baseConfig = requrie('./base.config')
module.exports= webpackMerge(baseConfig,{
plugins:[new Ugligy()]
}
一切完成,还需要在package.json中 修改
'build':'webpack --config ./build/prod.config.js'
'dev':'webpack-dev-server --open --config ./build/dev.config.js'
再打包后会出问题,最初设置是当前路径下(配置文件所在的路径)的dist文件夹保存打包后的文件。
现在要修改成:
module.exports = {
entry:'./src/main.js',
output:{
path:path.resolve(__dirname,'../dist'),//这里稍微改下
filename:'bundle.js'
}
}
三、Vue CLI 的使用
CLI
Command-line-interface 俗称为脚手架
作用
搭建Vue 的开发环境,和配置webpack
安装
npm instal -g @vue/cli //脚手架3的安转形式
项目创建
脚手架3创建项目:vue create my-project
如果需要按照Vue CLI 2初始化
拉取2 的版本 npm install @vue-cli-init -g
脚手架2创建项目:vue init webpack my-project
脚手架2配置说明

- vue init webpack
- 项目名
- 项目描述
- 作者
- 运行环境
- 是否安装 vue-router
- 是否使用ESLint (js规范)
是:选择标准的,还是airbnd公司,还是自定义 - 是否下载单元测试
- 是否下载端到端测试
它会使用selenium 进行测试,它可以操作浏览器 - 后面项目采用npm、yarn或自定义安装
四、Vue 代码优化
4.1 runtime-compile 版本
流程:
template --解析-->ast(抽象语法树) --编译-->
render---->Viturl DOM-->UI
4.2 runtime-only 版本
流程:
render---->Viturl DOM-->UI
优点:
1.性能更高;2.代码更少.
4.3 vue实例对象:render
createElenment 函数
作用
创建一个标签
使用
const cpn={
template:`<div>{{message}}</div>`,
data(){
return {'message':'组件'}
}
}
new Vue({
el:'#app',
//render 中创建的组件会替代#app
render:function(createElement){
//1.普通用法:createElement(标签,{标签的属性},[''])
//return createElement('h2',{class:'box'},['hello world',createElement()])
//2.传入组件
//return createElement(cpn)
//3.传入vue文件中的组件
return createElement(app)
}
--------------------------------------------------
})
//.vue 文件中的template是由谁处理的呢?
//由vue-template-compiler 解析为了render函数
//vue-template-compiler为开发时依赖,也就是在生产环境中没有template了。
简写
new Vue({
el:'#app',
render:h=>h('app')
})
--------------------------------------------------
new Vue({
render:h=>h('app')
}).$mount('#app')
五、参考链接
六、学习视频
vue.js-vue-Vue-VUE2.X-VUE3.0-github
七、总结
首先特别感谢王红元老师的开源精神,和把视频搬到B站那位朋友。王老师讲的很好,面面俱到,这也就激发了我做笔记的冲动,起初是用.txt做的,后面就觉得不对劲了.txt没有结构,笔记多了后回过头自己都不愿意看自己写的笔记。我就转向了早有耳闻的markdwon,结果就爱上了,哈哈哈!越写越兴奋,结果就是在一个.md文件中写了1000多行,vue的技术点还有很多,但我想把这篇笔记做为我第一篇博客发布,再长估计就没人愿意看了,也不太符合博客短而精的特点,所以就到这里结束啦!
ps:vue挺有意思的,和我以前学的微信小程序有很多共同点,让人不经感慨:相见恨晚。
(博客园和Hbuilder X 上面的markdown排版不同,啊啊啊啊!)
有人完全根据视频做了些笔记,这里记录一下他的链接,以供参考:


浙公网安备 33010602011771号