M代表模型,V代表视图,VM代表视图模型
在Vue中,M就是Vue实例中data里面定义的数据,V就是Vue实例所托管的区域,VM就是使用Vue实例化出来的对象
主要区别可以理解两者的通信方式
MVC: V中用户交 互后的数据流向C,C经过逻辑处理后再提交到M进行保存;M中的数据如果改变,会直接作用于视图,即M直接影响视图的更新.
MVVM:V中用户交互后的数据流向VM,VM处理数据后更新到M进行储存,M中数据如果改变,则也会交由VM,VM再通知V进行更新视图.
V -> M 监听表单元素的value
onchange
事件 然后将新值赋值到对应的属性上去M -> V angular和vue实现机制有所区别
会有一个类似定时器的功能,每隔一段时间自动遍历一下有没有属性值发生变化,当属性值发生变化 会调用$wantch事件 去监听页面上所有指令,查询出有需要改变的值,然后调用$apply方法进行DOM更新
利用
Object.defineProperty()
内部的setter
方法 监听数据的写操作(设置属性的操作),在setter
方法内部去更新DOM中显示的数据
var o = {};
o.name = 'zxx';
var age;
// 使用Object.defineProperty这种方式给对象添加属性,默认该属性不可修改.
Object.defineProperty(o,age,{
// value:18,
// writable:true
get:function(){
console.log('我被获取了');
return age;
},
// set方法可以监听到数据被改变
set:function(){
// 每次监听到属性发生变化时,都去通知DOM上绑定的该属性进行更新
// 页面上绑定了age属性的dom元素可以通过updateDOM()进行对value值的更新
unpdataDOM();
console.log('我被设置数据了');
}
});
o.age = 18;
console.log(o.age);
Array.prototype.splice(startIndex,length)
方法是对数组进行截取的方法,从startIndex
位置开始截取,截取length
个元素,截取完返回一个新数组,新数组中的元素就是截取出来的元素.同时会影响原数组.
var arr = [1,2,3,4,5];
var newarr = arr.splice(1,2); // 从索引1开始截取,截取2个元素 newarr == [2,3]
console.log(newarr); // [2,3]
console.log(arr); // [1,4,5]
Array.prototype.slice(startIndex,endIndex)
方法也是对数组进行截取,从startIndex
开始截取,一直截取到endIndex
索引为止,截取出来的元素包含startIndex
,不包含endIndex
位置的元素。不会对原数组产生影响.
var arr = [1,2,3,4,5];
var newarr = arr.slice(1,2); // 从索引1开始截取,截取到索引为2的元素为止,包含索引1的元素,不包含索引2的元素
console.log(newarr); // [2]
console.log(arr); // [1,2,3,4,5]
// 可以对数组进行遍历 然后返回满足条件(回调函数)的元素的索引
function findIndex(array,callback){
for(var i = 0;i
定义一个vue的管理范围
vue1.0里面vue的管理区域的id可以定义在HTML以及body标签上
vue2.0里面不允许这样来做
定义一个vue的对象
var vm = new Vue({
el:'#app',
// data定义vue实例的所有属性
data:{
// 定义将来要在vue管理区域中使用的数据
name:"zs"
},
// methods定义vue实例所有的方法
methods:{
fn:function(){
this.name = 'ls'
}
}
})
{{}}
:插值表达式
作用:将vue对象中的数据以及表达式显示到vue托管区域中
{{这里书写vue对象中data里面的数据或者表达式}}
v-text
:输出文本数据
v-html
:输出HTML结构数据
data:{
name:'zs'
}
v-cloak
:解决表达式闪烁问题
1. 定义一个样式
2. 使用
{{name}}
原理:当vue.js文件还没有加载出来时 使用[v-cloak]样式作用于当前指令所在标签,当vue.js能够起作用时,会自动删除v-cloak指令
v-bind
:动态给标签或者组件绑定属性
// 使用:简写v-bind
// 当绑定的属性值是常量字符串+变量时 我们在绑定这个属性时 是需要绑定一个对象,这个对象的键就是需要绑定的属性名 这个对象的值就是常量字符串+变量
跳转
v-on
:绑定事件
v-model
:双向数据绑定
// 可以使用的标签:input textarea select 组件
// name会和表单元素的value进行关联 value值变化 name值变化 反过来name值发生变化 value值也会发生变化
v-for
:循环输出HTML元素
{{item.name}}
v-if
:根据表达式值的真假决定元素的显示隐藏
// isShow为true显示div 为false隐藏div
// v-if是直接操作DOM 即隐藏时会将该div从DOM结构中移除
v-show
: 根据表达式值的真假决定元素的显示隐藏
// isShow为true显示div 为false隐藏div
// v-show是操作div的样式 显示时添加 style = 'display:block'; 隐藏时添加style = 'display:none'
v-if 是删除DOM元素 效率比较低 会造成页面的结构重新绘制
v-show 是控制样式 只会改变当前这一个元素的样式 不会造成页面结构的重新绘制
私有过滤器是将过滤器中的方法直接绑定到当前Vue实例上面,所以 只能在当前实例托管区域中使用
new Vue({
el:'#app',
....
filters:{
// 每一个过滤器都是一个方法
`过滤器名称`:function(input,arguments){
// input 是使用过滤器时 管道符 前面的数据
// arguments 是过滤器方法自己的参数
return `对input进行处理的代码逻辑`
}
}
})
全局过滤器相当于是将过滤器中的方法绑定到了Vue构造函数的原型中,可以保证每一个Vue实例的托管区域都可以使用
Vue.filter('过滤器名称',function(input,arguments){
return `对input进行处理的代码逻辑`
})
{{需要被处理的数据 | 过滤器名称(arguments)}}
{{new Date() | datefmt('YYYY-MM-DD HH:mm:ss')}}
// 使用键盘修饰符
v-on:事件名称.`修饰符名称`
eg:
v-on:keydown.enter = 'func'
// vue1.0
Vue.driective('on').keyCodes.f2 = 113
// vue2.0
Vue.config.keyCodes.f2 = 113
Vue.driective('指令名称',function(){
// 在函数内部完成该指令的逻辑
// this.el 获取使用当前指令的元素
// this.vm 获取到的是当前指令所属的vue对象实例
// this.expression 获取到的是 指令等号后面所书写的表达式
})
Vue.directive('指令名称',{
inserted:function(el,binding){
// el 当前指令所在元素
// binding.expression 当前指令后面所跟表达式
// binding.value 当前指令表达式的值
}
})
// 课堂案例改写
Vue.directive('focus',{
inserted:function(el){
el.focus();
}
})
Vue.directive('color',{
// 当前指令所在元素插入到父节点中执行
inserted:function(el,binding){
// this.el.style.color = this.vm[this.expression];
console.log(binding);
// el是当前指令所在的DOM元素对象
// binding.value 是指令后面所跟表达式的值
// binding.expression 是指令后面所跟的表达式
// el.style.color = binding.value;
setTimeout(function(){
el.style.color = this.vm[binding.expression];
},0)
}
})
在vue2.0中推崇的是组件写法,所以不再有自定义元素指令
Vue.elementDriective('指令名称'{
bind:function(){
// 在函数内部完成该指令的逻辑
}
})
http://www.lovegf.cn:8899/api/getprodlist // 获取数据
// 使用当前vue实例调用get方法
this.$http.get('url',{是需要给后台发送的数据}.then(function(res){
// res.body 是获取到的响应数据
})
http://www.lovegf.cn:8899/api/addproduct // 提交数据
this.$http.post('url',{是需要给后台发送的数据},{emulateJSON:true}).then(function(res){
// res.body 是获取到的响应数据
})
http://www.lovegf.cn:8899/api/jsonp
// 使用当前vue实例调用get方法
this.$http.jsonp('url(此URL必须支持jsonp请求)',{是需要给后台发送的数据}.then(function(res){
// res.body 是获取到的响应数据
})
为什么存在jsonp? 浏览器存在同源策略:在浏览器发送请求的过程中,会检查当前发送请求的URL地址和当前发送请求所在的网页地址是否同协议 同域名.同端口,如果三者一致,则请求可以发送成功,如果不一致,则请求不能发送.
为了保证在跨域的情况下也能发送,则需要使用jsonp.
jsonp 原理?(利用script标签src属性可自动发送请求且不受同源策略限制的特性)
- 会动态创建一个script标签
- 将发送的URL地址拼接到script的src属性中,然后在URL地址后面拼接上一个回调函数名fn
- 后台接收到请求会去检查当前请求是否是jsonp请求,如果是,那么会将需要返回给客户端的数据进行封装,将数据放到回调函数的参数中 echo fn + '('需要返回的数据')',然后返回给客户端
- 客户端接收到数据后,会把字符串转成js代码去执行,相当于去掉用该函数,那么真实数据就在函数的参数中
- 删除script标签
CORS跨域:Cross Origin Resource Sharing 跨域资源共享 CORS跨域只需要后台在请求头中添加允许跨域的信息即可,客户端不需要修改任何代码
res.header("Access-Control-Allow-Origin", "*");
Vue 实例有一个完整的生命周期,也就是从开始创建、初始化数据、编译模板、挂载Dom→渲染、更新→渲染、卸载等一系列过程,我们称这是 Vue 的生命周期。通俗说就是 Vue 实例从创建到销毁的过程,就是生命周期。
钩子函数:一个系统内置的一批函数,这些函数会在系统运行的某一阶段或者某一时间点自动触发,进行事件的处理后又接着执行 后续任务
beforecreate : 可以在这加个loading事件,在加载实例时触发
created : 初始化完成时的事件写在这里,如在这结束loading事件,异步请求也适宜在这里调用
mounted : 挂载元素,获取到DOM节点
updated : 如果对数据统一处理,在这里写上相应函数
beforeDestroy : 可以做一个确认停止事件的确认框
1. vue1.0中标识循环遍历的每一项使用的是`track-by='$index'`
vue2.0中使用`:key= 'index'`,
vue1.0中有`$index`这个特殊属性,
vue2.0中没有.
2. vue1.0中遍历数组写法`(index,value) in list`
vue2.0中是`(value,index) in list`
3. vue1.0遍历对象写法`(key,value) in obj`
vue2.0中是`(value,key) in obj`
1. vue1.0中有系统提供的过滤器,如 json uppercase ...
vue2.0中全部去除系统过滤器
2. vue1.0和vue2.0中都有自定义过滤器
- 自定义全局过滤器
`Vue.filter('过滤器名称', function (管道符号|左边参数的值,其他参数1,其他参数2,....) {
return 对管道符号|左边参数的值做处理以后的值
})`
- 自定义私有过滤器(定义在 VM中的filters对象中的所有过滤器都是私有过滤器)
new Vue({
...
filters:{
'过滤器名称':function(管道符号|左边参数的值,其他参数1,其他参数2,....){
return 对管道符号|左边参数的值做处理以后的值
}
}
});
1、vue1.0中,需要在实现过渡动画的元素上使用 transition 特性,示例:
,my-transition 可以有程序员自定义名称
2、 vue2.0中 transition特性的写法变成了 的写法
hello
3. 动画钩子函数
vue1.0中动画钩子函数
- 过渡动画进入
beforeEnter:function(el){} 过渡动画进入之前,一般在这个方法中定义目标元素的初始位置
enter:function(el,done){} 过渡动画进入中,在这个方法中定义目标元素的结束位置
afterEnter:function(el){} 过渡动画结束后,通常在这个方法里面重置初始值
enterCancelled:function(el){} 取消过渡动画时被调用
- 过渡动画离开
beforeLeave:function(el){} 动画离开之前触发
leave:function(el){} 过渡动画进入中触发
afterLeave:function(el){} 过渡动画离开结束后
leaveCancelled:function(el){} 取消过渡动画时被调用
vue2.0中动画钩子函数
- 过渡动画进入
before-enter 过渡动画进入之前,一般在这个方法中定义目标元素的初始位置
enter 过渡动画进入中,在这个方法中定义目标元素的结束位置
after-enter 过渡动画结束后,通常在这个方法里面重置初始值
enter-cancelled 取消过渡动画时被调用
- 过渡动画离开
before-leave 动画离开之前触发
leave 过渡动画进入中触发
after-leave 过渡动画离开结束后
leave-cancelled 取消过渡动画时被调用
1.14.1.1. 组件定义方式一
// 1. 定义组件
var `组件名称` = Vue.extend({
template:'模板(一般为HTML结构)'
});
// 2. 注册组件
Vue.component('login',login);
1.14.1.2. 组件的定义方式二
Vue.component(`组件名称`,{
template:'模板(一般为HTML结构)'
});
1.14.1.3. 组件的定义方式三
// 书写HTML结构
Vue.component('account',{
// #account 是template标签的ID
template:'#account',
});
// 将组件名称当做HTML标签使用,显示的内容就是组价定义时模板里面的内容
Vue.component('account',{
// #account 是template标签的ID
template:'#account',
});
- 子组件需要在父组件中的
components
属性里面进行定义,- 子组件需要在父组件的模板中使用
// 父组件模板
// 子组件只能在父组件模板中使用
Vue.component('account',{
// #account 是template标签的ID
template:'#account',
...
// 在components属性内部定义子组件
components:{
// 子组件名称:子组件对象
`login`:{
template:'子组件模板或者模板ID ',
components:{
'abc':{
template:"这是login的子组件
"
}
}
}
},
data:function(){
retunr {
msg:'我是组件内部定义的数据'
}
},
methods:{
fn:function(){
console.log(this.msg);
}
}
});
new Vue()
也是一个组件(通常称作根组件),这个组件的模板就是该实例的托管区域;一个组件也是一个vue实例; 使用Vue.component
定义出来的组件 是根组件new Vue()
实例的子组件组件内部定义数据
data
属性是一个方法,方法内部返回一个对象子组件定义在父组件
components
属性内部,子组件的使用必须写在父组件模板中
Vue2.0
组件模板内部的代码必须写在一个根元素内部(通常都是用一个div包裹所有其他元素)没有根元素时错误信息
Component template should contain exactly one root element
模板书写时按照以下格式
// 书写HTML结构
vue2.0中sub
不能作为组件名称
组件名称首字母如果是大写字母,使用时使用小写字母;组件名称中间某个字符是大写字母,使用时使用连字符-
new Vue({
el:'#app',
components:{
"UserLogin":{
template:'我的名字包含大写字母
'
}
}
})
1.15. 组件传值
1.15.1. 父组件向子组件传值
-
在子组件内部定义一个props属性,然后在这个属性内部定义变量用来接收父组件传过来的数据
-
在父组件中使用子组件时,在子组件上面绑定一个和子组件内部props里面定义的变量同名的属性
-
把父组件data中定义的数据(需要传递的数据) 作为 子组件绑定的属性的属性值进行传递
子组件sonComponent
父组件fatherComponent
sonComponent:
1. 定义props数组对象,数组对象中的属性用于接收父组件传递过来的数据
new Vue({
props:['id'], // id即为用于接收父组件传递过来数据的属性
})
fatherComponent:
1. 使用子组件时绑定子组件props中定义的属性进行传值
// 这里的id需要和子组件props中定义的属性一致
1.15.2. 子组件向父组件传值
发布 - 订阅者模式
-
在子组件中触发 this.$emit('消息名称','消息所携带的数据') 进行消息的发布
-
在父组件中使用子组件时 注册一个和 ‘消息名称’ 一致的事件,同时给定一个事件处理函数,这个事件处理函数是在父组件中进行定义的.
-
消息所携带的数据就父组件中定义的事件处理函数的参数中
子组件sonComponent
父组件fatherComponent
sonComponent:
1. 发布事件
this.$emit('事件名称','需要传递的数据');
2. 事件的触发
send(){
this.$emit('事件名称','需要传递的数据')
}
fatherComponent:
1. 订阅事件
// 父组件中使用子组件(`事件名称`和子组件中`this.$emit('事件名称','需要传递的数据')`里的事件名称一致)
2. 获取数据
methods:{
事件处理函数:function(data){
// data 就是子组件sonComponent中需要传递的数据
}
}
1.15.3. 非父子组件传值
使用event bus(事件总线):利用一个共享的vue实例对象来进行数据的传递. 同时采用的是 发布-订阅者模式
componentA componentB进行数据传递(B->A)
**定义一个公有的Vue实例,保证两个组件都能够使用,一般在一个单独的js文件中导出一个Vue实例,
然后在componentA和componentB组件中导入该实例进行使用**
export default var vm = new Vue();
componentB:(B组件时需要传递数据的组件)
1. 进行事件的发布(注册)
vm.$emit('事件名称','需要传递的数据')
2. 事件的触发(用于发布事件)
send(){
vm.$emit('事件名称','需要传递的数据')
}
componentA:(A组件是接收数据的组件)
1. 订阅事件
vm.$on('事件名称',function(data){
// 此处的data就是 发布组件中传递过来的数据
})
1.16. v-el和v-ref
vue1.0中使用v-el获取DOM元素 使用v-ref获取组件
vue2.0中统一使用ref属性获取DOM元素和组件
// 获取DOM this.$refs.mydiv
// 获取组件 this.$refs.myaccount
1.17. vue-router的使用
- 使用指定点击元素后需要跳转的路径
- 在创建出来的VueRouter对象中定义路由规则,路由规则就是规定一个路径对应哪一个组件
- 使用进行占位,作用就是将来每一个组件都会被渲染到当前这个位置
new VueRouter({
routes:[
// 一个对象就是一个路由规则
// path后面的路径需要和router-link中to属性 路径一致
// 组件对象需要提前定义
{path:'路径',component:组件对象}
]
})
1.17.1. 基本步骤
1. 使用`router-link`定义跳转路径
账号
2. 使用`router-view`进行占位,以便于显示组件
3. 定义跳转路径对应的需要显示的组件
// 实际项目中一个文件就是一个组件,所以应该是直接引入组件
var account = Vue.extend({
template:'账号
'
});
var login = Vue.extend({
template:'登录
'
});
4.实例化路由对象并配置路由规则
var router = new VueRouter({
routes:[
{
path:'/account',
component:account,
children:[
{
path:'login',
component:login,
}
]
},
]
});
5. 开启路由
new Vue({
el :'#app',
router : router //启动路由对象
});
1.17.2. 嵌套路由注意事项
1、定义路由规则清单的时候,使用children
属性定义子路由,children
下面的子路由规则path中的文本字符串是不需要加/的,否则无效
2、嵌套路由的上层路由中的path要加 /,并且template
中要增加
3、修改
1.17.3. 路由传参
-
修改路由规则为带有参数形式{path:'/路径/:参数名称',component:组件对象}
-
使用
进行传参,将需要传递的值放到路径后面,用/分隔
-
使用this.$router.params.参数名称获取参数值
1.18. watch和computed计算属性的使用
1.18.1. watch的使用
watch
可以监测data
中的数据变化,然后触发定义的方法执行操作。
new Vue({
...
data:{
name:'zxx'
},
watch:{
// 监控的是data中已经定义过的数据
'name':function(newval,oldval){
// 只要将来name值发生变化,就会自动触发这个方法
// newval 表示name属性变化后的值 oldval表示变化前的值
},
/*特殊:watch可以监控路由对象*/
'$route':function(newroute,oldroute){
// 只要vue中集成了vue-router,watch就可以监控路由的变化
}
}
})
1.18.2. computed的使用
使用computed
定义的属性就相当于data
中定义的数据属性一样,只不过computed
里面定义的属性值是通过计算得到的。
new Vue({
...
data:{
name:'zxx',
age:18
}
computed:{
// 定义一个计算属性info
info:function(){
// 进行计算,然后返回
// 计算属性的值就是这里返回的值 'zxx18'
// 如果将来this.name和this.age任何一个数据发生变化,都会重新触发这个函数进行计算
return this.name + this.age
}
}
})
2. webpack 的学习
2.1. webpack 和 gulp 的区别
gulp是工具链、构建工具,可以配合各种插件做js压缩,css压缩,less编译 替代手工实现自动化工作
-
构建工具
-
自动化
-
提高效率用
webpack是文件打包工具,可以把项目的各种js文、css文件等打包合并成一个或多个文件,主要用于模块化方案,预编译模块的方案
-
打包工具
-
模块化识别
-
编译模块代码方案用
2.2. npm相关指令
全局安装 -g:
全局安装的包位于Node.js环境的node_modules目录下,全局安装的包一般用于命令行工具
C:\Users\LEO\AppData\Roaming\npm
本地安装:
本地安装的包在当前目录下的node_modules里面,本地安装的包一般用于实际的开发工作
npm常用的命令:
1、安装包(如果没有指定版本号,那么安装最新版本)
npm install -g 包名称 (全局安装)
npm install 包名称 (本地安装)
2、安装包的时候可以指定版本
npm install -g 包名称@版本号
3、卸载包
npm uninstall -g 包名
4、更新包(更新到最新版本)
npm update -g 包名
5、查看包信息
npm info 包名
开发环境(平时开发使用的环境)
生产环境(项目部署上线之后的服务器环境)
--save 向生产环境添加依赖 dependencies
--save-dev 向开发环境添加依赖 DevDependencies
2.3. 安装webpack
1. 全局安装 nrm: `npm install nrm -g`
2. 查看镜像源 `nrm ls`
3. 切换淘宝镜像源 `nrm use taobao`
4. 全局安装webpack `npm install [email protected] -g`
2.4. webpack 进行代码打包
导出一个模块 `module.exports = 需要导出的对象`
导入一个模块 `var 模块名 = require(文件路径)`
webpack 打包命令
`webpack 需要打包的文件名 输出的文件名`
例如:
`webpack main.js build.js`
2.5. webpack 配置文件
1. 默认配置文件名称webpack.config.js
module.exports = {
entry:'*需要打包的文件*' // 路径+文件名 一般为 ./src/xxx.js
output:{
path:'*输出文件的路径*' // 绝对路径 使用__dirname + 路径
filename:`*输出文件的名称*` // 一般都为build.js/bundle.js
}
}
2. 使用webpack进行打包
- 如果是默认配置文件 则直接在命令行中 输入 `webpack`
- 如果是其他改过名字的配置文件 则使用 `webpack --config 配置文件名`
2.6. webpack loader的使用
loader:预处理器。在js代码执行之前需要执行的一些处理。
2.6.1. css-loader
css-loader 是进行css解析,能够使浏览器正常识别js文件中导入的 css 文件
1. 初始化package.json
npm init
2. 安装css-loader以及style-loader
npm install style-loader css-loader --save-dev
3. 在webpack.config.js文件中进行配置
module:{
loaders:[
{
test: /\.css$/,
loader:'style-loader!css-loader'
}
]
}
2.6.2. sass-loader 的使用
sass-loader是进行scss文件的解析
1. 安装sass-loader
npm install node-sass sass-loader style-loader css-loader --save-dev
2.配置sass-loader
loaders:[
{
test: /\.scss$/,
loader:'style-loader!css-loader!sass-loader'
}
]
2.6.3. less-loader 的使用
less-loader是进行less文件的解析
1. 安装scss-loader
npm install less less-loader style-loader css-loader --save-dev
2.配置scss-loader
loaders:[
{
test: /\.less$/,
loader:'style-loader!css-loader!less-loader'
}
]
2.6.4. url-loader 的使用
url-loader是进行url资源的解析
1. 安装url-loader
`npm install file-loader url-loader --save-dev`
2.配置url-loader
loaders:[
{
test: /\.(png|jpg|gif|ttf)$/,
loader:'url-loader!limit=20000&name=images/[hash:8].[name].[ext]'
// limit单位是字节 1kb = 1024b(字节)
// 对于比较小的图片资源可以使用limit进行限制
// 小于limit值转换成base64字符串内嵌到js代码中
// 大于limit值的图片才转成URL进行网络请求
}
]
2.6.5. webpac-dev-server的使用
1. 安装webpack-dev-server
npm install [email protected] [email protected] --save-dev
2. 安装自动生成HTML文件的插件
npm install [email protected] --save-dev
3. 修改package.json文件
"scripts": {
"dev": "webpack-dev-server --hot --inline --open --port 5008"
},
4. 配置webpack.config.js中的内容
- 引入html-webpack-plugin
`var htmlWP = require('html-webpack-plugin');`
- 在modul.exports中加入
plugins:[
new htmlWP({
title: '首页', //生成的页面标题
filename: 'index.html', //webpack-dev-server在内存中生成的文件名称,自动将build注入到这个页面底部,才能实现自动刷新功能
template: 'template.html' //根据template.html这个模板来生成(这个文件程序员自己书写)
})
]
5. 运行 npm run dev
2.6.6. babel-loader的使用
babel-loader是用来将es6语法转换成es5语法
1. 安装babel-loader
`npm install [email protected] [email protected] [email protected] [email protected] --save-dev`
2. 配置webpack.config.js文件
{
test: /\.js$/, // 将.js文件中的es6语法转成es5语法
loader:'babel-loader',
exclude:/node_modules/ // 排除node_modules文件夹下的js文件不用被转换
}
3. 配置babel的转码规则
babel:{
presets:['es2015'], // 配置将es6语法转换成es5语法
plugins:['transform-runtime'] // 用来解析vue文件
}
2.7. webpack解析vue文件
2.7.1. 安装vue-loader解析.vue文件
1. 安装相关包
`npm install vue [email protected] vue-template-compiler [email protected] --save-dev`
2. 配置webpack.config.js文件
{
test: /.vue$/, // 解析 .vue 组件页面文件
loader:'vue-loader'
}
2.7.2. .vue文件基本代码结构
一个.vue文件就是一个vue的组件
// 1. 组件模板
// 2. 负责导出vue的对象
// 3. 书写组件内部的样式
2.7.3. 项目入口文件main.js中渲染组件
// 1.0 导入vue核心包
// 凡是使用npm安装的包 引入的时候都不需要写相对路径 只需要写包名即可
import Vue from 'vue';
// 2.0 导入App.vue的vue对象
import App from './App.vue';
// 3.0 利用Vue对象进行解析渲染
new Vue({
el:'#app',
render:function(create){return create(App)} //es5的写法
// render:c=>c(App) // es6的函数写法 =>:goes to
});
2.8. 使用webpack以及npm创建项目
1. 创建项目文件夹
2. 创建npm的配置文件package.json
npm init -y
3. 创建webpack配置文件(webpack.config.js)
4. 根据项目需求安装所需要使用的模块
npm install 包名 --save-dev
3. 其他
3.1. ES6语法使用总结
1、对象的写法
es5中对象: {add:add,substrict:substrict}
es6中对象: {add,substrict} 注意这种写法的属性名称和值变量是同一个名称才可以简写,否则要想es5那样的写法,例如: {addFun:add}
2、在对象中的方法的写法
es5中对象: {add:function(){},substrict:function(){}}
es6中对象: {add(){},substrict(){}}
3、对象的导出写法
es5两种形式:
1、module.exports = fucntion (){};
2、exprots.add = fucntion (){};
es6中写法:
1、export default{
add(){}
}
2、export fucntion add(){} 相当于 将add方法当做一个属性挂在到exports对象
4、对象的导入
es5: var add = require('./calc.js');
es6:
如果导出的是:export default{ add(){}}
那么可以通过 import obj from './calc.js'
如果导出的是:
export fucntion add(){}
export fucntion substrict(){}
export const PI=3.14
那么可以通过按需加载 import {add,substrict,PI} from './calc.js'
5、es6中的箭头函数的写法
箭头的演变过程:
//需求:利用函数实现倒序排列
[2,1,3].sort(function(x,y){return y - x;});
//用箭头函数实现 =>读 goes to
[2,1,3].sort((x,y)=>{return y - x;});
[2,1,3].sort((x,y)=> {x++;y++; y - x;});
[2,1,3].forEach(x=> {console.log(x)});
3.2. vue-router集成
1. 安装vue-router
`npm install vue-router --save`
2. App.vue中书写跳转链接
登录
注册
3. main.js中集成vue-router并配置路由规则
// 1. 导入vue-router
import vueRouter from 'vue-router';
// 2. 将vueRouter对象绑定到Vue对象上
Vue.use(vueRouter);
// 3. 导入路由规则对应的组件对象
import login from './components/account/login.vue';
import register from './components/account/register.vue';
// 4.定义路由规则
var router1 = new vueRouter({
routes:[
{path:'/login',component:login},
{path:'/register',component:register}
]
});
// 5. 利用Vue对象进行解析渲染
new Vue({
el:'#app',
// 使用路由对象实例
router:router1,
render:c=>c(App)
});
3.3. mint-ui的使用
1. 安装mint-ui
npm install mint-ui --save
2. 在项目入口文件main.js中配置mint-ui
- 导入mint-ui
import mint from 'mint-ui'
- 在vue中注册mint-ui
Vue.use(mint)
3. 使用csscomponents
- 在main.js中导入css样式
import 'mint-ui/lib/style.min.css';
- 在vue的组件中使用mint-ui提供的控件
4. 使用jscomponents
- 在vue组件内部的script标签中按需导入需要使用的控件
import {js组件名称} form 'mint-ui'
- 在js代码中使用mint-ui提供的控件
3.4. git 常用命令
git config --global user.name "用户名"
git config --global user.email "邮箱账号"
// 创建版本库
git init
// 添加文件到缓存区
git add ./
// 提交信息
git commit -m '说明信息'
// 推送到远程仓库
git push -u orign master
// 查看仓库状态
git status
// 查看提交记录
git log --oneline
// 查看版本切换记录
git reflog
// 版本回退
git reset --hard 版本号
// 回到主分支
首先git checkout -b temp
其次git checkout master
3.5. 项目学习
1. 克隆我的代码
`git clone https://git.oschina.net/UniverseKing/vue_system.git`
2. 将版本进行回退到项目框架搭建位置
git log --oneline
git reset --hard 版本号
3. 复制回退后的代码文件(不需要.git文件夹)到自己的项目文件夹里面
4. 在自己的项目文件夹里面执行`npm install`
5. 开始功能开发
3.6. vscode 代码片段
文件 - 首选项 - 用户代码片段 - 搜索vue(选择vue) - 将以下代码复制到{}
中
"Create vue template": {
"prefix": "vuec",
"body": [
"",
" ",
" ",
"",
"",
""
],
"description": "Create vue template"
}
3.7. vetur插件配置
先安装好vetur插件。然后 文件 - 首选项 - 设置 - 用户设置 - 将以下代码复制到{}
中
"emmet.syntaxProfiles": {
"vue-html": "html",
"vue": "html"
}
4. 补充
4.1. 大型复杂项目中数据状态管理
复杂项目中数据的传递和管理一般不会用到event bus
,因为如果订阅者过多,无法准确的知道数据的流向.所以对于大型项目应该使用Vue
提供的vuex
进行数据管理
官方文档https://vuex.vuejs.org/zh-cn/
1. 安装vuex
npm install vuex --save
2. main.js中引入安装
import Vuex from 'vuex';
Vue.use(Vuex);
3. 配置vuex
//Vuex配置
const store = new Vuex.Store({
// state类似vue实例中的data 用来存放数据
state: {
// 可以设置一些需要全局使用的数据
username:'zxx'
},
// mutations类似vue实例中的methods
mutations: {
// 用来处理数据 比喻数据删除更新等操作
// 第一个参数state是固定写法 第二个参数表示的是需要修改成的数据
update(state,name){
state.username = name;
}
}
})
3. 组件中通过this.$store使用
console.log(this.$store.state.username);
4. 调用mutations方法更新数据
// 第一个参数是 mutations 中定义的对应的方法名 第二个参数是需要更新的数据
// 具体更新逻辑在update方法中实现
this.$store.commit('update','lxy');调用update方法更新用户名
5.组件内监视state中的数据更新
import { mapState } from 'vuex';
// mapState可以将vuex实例state中定义的属性 映射成为当前组件中的计算属性
// 同时可以保证在计算属性的方法体中可以使用state中的属性
computed: mapState({
username: state => state.username
// username:function(state){return state.username};
})
4.2. vue-cli命令行工具搭建spa应用
1、在cmd命令面板中执行:npm install --global vue-cli 全局安装 vue-cli
2、利用:vue init webpack projectName(自定义项目名称) 创建一个基于webpack模板的新项目
3、进入到项目名称文件夹中执行 npm install 安装项目所需依赖
4、运行 npm run dev 运行项目
4.3. vue项目引入公共js文件
> 如果需要将公共js文件引入到main.js文件中使用,可以引入后将模块注入到Vue的原型中
// main.js
import common from 'common.js';
Vue.prototype.$common = common;
// Object.definePrototype(Vue.prototype, '$common', { value: common });
// 其他文件使用
this.$common就是引入的common对象
4.4. vue插件开发
// common.js文件
var obj = {
apidomain:'http://www.lovegf.cn:8899', // 所有数据请求的根域名地址
}
export default {
install: function(Vue) {
Object.defineProperty(Vue.prototype, '$common', { value: obj });
}
}
// main.js文件
import common from 'common';
Vue.use(common);
// 其他文件使用
this.$common
4.5. vue-router路由拦截
// 1. 设置路由规则时进行拦截
{
path: '/userinfo',
component: userinfo,
meta: {
requireAuth: true, // 添加该字段,表示进入这个路由是需要登录的
},
beforeEnter: (to, from, next) => {
if (to.meta.requireAuth) { // 判断该路由是否需要登录权限
if (getCookie('session')) { // 通过vuex state获取当前的token是否存在
next(); // 存在就进入userinfo
}
else {
next({
path: '/login',
query: { redirect: to.fullPath } // 将跳转的路由path作为参数,登录成功后跳转到该路由
})
}
}
else {
next();
}
}
}
// 2. 登录成功后跳转路由
this.$router.push('/userinfo');
4.6. vue-router路由模式
var router = new vueRouter({
// 设置路由模式
mode: 'hash',
// hash带锚点 history不带锚点
// hash可以将页面放到其他浏览器或标签打开 history不可以(服务端渲染解决)
})
4.7. SPA应用性能优化
4.7.1. 服务端渲染
问题:1.单页面应用不利于SEO,因为所有HTML文档都是由js动态生成的。2.首次加载速度过慢。
4.7.2. 分离css
1. 安装插件
npm install [email protected] --save-dev
2. 修改css-loader配置
loader: ExtractTextPlugin.extract("style-loader", "css-loader")
3. plugin配置中使用插件
new ExtractTextPlugin('app.css'),
4.7.3. 分离第三方包
1. 引入webpack
var webpack = require('webpack');
2. 修改入口文件
entry: {
app: path.resolve(__dirname, 'src/main.js'),
// 需要分离的第三方包名写在数组中
vendors: ['vue', 'vue-resource', 'vue-router', 'vuex', 'mint-ui', 'moment', 'vue-preview']
},
3. plugin中配置插件
// 分离第三方包插件
new webpack.optimize.CommonsChunkPlugin({
name: 'vendors',
filename: 'vendors.js'
})
4.7.4. 代码压缩
1. html代码压缩
new htmlwp({
title: '首页', //生成的页面标题首页
filename: 'index.html', //webpack-dev-server在内存中生成的文件名称,自动将build注入到这个页面底部,才能实现自动刷新功能
template: 'template.html', //根据index1.html这个模板来生成(这个文件请程序员自己生成)
// 代码压缩
minify: {
// 删除注释
removeComments: true,
// 删除空格
collapseWhitespace: true,
// 删除空格缩进
removeAttributeQuotes: true
}
}),
// 2. js代码压缩混淆插件
new webpack.optimize.UglifyJsPlugin({
beautify: false,
mangle: {
screw_ie8: true,
keep_fnames: true
},
compress: {
warnings: false,
screw_ie8: true
},
comments: false
}),
// 3. 删除警告
new webpack.DefinePlugin({
'process.env': {
// 注意字符串被引号引起来
NODE_ENV: '"production"'
}
})
5. 扩展
-
现在流行的三大框架,angular,vue,react;希望老师从具体应用的角度,介绍一下它们的优劣,长处短处,应用范围,前景,性能等等。
Angular的适用领域相对窄一些,React可以拓展到服务端,移动端Native部分,而Vue因为比较轻量,还能用于业务场景非常轻的页面中
// react && vue
使用 Virtual DOM
提供了响应式(Reactive)和组件化(Composable)的视图组件。
将注意力集中保持在核心库,伴随于此,有配套的路由和负责处理全局状态管理的库。
angular
框架体系非常大,面面俱到
vue: 双向数据绑定 观察者模式
angular: 双向数据绑定 脏值检测
react : 单向数据流
angular-cli:
npm i angular-cli -g
ng new project
ng serve
-
vue能不能设置全局的方法,让每个组件都能调用那个方法
1. 在一个js文件中书写方法进行导出
export function fn(){console.log('我是每一个组件都需要使用的方法')};
2. 在项目入口文件main.js中引入该js文件,并将该方法绑定到Vue的原型中
import fn from './xxx.js'
Vue.prototypr.fn = fn;
3. 项目中的.vue文件,即其他组件都可以使用该方法
this.fn(); // 我是每一个组件都需要使用的方法
-
项目开始的配置单
https://git.oschina.net/UniverseKing/vue_coding.git
-
如果想写一些原生的js 的话不知道该怎么写,还有如果用less写css的话怎么引入各组件里面?
1. 原生js依旧写到单独的js文件中,然后对其内容进行导出,在其他组件中使用。
2. 将原生js写到.vue组件中的script标签中
-
各个包的作用以及怎么用跟我们好好把思路帮我们整理一下。
Vue: 框架核心
webpack: 用来对模块进行打包的一个工具(打包就是一个解析,编译的过程,解析的就是浏览器不能识别的语法)
webpack-dev-server: 一个webpack的插件,内置了express的node服务器,用于在开发阶段编译代码,实现热更新加载等功能
vue-resource: 实现vue的ajax请求库
vue-router: 实现 vue 的路由库
vuex: vue状态(数据)管理库
babel: 语法解析器,可以将很多浏览器不能识别的语法转换成可识别的es5语法.es6->es5 , vue->es5
html-webpack-plugin:一个webpack的插件,用于webpack编译时自动根据模板生成一个index.html文件
-
vue axios请求跟vue-resource有什么区别?
axios使用:
1. 安装 axios
npm install axios --save
2. 因为axios不支持Vue.use()方法,所以为了所有组件能够使用,需要绑定到Vue原型中
import axios from 'axios';
Vue.prototype.$http = axios
3. 发送请求参照vue-resource
// get请求
this.$http.get(url).then(function(res){
// 返回的响应数据在res.data属性中
console.log(res.data);
// 回调函数内部的this不是当前数据请求方法的调用者
// 通常内部this是window 在node平台 内部this是undefined
})
// 一般使用箭头函数写法
this.$http.get(url).then((res)=>{
console.log(res.data);
})
// post请求(Content-Type:application/x-www-form-urlencoded 时需要配合qs.stringify使用)
npm install qs --save;
import qs from 'qs';
this.$http.post(url,qs.stringify({数据}).then(function(res){
// 返回的响应数据在res.data属性中
console.log(res.data);
})
也可以参照https://github.com/imcvampire/vue-axios配合使用,支持使用Vue.use()