Vue教程
文章目录
1.介绍
1.1简介
描述:
- 渐进式 JavaScript 框架
- 作者: 尤雨溪(一位华裔前 Google 工程师)
- 作用: 动态构建用户界面
Vue 的特点:
- 遵循 MVVM 模式
- 编码简洁, 体积小, 运行效率高, 适合移动/PC 端开发
- 它本身只关注 UI, 可以轻松引入 vue 插件或其它第三库开发项目
与其它前端 JS 框架的关联
- 借鉴 angular 的模板和数据绑定技术
- 借鉴 react 的组件化和虚拟 DOM 技术
1.由于先出来angular框架,然后再出来react框架,那么vue就借鉴这两种框架的技术
2.说白了,vue和jQuery一样,是一个js框架,简化dom操作,支持双向绑定,使我们js开发更加简单高效,而且vue上手快,体积小
1.2 vue插件制作
1.下载工具源码 https://github.com/vuejs/vue-devtools
2.执行cnpm install
,安装相关依赖
3.执行打包构建,cnpm run build
4.修改配置项为true,必须要修改,不然后面插件用不了
5.打开谷歌浏览器,更多工具-扩展程序,然后找到我们编译好的工具目录里,找到chrome文件夹进行加载即可
1.3 helloword
1.创建一个vue项目
2.添加相关代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>01_HelloWorld</title>
</head>
<body>
<!--
1. 引入Vue.js
2. 创建Vue对象
el : 指定根element(选择器)
data : 初始化数据(页面可以访问)
3. 双向数据绑定 : v-model
4. 显示数据 : {{xxx}}
5. 理解vue的mvvm实现
-->
<!--模板-->
<div id="test">
<input type="text" v-model="msg"><br><!--指令-->
<p>hello {{msg}}</p><!--大括号表达式-->
</div>
<script type="text/javascript" src="../js/vue.js"></script>
<script type="text/javascript">
const vm = new Vue({ // 配置对象 options
// 配置选项(option)
el: '#test', // element: 指定用vue来管理页面中的哪个标签区域
data: {
msg: 'atguigu'
}
})
</script>
</body>
</html>
普通方式(src)引入vue:
<!--body必须要放到最前面,因为vue实例化的时候,需要从上到下找到相关html节点,若没找到html则无法绑定而报错-->
<body>
<div id="app" class="aa">
<h1>{{msg}}</h1>
</div>
</body>
</html>
<!--引入核心js文件-->
<script src="js/vue.js"></script>
<!--书写vue的代码-->
<script>
new Vue({
el:"#app", //el: element 元素 代表vue实例的作用范围,即app这个节点下的所有{{}}都能取到data里的数据
data:{
msg:"你好vue",
count:0,
content:"hello vue"
} //data 数据 自定义各种数据
});//创建一个vue实例
</script>
# 总结:
1.一个页面中只能存在一个Vue实例 不能创建多个vue实例
2.vue实例中el属性代表vue实例的作用范围,日后再vue实例作用范围内可以使用{{data属性中变量名}} 直接获取data中变量名对应属性值
3.vue实例中data属性用来给当前vue实例绑定自定义数据,日后绑定数据可以在vue实例作用范围内直接使用 {{变量名}}方式获取
4.使用{{}}进行data中数据获取时,可以在{{}}取值语法中进行 算数运算 逻辑运算以及调用相关类型的相关方法
5.vue实例中el属性可以书写任何css选择器 但是推荐使用id选择器 因为一个vue实例只能作用于一个具体作用范围
1.4 mvvm理解
页面操作html组件对象,vm实例里有监听器,当组件对象里的数据改变时,会同步修改data数据模型的数据,若data数据模型的数据改变了,又会影响页面数据的显示。
1.5 声明周期
在vue实例生命周期过程中官方提供一系列声明周期函数 钩子: 这些生命周期函数最大特点伴随着vue实例过程自动触发的
vue 实例生命周期阶段: 1.初始化阶段 2.运行阶段 3.销毁阶段
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jUpkFp2H-1630407740613)(https://gitee.com/cfmCode/drawing-bed/raw/master/img/lifecycle-生命周期(图示版)].png)
<script src="js/vue.js"></script>
<script>
//在vue实例生命周期过程中官方提供一系列声明周期函数 钩子: 这些生命周期函数最大特点伴随着vue实例过程自动触发的
//vue 实例生命周期阶段: 1.初始化阶段 2.运行阶段 3.销毁阶段
var app = new Vue({
el:"#app",
data:{
msg:"vue生命周期",
users:[],
},
methods:{},
computed:{},
//初始化阶段
beforeCreate(){//第一个生命周期函数 这个函数执行时 仅仅完成自身内部事件和生命周期函数注入
console.log("beforeCreate:",this.msg);
},
created(){//第二个生命周期函数 这个函数执行时 完成自身内部事件和生命周期函数注入 包括自定义data methods computed等属性注入和校验工作
console.log("created:",this.msg);
//var _this = this;
//axios.get().then(function(response){_this.users = response.data})
},
beforeMount(){//第三个生命周期函数 这个函数执行时 el执行html还是一个原始模板 并没有完成数据渲染工作
console.log("beforeMount:",document.getElementById("h1").innerText);
},
mounted(){//第四个生命周期函数 这个函数执行时 vue已经完成template和el执行html渲染工作
console.log("beforeMount:",document.getElementById("h1").innerText);
},
//运行阶段
beforeUpdate(){ //运行阶段第一个函数 这个函数执行时 data数据发生变化,此时页面数据还是原始数据
console.log("beforeUpdate data:", this.msg);
console.log("beforeUpdate view:",document.getElementById("h1").innerText);
},
updated(){//运行阶段第二个函数 这个函数执行时 data数据页面数据保持一致
console.log("updated data:", this.msg);
console.log("updated view:",document.getElementById("h1").innerText);
},
//销毁阶段
beforeDestroy(){//销毁时第一个函数 这个函数执行时 vue实例刚刚开始销毁
console.log("beforeDestroy:","开始销毁");
},
destroyed(){
console.log("destroyed:","全部销毁");
}
})
2.使用
2.1 vue常用属性
2.1.1 el挂载点
el是用来设置Vue实例挂载(管理)的元素
-
Vue会管理el选项中的元素以及其内部的后代元素
-
可以使用其他选择器,但建议使用ID选择器
比如:#app .app
-
可以使用其他的双标签,但不能作用于html和body标签
2.1.2 data属性
1.Vue中用到的数据都定义在data中,即我们可以通过{{}}
来取值
2.data中可以写复杂类型的数据
const vm = new Vue({
el: '#app',
data: {
msg: 'atguigu',
school: {
name: 'xiaoming',
age: 18
}
}
})
3.渲染复杂类型的数据时,遵循js的语法即可
比如 {{school.name}}
2.2 vue指令
vue指令是以==v-==开头的一组特殊语法
2.2.1 v-text
1.用来设置标签(比如p,span等)的文本内容(textContent),内部支持写表达式
2.默认会替换全部内容,可以使用差值表达式替换部分指定内容
2.2.2 v-html
1.用来设置元素的innerHTML
2.内容中有html结构的会被解析会标签
3.v-text无论什么内容都会解析成文本
4.若只解析为文本,那么html和text都是一样的,若需要解析html结构的,就必须使用v-html
# 总结:
v-text 和 v-html: 作用: 用来获取vue实例中data属性声明数据 使用语法: 在哪个标签上获取直接在哪个标签上定义v-text v-html 在v-text="属性名"
{{}} 取值 和 v-text 取值区别:
1.{{}}取值不会将标签原始数据清空 使用v-text取值清空标签原始数据 {{}}===>这种方式取值 插值表达式
2.{{}}取值存在插值闪烁 v-text v-html取值 不存在插值闪烁
推荐: 两种方式都可以使用 {{}} 更加灵活
v-text (innerText)、 v-html (innerHtml)区别:
1.使用v-text取值:直接将获取数据渲染到指定标签中
2.使用v-html取值:先将获取数据进行html标签解析,解析之后在渲染到指定标签中
2.2.3 v-on
1.为元素绑定事件
2.事件名前不需要on,指令可以简写成@,绑定的方法定义在methods属性中
3.方法内部通过this关键字可以访问定义在data中的数据
4.事件的后面跟上==.修饰符==可以对事件进行限制
5.事件绑定的方法写成函数形式,可以自定义参数,用来接收传入的实参
# 总结:
js中事件(event): 事件三要素:
事件源: 发生特定动作html标签
事件: 发生特定动作事件 单击事件 onclick ondblclick onmouseover onmouseout keyup keydown .....
监听器: 事件处理程序 一般在js中是事件处理函数 function(){}
v-on 指令: 作用: 用来给页面中标签绑定事件用的 语法: 在对应标签上使用v-on:事件名="事件处理函数名"
v-on指令: 用来给对应标签绑定特定事件
v-on指令简化写法 @ 语法: @事件名=事件处理函数名
原始定义函数: 函数名:function(){} =====> 简化函数: 函数名(){}
2.2.3.1 事件修饰符
事件修饰符:
.stop 作用: 用来阻止事件冒泡 用来阻止事件继续向外传递
.prevent 作用: 用来阻止标签的默认行为
.self 作用: 只监听自身标签触发的事件
.once 作用: 该事件只触发一次
语法: @事件名事件修饰符="事件处理函数"======> @click.stop="test"
<div style="width: 200px;height: 200px;background: red" @click="parent">
//@click.stop 表示 child1点击后,事件只在child1和child触发
<div style="width: 100px;height: 100px;background: aquamarine" @click.stop="child">
<div style="width: 50px;height: 50px;background:royalblue" @click="child1">
</div>
</div>
</div>
2.2.3.2 按键修饰符
事件修饰符: 用来对事件一些列描述修饰
按键修饰符: 用来对键盘按键事件进行修饰 修饰符
keyup keydown ...
.enter 对键盘回车键修饰
.tab 对键盘切换tab按键修饰
.delete (捕获“删除”和“退格”键)
.esc 对键盘esc按键修饰
.space 对键盘的空格按键修饰
.up 对 上
.down 下
.left 左
.right 右
<input type="text" v-model="name" @keyup.enter.tab.delete.esc.space.up.down.left.right="keyup">
<input type="text" @keyup.enter="test">
2.2.4 v-show
1.根据表达式的真假,切换元素的显示和隐藏
2.原理是修改元素的display,实现显示与隐藏
3.指令后面的内容必须是布尔值,若为true,则显示
2.2.5 v-if
1.根据表达式的真假切换元素的显示状态
2.本质是通过操纵dom元素来切换显示状态
3.表达式的值为true,元素存在于dom树中,为false,则从dom树中移除
4.频繁的切换用v-show,反之用v-if,因为前者切换消耗小
# 总结
v-if 、 v-show:
指令: 作用: 用来通过vue方式控制页面中哪些标签展示和隐藏
语法: 控制那个标签显示隐藏直接在那个标签上 加入v-if="true|false|逻辑运算表达式" v-show="true|false"
区别:
1.v-if 底层通过控制dom树上元素节点实现 页面标签展示和隐藏 dom树
2.v-show 底层通过控制标签css中display属性实现标签展示和隐藏 css样式
使用总结:
一般来说,v-if 有更高的切换开销,而 v-show 有更高的初始渲染开销。因此,如果需要非常频繁地切换,则使用 v-show 较好;如果在运行时条件很少改变,则使用 v-if 较好
变化快 用v-show 变化慢 v-if
2.2.6 v-bind
1.设置元素的属性,比如src,title,class
2.简写 :属性名
3.需要动态的删除class属性的,建议使用对象的方式
v-bind: 绑定
作用: 用来绑定html标签中某个属性交给vue实例进行管理
好处: 一旦属性交给vue实例进行管理之后,日后可以通过修改vue实例中绑定属性达到动态修改标签属性的效果
语法: 对应标签上 v-bind:属性名
简化写法: :属性名="属性值" 推荐
1.动态修改标签属性
比如 <img v-bind:width="width" v-bind:height="height" src="https://img2.baidu.com/it/u=1909694165,3400923478&fm=26&fmt=auto&gp=0.jpg">
上面的标签src属性是写死的,若我们想要动态改变的话,就可以把src交给vue实例来管理,这样我们通过vue实例来修改就可以改变标签的相应属性:
<img v-bind:width="width" v-bind:height="height" v-bind:src="src">
var app = new Vue({
el:"#app",//代表vue实例作用范围
data:{ //用来vue实例绑定数据
msg:"hello vue",
src:"https://img2.baidu.com/it/u=1909694165,3400923478&fm=26&fmt=auto&gp=0.jpg",
width:200,
height:200
}
});
2.动态修改标签样式
v-bind: 用来将html标签属性绑定vue实例,日后通过修改vue实例中属性以达到动态修改标签属性效果
<div v-bind:class="cls?'aa':'bb'" @mouseover="changeClsBB" @mouseout="changeClsAA"></div>
<style>
.aa{
width: 200px;
height: 200px;
border: 10px red solid;
}
.bb{
width: 200px;
height: 200px;
border: 10px green dashed;
}
</style>
2.2.7 v-for
1.根据数据生成列表结构
2.数组经常和v-for结合使用
3.语法是(item , index) in 数据,item是元素,index是下表索引,item和index可以和其他指令结合一起使用
# 总结:
v-for
指令: 作用: 用来在页面中实现vue中定义数据的遍历
语法: 直接在对应标签上加入v-for指令
a.遍历对象: v-for="value,key,index in data中变量名"
b.遍历数组: v-for="item普通类型元素,index in data中变量名"
c.遍历数组对象: v-for="item对象,index in data中变量名"
注意: 在使用v-for 建议尽可能在使用 v-for 时提供 key attribute key属性唯一 (虽然key不是html标签属性)
<h3>遍历对象</h3>
<span v-for="value,key,index in user"> [{{index}} {{key}} {{value}}] </span>
<h3>遍历数组</h3>
<li v-for="item,index in schools">{{index+1}}--- {{item}}</li>
2.2.8 v-model
1.获取和设置表单元素的值(双向数据绑定)
2.绑定的数据会和表单元素值相关联
# 总结:
v-bind: 绑定 作用: 用来将html标签的属性进行绑定,交给vue实例管理 除了value属性以外所有属性
v-model: 模型 作用: 用来将html标签的value属性进行绑定,交给vue实例管理 主要用在表单元素上 最能体现双向绑定机制一个指令
语法: 在表单元素标签上 直接加入 v-model="vue实例中一个变量"
比如:<input type="text" value="aaa"> 这个表单的值是aaa,已经定死了,若我们要实时修改并展示它的值,那么就可以用双向绑定,
<input type="text" v-model="msg">
data:{ //用来vue实例绑定数据
msg:"aaa",
}
2.1 模板语法
模板的理解: 动态的html页面,包含了一些JS语法代码
1.双大括号表达式
语法: {{exp}}
功能:
- 向页面输出数据
- 可以调用对象的方法
<p>{{content}}</p>
<p>{{content.toUpperCase()}}</p>
2.指令:以v-开头的自定义标签属性
指令一: 强制数据绑定
功能: 指定变化的属性值
完整写法:
v-bind:xxx=‘yyy’ //yyy会作为表达式解析执行
简洁写法:
:xxx=‘yyy’
指令二: 绑定事件监听
功能: 绑定指定事件名的回调函数
完整写法:
v-on:click=‘xxx’
简洁写法:
@click=‘xxx’
<h2>2. 指令一: 强制数据绑定</h2>
<a href="url">访问指定站点</a><br>
<a v-bind:href="url">访问指定站点2</a><br>
<a :href="url">访问指定站点2</a><br>
<h2>3. 指令二: 绑定事件监听</h2>
<button v-on:click="test">点我</button>
<button @click="test">点我</button>
<script type="text/javascript">
new Vue({
el: '#app',
data: {
content: 'NBA I Love This Game',
url: 'http://www.atguigu.com'
},
methods: {
test () {
alert('好啊!!!')
}
}
})
</script>
2.2 计算属性
假如我们需要统计一个商品的总价格,最普遍的做法是,在method里定义好计算的逻辑,然后通过调用方法去返回计算的总价格,这种方式,若在好几个页面都要显示总价格,那么每个页面都要重复去调用该方法来执行,而每次方法执行都要消耗性能,所以可以使用computed这种,因为计算出来的结果会缓存
computed: 计算属性 推荐
作用: 用来在vue实例中完成相关业务计算工作 日后在将某个数据渲染页面时如果该数据需要经过业务处理之后再渲染就可以使用computed
好处: 提升vue运行性能 主要使用computed进行计算相关处理 会将第一次计算结果进行缓存,便于日后页面多次使用
使用: {{属性名}}
<h1> {{counts}} {{counts}} {{counts}}</h1>
computed:{ //计算属性
counts(){
console.log("computed.counts----------------------");
return this.count+10;
}
}
2.3 监视
2.4 强制绑定
3.组件模板
1.一个应用只有一个vue实例,意思就是整个应用都是只有一个new vue()执行的,以后所有的操作都在这个vue里执行,不可能存在每个页面都有一个vue实例的
2.组价里的data属性必须是一个具有返回值(返回值是一个对象)的函数,组件里定义的数据都会放到data函数里,并且组件里的data数据只能在当前组件内使用
3.若组件里有多个标签元素,组件里必须要有一个根容器包裹起来(比如加一个div)
4.当想查看某个示例的某些属性时,可以通过console.log(this)来查看示例具体属性
3.1 组件作用
组件作用: 用来减少Vue实例对象中代码量,日后在使用Vue开发过程中,可以根据 不同业务功能将页面中划分不同的多个组件,然后由多个组件去完成整个页面的布局,便于日后使用Vue进行开发时页面管理,方便开发人员维护。
3.2 组件使用
3.2.1 全局组件
说明:全局组件注册给Vue实例,日后可以在任意Vue实例的范围内使用该组件
//1.开发全局组件
Vue.component('login',{
template:'<div><h1>用户登录</h1></div>'
});
//2.使用全局组件 在Vue实例范围内
<login></login>
# 注意:
- 1.Vue.component用来开发全局组件 参数1: 组件的名称 参数2: 组件配置{} template:''用来书写组件的html代码 template中必须有且只有一个root元素
- 2.使用时需要在Vue的作用范围内根据组件名使用全局组件
- 3.如果在注册组件过程中使用 驼峰命名组件的方式 在使用组件时 必须将驼峰的所有单词小写加入-线进行使用
3.2.2 局部组件
说明:通过将组件注册给对应Vue实例中一个components属性来完成组件注册,这种方式不会对Vue实例造成累加
- 第一种开发方式
//局部组件登录模板声明
let login ={ //具体局部组件名称
template:'<div><h2>用户登录</h2></div>'
};
const app = new Vue({
el: "#app",
data: {},
methods: {},
components:{ //用来注册局部组件
login:login //注册局部组件
}
});
//局部组件使用 在Vue实例范围内
<login></login>
- 第二种开发方式
//1.声明局部组件模板 template 标签 注意:在Vue实例作用范围外声明
<template id="loginTemplate">
<h1>用户登录</h1>
</template>
//2.定义变量用来保存模板配置对象
let login ={ //具体局部组件名称
template:'#loginTemplate' //使用自定义template标签选择器即可
};
//3.注册组件
const app = new Vue({
el: "#app",
data: {},
methods: {},
components:{ //用来注册局部组件
login:login //注册局部组件
}
});
//4.局部组件使用 在Vue实例范围内
<login></login>
代码示例:
const login = {
template:`<div id="aa">
<h2>用户登录</h2>
<h2>{{counter}}---{{msg}}---{{counterSqrt}}---{{counterSqrt}}----{{counterSqrt}}</h2>
<button @click="test(10)">点我counter++</button>
<aa></aa>
<register></register>
</div>`, //用来书写组件html代码
data(){ //用来给当前组件定义属于组件自己数据 组件中定义数据 data必须是一个函数
return {
counter:1,
msg:"我是组件msg"
}
},
methods:{ //用来给组件自己定义一些列方法
test(count){
this.counter+=count;
}
},
computed:{ //用来给组件自己定义一些列计算方法
counterSqrt(){
return this.counter*this.counter;
}
},
//初始化阶段
beforeCreate(){
console.log("beforeCreate:",this.msg);},
created(){
console.log("created:",this.msg);
},
beforeMount(){ //此时组件中template还是模板还没有渲染
console.log(this);
//console.log("beforeMount:",this.$el.innerHTML);
},
mounted(){ // 此时组件中页面的数据已经和data中数据一致
console.log("mounted:",document.getElementById("aa").innerHTML);
},
//运行阶段
beforeUpdate(){// 此时data中数据变化了 页面数据还是原始数据
console.log("beforeUpdate:",this.counter);
console.log("beforeUpdate:",document.getElementById("aa").innerHTML);
},
updated(){ //此时data 页面数据一致
console.log("updated:",this.counter);
console.log("updated:",document.getElementById("aa").innerHTML);
},
//销毁阶段
beforeDestroy(){},
destroyed(){},
components:{//组件内还有子组件
aa:{ //定义组件
template:'<div><span>我是aa子组件</span></div>'
},
}
};
3.3 组件数据传递
3.3.1 Prop的使用
1.作用:props用来给组件传递相应静态数据或者是动态数据的
2.只能完成父组件向子组件的数据传递,是单向的
3.props:[‘userName’],就相当于data里申明了一个变量userName,所以props里已经定义好一个变量比如userName后,不用再在data里去定义一个userName了
3.3.1.1 通过在组件上声明静态数据传递给组件内部
//1.声明组件模板配置对象
let login = {
template:"<div><h1>欢迎:{{ userName }} 年龄:{{ age }}</h1></div>",
props:['userName','age'] //props作用 用来接收使用组件时通过组件标签传递的数据,用来接收父组件给当前组件传递数据 注意:props机制接收数据就相当于自己组件data中声明一个这样数据
}
//2.注册组件
const app = new Vue({
el: "#app",
data: {},
methods: {},
components:{
login //组件注册
}
});
//3.通过组件完成数据传递
<login user-name="小陈" age="23"></login>
# 总结:
1.使用组件时可以在组件上定义多个属性以及对应数据
2.在组件内部可以使用props数组生命多个定义在组件上的属性名 日后可以在组件中通过{{ 属性名 }} 方式获取组件中属性值
3.3.1.2 通过在组件上声明动态数据传递给组件内部
//1.声明组件模板对象
const login = {
template:'<div><h2>欢迎: {{ name }} 年龄:{{ age }}</h2></div>',
props:['name','age']
}
//2.注册局部组件
const app = new Vue({
el: "#app",
data: {
username:"小陈陈",
age:23
},
methods: {},
components:{
login //注册组件
}
});
//3.使用组件
<login :name="username" :age="age"></login> //使用v-bind形式将数据绑定Vue实例中data属性,日后data属性发生变化,组件内部数据跟着变化
3.3.1.3 prop的单向数据流
单向数据流:所有的 prop 都使得其父子 prop 之间形成了一个单向下行绑定:父级 prop 的更新会向下流动到子组件中,但是反过来则不行。
-
所有的 prop 都使得其父子 prop 之间形成了一个单向下行绑定:父级 prop 的更新会向下流动到子组件中,但是反过来则不行。这样会防止从子组件意外改变父级组件的状态,从而导致你的应用的数据流向难以理解。
-
额外的,每次父级组件发生更新时,子组件中所有的 prop 都将会刷新为最新的值。这意味着你不应该在一个子组件内部改变 prop。如果你这样做了,Vue 会在浏览器的控制台中发出警告。—摘自官网
3.3.2 向子组件中传递事件并在子组件中调用该事件
1.在子组件中调用传递过来的相关事件必须使用 this.$emit(‘函数名’) 方式调用
2.在使用组件时向组件传递事件 直接在对应组件标签上定义传递事件即可 @key=value @传递事件名="父组件中传递事件名
//1.声明组件
const login = {
template:"<div><h1>百知教育 {{ uname }}</h1> <input type='button' value='点我' @click='change'></div>",
data(){
return {
uname:this.name
}
},
props:['name'],
methods:{
change(){
//调用vue实例中函数
this.$emit('aaa'); //调用组件传递过来的其他函数时需要使用 this.$emit('函数名调用')
}
}
}
//2.注册组件
const app = new Vue({
el: "#app",
data: {
username:"小陈"
},
methods: {
findAll(){ //一个事件函数 将这个函数传递给子组件
alert('Vue 实例中定义函数');
}
},
components:{
login,//组件的注册
}
});
//3.使用组件
<login @aa="findAll"></login> //=====> 在组件内部使用 this.$emit('find')
向父组件传递值示例:
const login = {
template:`<div><h3>用户登录---{{name}}---{{msg}}</h3> <button @click="testChild">点我去掉父组件中某个事件</button></div>`,
data(){
return {
count:19
}
},
props:['name','msg'],
methods:{
testChild(){
alert('我是子组件中定义事件');
//调用父组件中testParent事件
this.$emit('testparent');//这个方法用来调用父组件传递过来事件 参数1:调用事件名
//this.$emit('bb',this.count,'xiaochen',true);//传递零散参数
//this.$emit('bb',{count:this.count,name:"小陈",sex:true});//传递零散参数
}
}
};
const app = new Vue({
el: "#app",
data: {
msg: "组件之间事件传递",
count:0
},
methods:{
testParent(){
alert('我是父组件上事件')
},
testHehe(obj){
console.log("parent:","hehe");
console.log("parent:",obj);
console.log("parent:",obj.count);
console.log("parent:",obj.name);
console.log("parent:",obj.sex);
this.count = obj.count;
}
},
components:{ //注册局部组件
login,
}
});
4.插槽slot
插槽: slot 作用: 用来扩展现有组件 让组件变得更加灵活 usb 接口 具名插槽: 带有名字插槽
说白了,就是一个占位符,先预定位置,就是说以后组件若需要用到预定的位置展示,就可以向插槽里增加数据,就可以显示出来了,若用不到,就是空白不显示
<login><span slot="bb">欢迎进入我们网站</span></login>
<hr>
<login><span slot="aa">welcome to website!!! {{msg}}</span></login>
<hr>
<login><button slot="aa" @click="incrmentCount()">点我</button></login>
const login={
template:`<div><slot name="aa"><span>i am moren chacao</span></slot><h3>用户登录</h3><slot name="bb"></slot></div>`
};
const app = new Vue({
el: "#app",
data: {
msg: "组件的slot(插槽)",
count:0,
},
methods:{
incrmentCount(){
this.count++;
}
},
components:{ //注册局部组件
login,
}
});
5.网络通讯
5.1 axios
Axios
是一个异步请求技术,核心作用就是用来在页面中发送异步请求,并获取对应数据在页面中渲染 页面局部更新技术 Ajax中文网站:https://www.kancloud.cn/yunye/axios/234845
<script src="js/axios.min.js"></script>
<script>
//发送axios的get方式请求
/*
axios.get("http://localhost:8081/demo?id=21&name=xiaochen").then(function(res){
console.log(res);
console.log(res.data);
}).catch(function (err) {
alert('进入catch')
console.log(err);
});
*/
//发送一个post方式请求
// axios.post("http://localhost:8081/test",{id:21,name:"xiaochen"}).then(function(res){
// console.log(res);
// console.log(res.data);//响应结果
// }).catch(function(err){
// console.log(err);
// });
//发送put方式请求
// axios.put("http://localhost:8081/test1",{id:22,name:"小三"}).then(function(res){
// console.log(res);
// console.log(res.data);//响应结果
// }).catch(function(err){
// console.log(err);
// });
//创建axios的配置对象
var instance = axios.create({
baseURL:"http://localhost:8081/",
timeout: 5000,
});
//请求拦截器
instance.interceptors.request.use(function (config) {
if(config.url.indexOf("?")==-1){
config.url+="?token=1234"
}else{
config.url +="&token=1234";
}
return config;
});
//响应拦截器
instance.interceptors.response.use(function (response) {
if(response.status==500){
alert('服务器出现错误!');
}
return response;
});
//发送get方式请求
instance.get("/demo?id=11&name=xiaochen").then(function(res){
console.log(res.data);
});
instance.post("http://localhost:8081/test",{id:21,name:"xiaochen"}).then(function(res){
console.log(res.data);
});
5.2 脚手架安装
# 1.安装axios
npm install axios --save
# 2.配置main.js中引入axios
import axios from 'axios';
Vue.prototype.$http=axios;
# 3.使用axios
在需要发送异步请求的位置:this.$http.get("url").then((res)=>{}) this.$http.post("url").then((res)=>{})
6.自定义内容分发
7.ES6
7.1 介绍
以前是网景公司开发script,后面又接着java的热度,命名为javascript,后面贡献给欧洲计算机协会后,又逐年推出ECMAScript 1.x ,5.x,6.x,7.x....
javascript chrome jscript ie =====> ECMAScript 到今天js依然存在浏览器
EcmaScript: 1.x=====> 7.x 8.x ES11.x
现在大多数浏览器都支持5.x的,部分最新支持6.x,开发可以逐步使用ES6的一些新特性进行开发
EcmaScript: 5.x 通用版5.x
EcmaScript: 6.x 简称 ES6
7.2 常用语法
ES6提供了一些用法优化,明确了一些数据范围以及简化用法,最常用的是下面这四个
7.2.1 变量声明
var原因: 使用var声明变量存在作用范围混淆问题
let:用来声明局部变量 好处: 作用范围严谨 从代码声明出开始 到代码块结束 一般在声明基本变量使用推荐使用let
const:用来声明js中常量 好处: 一旦被赋值不能被修改 推荐使用这两个关键字声明变量 声明js中对象时推荐使用const 数组
定义一个对象 const在定义对象时指的是对象的地址不变 对象中属性可以改变
定义一个数组 const在定义数组时指的数组地址不能改变 但是数组中元素可以改变
function test(){
for (var i = 0; i < 10; i++) {
console.log("for in",i);
}
console.log(i);//使用var定义的变量,这里都能继续访问到,容易造成变量作用域混乱
function test(){
for (let i = 0; i < 10; i++) {
console.log("for in",i);
}
const name = "xiaochen";
console.log(name);
7.2.2 匿名函数
在使用匿名函数时作为参数时候 function(){} 推荐使用es6中箭头函数 (参数,参数)=>{函数体}
axios.get("url").then(function(res){}).catch(function(err){});
axios.get("url").then((res)=>{
}).catch((err)=>{});
注意:
1.当箭头函数没有参数时或者参数大于1个 必须加入()
2.当箭头函数只有一个参数时 () 可以省略不写
3.当函数体中只有一行代码时 函数体{} 可以省略不写
4.箭头函数和匿名函数最大区别 箭头函数没有自己this 匿名函数存在自己的this
7.2.3 模板字符串
模板字符串 使用语法: ` `
let html = "<button οnclick=\"test('+id+')\">点我</button>" +
"<button οnclick=\"test('+id+')\">点我</button>" +
"<button οnclick=\"test('+id+')\">点我</button>" +
"<button οnclick=\"test('+id+')\">点我</button>" +
"<button οnclick=\"test('+id+')\">点我</button>" +
"<button οnclick=\"test('+id+')\">点我</button>";
正如上面所示,我们要拼接一个html字符串,里面会进行单引号和双引号来回切换,很不方便,我们可以使用``这种,把里面的内容括起来即可
let html1 = `<div>
<h1>我是小黑</h1>
<button οnclick="test()">点我</button>
</div>`;
console.log(html1);
7.2.4 对象定义
便利: 在定义对象时如果对象属性名和变量名一致,写一个即可
let id = 21;
let name = "小三";
let age = 23;
//es5.x
const emp = {id:id,name:name,age:age};
console.log("es5",emp);
//es6.x 若变量名和对象的属性名一样,那么可以直接只写任意一个名称即可,不用把两个都想E5那样id:id这种写出来
const emp1 = {id,name,age}
console.log("es6",emp1);
8.路由
1.路由:根据请求的路径按照一定的路由规则进行请求的转发从而帮助我们实现统一请求的管理
8.1 路由基本使用
-
引入路由
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> <script src="https://unpkg.com/vue-router/dist/vue-router.js"></script> //vue 路由js
-
创建组件对象
//声明组件模板 const login = { template:'<h1>登录</h1>' }; const register = { template:'<h1>注册</h1>' };
-
定义路由对象的规则
//创建路由对象 const router = new VueRouter({ routes:[ {path:'/login',component:login}, //path: 路由的路径 component:路径对应的组件 {path:'/register',component:register} ] });
-
将路由对象注册到vue实例
const app = new Vue({ el: "#app", data: { username:"小陈", }, methods: {}, router:router //设置路由对象 });
-
在页面中显示路由的组件
<!--显示路由的组件--> <router-view></router-view>
-
根据连接切换路由
<a href="#/login">点我登录</a> <a href="#/register">点我注册</a>
8.2 切换路由的几种方式
8.2.1 路径输入切换
routes:[
{path:'/login',component:login}, //path: 路由的路径 component:路径对应的组件
{path:'/register',component:register}
]
该种方式,当请求url里带有上面指定的路径字符串时,routers匹配上的话,就会转向指定组件去展示
8.2.2 router-link使用
<a href="#/login">用户登录</a>
<a href="#/reg">用户注册</a>
<!--路径切换路由: 根据请求路径切换显示不同组件-->
<!--切换路由链接-->
<a href="#/login">用户登录</a>
<a href="#/register">用户注册</a>
<!--切换路由标签 router-link 标签必须加入 to属性 to="路由路径" -->
<router-link to="/login">用户登录</router-link>
<router-link to="/register">用户注册</router-link>
<!--切换路由标签-->
<router-link :to="{path:'/login'}">用户登录</router-link>
<router-link :to="{path:'/register'}">用户注册</router-link>
<!--名称切换路由: 根据路由对象名称切换路由显示不同组件 根据路由名称切换路由只能使用router-link 推荐使用命名路由-->
<router-link :to="{name:'Login'}">用户登录</router-link>
<router-link :to="{name:'Register'}">用户注册</router-link>
const login = {
template:`<div><h4>用户登录</h4></div>`
};
//register
const register = {
template:`<div><h4>用户注册</h4></div>`
};
//1.创建路由规则对象
const router = new VueRouter({
routes:[
//name:这个属性代表路由对象名称 用来给路由对象一个唯一名称标识
{path:'/login',component:login,name:'Login'},
{path:'/register',component:register,name:'Register'},
]
});
const app = new Vue({
el: "#app",
data: {
msg:"vue router 基本使用之使用router-link切换路由"
},
methods:{},
router,//注册路由对象
});
1.作用:用来替换我们在切换路由时使用a标签切换路由
2.好处:就是可以自动给路由路径加入#不需要手动加入
8.2.3 路由器切换
1.this.$route object 当前路由对象 ,每个组件都有一个路由对象,该route就是表示当前组件的路由信息
2.this.$router vueRouter 代表路由管理器对象,管理所有路由
methods:{
login(){
//发送axios请求完成登录 响应回来之后切换路由到主页
//this.$route object 当前路由对象 this.$router vueRouter 代表路由管理器对象
//console.log(this.$route.name);
//this.$router.push('/login');//切换路由
//this.$router.push({path:'/login'});
//在vuerouter 中多次切换相同路由出现错误 1.每次切换之前手动判断 2.加入官方一段配置解决错误问题
// if(this.$route.name!='Login'){
// this.$router.push({name:'Login'});//使用名称切换
// }
this.$router.push({name:'Login'});//使用名称切换 推荐使用这种方式
},
register(){
//console.log(this.$route.name);
// if(this.$route.name!='Register') {
// this.$router.push({name: 'Register'});//使用名称切换
// }
this.$router.push({name: 'Register'});//使用名称切换
}
},
8.3 连续访问相同路径报错解决
1.在报错的地方加入下面这段代码
//解决同一个路由多次切换报错的问题
const originalPush = VueRouter.prototype.push;
VueRouter.prototype.push = function push(location) {
return originalPush.call(this, location).catch(err => err)
};
2.或者路由跳转加入判断
//在vuerouter 中多次切换相同路由出现错误 1.每次切换之前手动判断 2.加入官方一段配置解决错误问题
if(this.$route.name!='Login'){
this.$router.push({name:'Login'});//使用名称切换
}
8.4 默认路由设置
作用:用来在第一次进入界面是显示一个默认的组件
const router = new VueRouter({
routes:[
//{ path:'/',component:login},
{ path:'/',redirect:'/login'}, //redirect: 用来当访问的是默认路由 "/" 时 跳转到指定的路由展示 推荐使用
{ path:'/login', component:login},
{ path:'/register', component:register},
]
});
8.5 路由参数传递
8.5.1 传统方式
-
通过?号形式拼接参数
<router-link to="/login?id=21&name=zhangsan">我要登录</router-link> <router-link to="/login?name=xiaohei&password=123456">用户登录</router-link> <router-link :to="{path:'/login',query:{name:'xiaohong',password:123456}}">用户登录</router-link> <router-link :to="{name:'Login',query:{name:'xiaohei',password:123456}}">用户登录</router-link>
-
组件中获取参数
const login = { template:'<h1>用户登录</h1>', data(){return {}}, methods:{}, created(){ console.log("=============>"+this.$route.query.id+"======>"+this.$route.query.name); } };
8.5.2 restful
-
通过使用路径方式传递参数
<router-link to="/register/24/张三">我要注册</router-link> var router = new VueRouter({ routes:[ {path:'/register/:id/:name',component:register} //定义路径中获取对应参数 ] }); <router-link :to="{path:'/register/22/xiaojindou'}">用户注册</router-link> <router-link :to="{name:'Register',params:{id:233,name:'xiaojinniu'}}">用户注册</router-link>
-
组件中获取参数
const register = { template:'<h1>用户注册{{ $route.params.name }}</h1>', created(){ console.log("注册组件中id: "+this.$route.params.id+this.$route.params.name); } };
8.6 嵌套路由
如上图,有一个需求,当在1面板里点击“添加用户信息”的时候,表格下方会显示出表单来供信息录入,若我们按照下面这么写的话
//定义路由规则对象
const router = new VueRouter({
routes:[
{
path:'/users',name:'users',component:users,
path:'/useradd',name:'useradd',component:useradd
},
]
});
由于users和useradd两个路由是平级的,而只有一个,那么当我们点击任何一个路由的时候,页面内容就会被后一个路由所覆盖
解决办法如下:
<body>
<div id="app">
<h1>{{msg}}</h1>
<router-link :to="{name:'users'}">用户列表</router-link>
<!--1.展示路由组件-->
<router-view></router-view>
</div>
</body>
</html>
<template id="users">
<div>
<h3>用户列表</h3>
<a href="#/users/useradd">添加用户信息</a>
<table border="1">
<tr>
<th>id</th>
<th>name</th>
<th>age</th>
<th>salary</th>
<th>操作</th>
</tr>
<tr v-for="user,index in users">
<td>{{user.id}}</td>
<td>{{user.name}}</td>
<td>{{user.age}}</td>
<td>{{user.salary}}</td>
<td><a href="">删除</a> <router-link :to="{name:'useredit',query:{id:user.id}}">修改</router-link></td>
</tr>
</table>
<!--2.展示子路由组件标签-->
<router-view></router-view>
</div>
</template>
<script src="js/vue.js"></script>
<script src="js/vue-router.js"></script>
<script>
//定义用户列表
const users = {
template:'#users',
data(){
return {
users:[]
}
},
created(){
//发送axios请求查询所有
this.users = [{id:1,name:'xiaochen',age:23,salary:2300}]
}
};
//3.定义用户添加组件
const useradd={
template:`<div><form action="">姓名: <input type="text"> <br> 年龄: <input type="text"> <br> 工资: <input type="text"> <br> <input type="submit" value="提交"></form></div>`
};
//4.编辑组件
const useredit={
template:`<div><form action="">id: <input type="text" v-model="user.id"> <br> 姓名: <input type="text" v-model="user.name"> <br> 年龄: <input type="text" v-model="user.age"> <br> 工资: <input type="text" v-model="user.salary"> <br> <input type="button" @click="editUser" value="提交"></form></div>`,
data(){
return {
user:{}
}
},
methods:{
editUser(){
//发送axios请求更新用户
// axios.post("url",this.user).then(res=>{
// this.user = {};//清空数据
// this.$router.push({name:'users'})//切换路由
// });
this.$router.push({name:'users'})//切换路由
}
},
created(){
let id = this.$route.query.id;
console.log("updated: ",id);
//发送axios请求
//axios.get("url?id="+id).then(res=>this.user = res.data);
this.user = {id:id,name:'xiaochen',age:23,salary:2300};
}
};
//5.定义路由规则对象
const router = new VueRouter({
routes:[
{
path:'/users',name:'users',component:users,
children:[ //嵌套子组件路由 注意:嵌套路由中子路由不能使用/开头 访问子路由 /users/useradd
{path:'useradd',name:'useradd',component:useradd},
{path:'useredit',name:'useredit',component:useredit},
]
},
]
});
const app = new Vue({
el: "#app",
data: {
msg:"vue router 基本使用之嵌套路由"
},
methods:{},
router,//注册路由
});
</script>
9.webpack
本质上,webpack 是一个现代 JavaScript 应用程序的静态模块打包器(module bundler)。当 webpack 处理应用程序时,它会递归地构建一个依赖关系图(dependency graph),其中包含应用程序需要的每个模块,然后将所有这些模块打包成一个或多个 bundle。
9.1 模块化的演进
# 1.Script标签引入
以前需要用到别人写好的js,就需要用script标签去引入,这样就导致各种变量冲突,每个包都需要手动去引入,而且管理混乱
# 2.CommonsJs
CommonsJS规范,核心思想是允许模块通过require方法来同步加载所需依赖,然后通过exports或module.exports来导出需要暴露的接口。
但这种方式是同步去加载,并不能并行加载多个模块,效率比较低
# 3.AMD
鉴于浏览器的特殊情况,又出现了一个规范,这个规范呢可以实现异步加载依赖模块,并且会提前加载那就是AMD规范,其核心接口是:define(id?, dependencies?, factory) ,它要在声明模块的时候指定所有的依赖 dependencies ,并且还要当做形参传到factory 中,对于依赖的模块提前执行,依赖前置。在浏览器环境中异步加载模块;并行加载多个模块
define("module", ["dep1", "dep2"], function(d1, d2) {
return someExportedValue;
});
require(["module", "../file"], function(module, file) { /* ... */ });
但开发成本高,代码的阅读和书写比较困难
# 4. CMD
Common Module Definition 规范和 AMD 很相似,尽量保持简单,并与 CommonJS 和 Node.js 的 Modules 规范保持了很大的兼容性。
define(function(require, exports, module) {
var $ = require('jquery');
var Spinning = require('./spinning');
exports.doSomething = ...
module.exports = ...
})
依赖就近,延迟执行 可以很容易在 Node.js 中运行,但依赖 SPM 打包,模块的加载逻辑偏重
# 5.ES6
ES6模块的设计是尽可能的静态化,使得编辑时就能确定模块之间的依赖关系,以及输入和输出变量。而CommonJs和AMD则是在运行时才能实现以上结果。
例如CommonJs模块就是一个对象,输入时必须查找对象属性,而ES6模块则可以暴露出任何变量、函数等。
所以说ES6模块的加载方式是“编译时“加载或者是静态加载。
ES6模块功能主要由两个命令构成:export和import。export用来规定模块的对外接口,import用来输入其他模块提供的功能。
参考:
https://zhuanlan.zhihu.com/p/26625636
https://www.cnblogs.com/chinabin1993/p/10565816.html
https://zhuanlan.zhihu.com/p/41231046
https://www.imooc.com/article/20057/
9.2 作用
1.可以把ES6打包成ES5,从而让所有浏览器都支持运行
2.它是一个工具,将很多的的 css文件,js文件,图片等“物品”,全都写进一个js文件,而不是在一个html页面通过script,link标签去引入多个静态资源
3.CSS 预处理。将 Less, Sass 编译成css
① 模块化开发(import,require)
② 预处理(Less,Sass,ES6,TypeScript……)
③ 主流框架脚手架支持(Vue,React,Angular)
④ 庞大的社区(资源丰富,降低学习成本)
10.脚手架Vue CLI
10.1 nodeJs安装
1.Node.js 是一个开源与跨平台的 JavaScript
运行时环境
(就相当于一个浏览器,可以直接运行代码)。 它是一个可用于几乎任何项目的流行工具!
2.Node.js 是一个底层的平台。 为了使开发者做事变得容易又来劲,社区在 Node.js 上构建了数千个库。
3.Node.js是一个事件驱动I/O服务端JavaScript环境,基于Google的V8引擎,V8引擎执行Javascript的速度非常快,性能非常好。
# 1.下载nodejs
http://nodejs.cn/download/
windows系统: .msi 安装包(exe)指定安装位置 .zip(压缩包)直接解压缩指定目录
mac os 系统: .pkg 安装包格式自动配置环境变量 .tar.gz(压缩包)解压缩安装到指定名
安装后,会自动安装npm,并且把环境变量加入到path
`npm package manager`表示npm包管理器
`online documentation shortcuts` 在线文档快捷方式
`Add to PATH`添加node安装路径到环境变量
# 2.配置nodejs环境变量
1.windows系统: 若没有自动添加到path,那么需要自己去手动配置
计算上右键属性----> 高级属性 ---->环境变量 添加如下配置:
NODE_HOME= nodejs安装目录
PATH = xxxx;%NODE_HOME%
2.macos 系统
推荐使用.pkg安装直接配置node环境
# 3.验证nodejs环境是否成功
node -v
# 4.npm介绍
node package mangager nodejs包管理工具 前端主流技术 npm 进行统一管理
maven 管理java后端依赖 远程仓库(中心仓库) 阿里云镜像
npm 管理前端系统依赖 远程仓库(中心仓库) 配置淘宝镜像
# 5.配置淘宝镜像(由于远程仓库在国外的话,下载组件比较慢,故需要配置淘宝仓库)
设置仓库
npm config set registry https://registry.npm.taobao.org
查看仓库
npm config get registry
若不配置远程仓库,也可以每次npm下载的时候, 后面都加一个registry指定仓库去下载也行
# 6.配置npm下载依赖位置
windows:
npm config set cache "D:\nodereps\npm-cache"
npm config set prefix "D:\nodereps\npm_global"
mac os:
npm config set cache "/Users/chenyannan/dev/nodereps"
npm config set prefix "/Users/chenyannan/dev/nodereps"
# 7.验证nodejs环境配置
npm config ls
; userconfig /Users/chenyannan/.npmrc
cache = "/Users/chenyannan/dev/nodereps"
prefix = "/Users/chenyannan/dev/nodereps"
registry = "https://registry.npm.taobao.org/"
10.2 Vue cli安装
命令行界面(英语:command-line interface,缩写:CLI)是在图形用户界面得到普及之前使用最为广泛的用户界面,它通常不支持鼠标,用户通过键盘输入指令,计算机接收到指令后,予以执行。也有人称之为字符用户界面(CUI)
1.以前我们用到其他js的功能,那么我们一般是通过cript src手动去引入相应的js进来,而现在通过vue可以通过命令直接下载相关的依赖就可以用了
2.以前开发需要手动引入vuejs vuerouter axios等组件,使用脚手架后,就自动帮我们都引入好了
3.当引入的组件,需要升级的时候,只需一条命令就可以升级了
4.webpack是一种打包方式(yarn是另外一种),类似于打包成java中的jar或war等形式,使用脚手架可以方便打包编译,然后再部署到服务器上运行即可
5.脚手架还提供了默认的配置文件,我们可以修改这些配置文件,达到自己想要的项目环境
6.可以通过插件进行扩展,比如v-chars elementui等
vue.cli脚手架,就类似于我们maven的骨架一样,都是提供一种模板方式(预先定义好项目结构目录以及基础代码等),快速生成一个vue项目(使用vue脚手架之后我们的页面僵尸一个完整系统)
功能有:统一的目录结构,本地调试,热部署,单元测试,集成打包上线
脚手架:核心思想是一切皆组件
@vue/cli 是V3版本 vue/cli是V2版本
# 0.卸载脚手架
npm uninstall -g @vue/cli //卸载3.x版本脚手架
npm uninstall -g vue-cli //卸载2.x版本脚手架
# 1.Vue Cli官方网站
https://cli.vuejs.org/zh/guide/
# 2.安装vue Cli
npm install -g vue-cli
安装好后,我们可以去本地仓库查看
安装好了,执行vue -V
看看,若不行,则需要手动添加到path里去,参考,添加到path里后,在执行vue,若不行,则重启webStorm,若还不行,则重启一下电脑即可
10.3 创建vue项目
1.选择一个项目父目录,如图:
2.初始化
vue init <template-name> <project-name>
初始化一个项目,打包方式为webpack
vue init webpack helloVue
3.初始化好后,我们会得到启动命令步骤
4.进入到有package.json的目录,然后执行npm start
# 1.创建vue脚手架第一个项目
vue init webpack 项目名
# 2.创建第一个项目
hello ------------->项目名
-build ------------->用来使用webpack打包使用build依赖 构建一些依赖文件
-config ------------->用来做整个项目配置目录 主要用来对 开发 测试 环境进行配置
-node_modules ------>用来管理项目中使用依赖
-src ------>用来书写vue的源代码[重点]
+assets ------>用来存放静态资源 [重点]
components ------>用来书写Vue组件 [重点]
router ------>用来配置项目中路由[重点]
App.vue ------>项目中根组件[重点]
main.js ------>项目中主入口[重点]
-static ------>其它静态
-.babelrc ------> 将es6语法转为es5运行
-.editorconfig ------> 项目编辑配置
-.gitignore ------> git版本控制忽略文件
-.postcssrc.js ------> 源码相关js
-index.html ------> 项目主页
-package.json ------> 类似与pom.xml 依赖管理 jquery 不建议手动修改
-package-lock.json ----> 对package.json加锁
-README.md ----> 项目说明文件
# 3.如何运行在项目的根目录中执行
npm start 运行前端系统
# 4.如何访问项目
http://localhost:8080
# 5.Vue Cli中项目开发方式
注意: 一切皆组件 一个组件中 js代码 html代码 css样式
1. VueCli开发方式是在项目中开发一个一个组件对应一个业务功能模块,日后可以将多个组件组合到一起形成一个前端系统
2. 日后在使用vue Cli进行开发时不再书写html,编写的是一个个组件(组件后缀.vue结尾的文件),日后打包时vue cli会将组件编译成运行的html文件
10.4 脚手架 项目启动流程分析
1.一个vue项目只有一个html页面,而index.html页面我们是不需要修改的,其实这个页面也就是提供后面根vue实例挂载的页面而已,后面所有组件也就绑定到这个实例里进行渲染出各种页面替换显示
2.项目启动,去找main.js
,然后创建一个全局的实例Vue,并且为这个实例注册一些路由,组件等信息
import Vue from 'vue' //引用vue组件
import App from './App' //引用App组件
import router from './router' //其实这个引用的全路径是 ./router/index.js 只不过一般引入目录地址,那么默认就是去找index.js
Vue.config.productionTip = false
/* eslint-disable no-new */
new Vue({
el: '#app', //挂载到html的Id为app的标签上
router, //注册路由器
components: { App }, //注册组件
template: '<App/>' //挂载模板
})
3.vue实例里有个App,则需要去找App.vue,然后把这个组件挂载到 Vue的实例 模板 template 中
<template>
<div id="app">
<img src="./assets/logo.png">
<!--这个每个模板渲染后,根据路由不同来显示不同模板内容-->
<router-view/>
</div>
</template>
<script>
export default {
name: 'App' //模板名字
}
</script>
<style>
#app {
font-family: 'Avenir', Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
</style>
同时,还会去router里找index.js,这个里面定义了一个路由管理器,以后我们需要访问的url都可以在这里面进行配置
import Vue from 'vue'
import Router from 'vue-router'
import HelloWorld from '@/components/HelloWorld' //@/表示根路径 也可以切换成./这种相对路径
Vue.use(Router) //注册全局路由器
export default new Router({
routes: [
{
path: '/',
name: 'HelloWorld',
component: HelloWorld
}
]
})
4.当我们访问 http://localhost:8080
的时候,就会去找根路径下的HelloWorld
组件,然后进行渲染
<template>
...
</template>
<script>
export default {
name: 'HelloWorld',
data () {
return {
msg: 'Welcome to Your Vue.js App'
}
}
}
</script>
<style scoped> //scoped:表示作用域,只能在当前组件有效,若去掉scoped,那就是全局的了
...
</style>
10.5 脚手架项目开发结构说明
以后开发模式按照这种目录结构来开发:
11.webStorm 配置
11.1 安装vue插件
11.2 前端支持ES6语法编写
12. Vuex 状态管理
12.1 简介&安装
# 1.简介
- Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化
# 2.安装vuex
- npm install vuex --save
# 3.创建vue cli中创建store文件夹
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Tazz2XXo-1630407740673)(D:\Work_space\Typora_Space\IMGS\Vue教程\image-20201226214407298.png)]
# 4.在stroe中创建index.js文件
import Vue from 'vue'
import Vuex from 'vuex'
//1.安装vuex
Vue.use(Vuex);
//2.创建store对象
const store = new Vuex.Store({
});
//3.暴露store对象
export default store;
# 5.在main.js中引入stroe并注册到vue实例
import Vue from 'vue'
import App from './App'
import router from './router'
import store from "./stroe";//引入store
Vue.config.productionTip = false
/* eslint-disable no-new */
new Vue({
el: '#app',
router,
components: { App },
template: '<App/>',
store,//注册状态
})
12…2 state属性
# 1.state属性
- 作用: 用来全局定义一些共享的数据状态
# 2.语法
const store = new Vuex.Store({
state:{
counter:0,//定义共享状态
},
}
# 3.使用
{{$store.state.counter}} ===> {{this.$store.state.counter}}
12…3 mutations 属性
# 1.mutations 属性
- 作用: 用来定义对共享的数据修改的一系列函数
# 2.语法
const store = new Vuex.Store({
state:{
counter:0,//定义共享状态
},
mutations:{
//增加
increment(state){
state.counter++
},
//减小
decrement(state){
state.counter--
}
}
});
# 3.使用
this.$store.commit('decrement');
this.$store.commit('increment');
# 4.mutations传递参数
- a.定义带有参数的函数
mutations:{
//addCount 参数1:state 对象 参数2:自定义参数
addCount(state,counter){
console.log(counter);
return state.counter += counter ;
}
}
- b.调用时传递参数
this.$store.commit('addCount',11);
12…4 getters 属性
# 1.getters 属性
- 官方: 允许我们在 store 中定义“getter”(可以认为是 store 的计算属性)。就像计算属性一样,getter 的返回值会根据
它的依赖被缓存起来,且只有当它的依赖值发生了改变才会被重新计算。
- 作用: 用来定义对共享的数据的计算相关的一系列函数 相当于 computed 属性 会对结果进行缓存
# 2.语法
getters:{
//平方
mathSqrts(state){
console.log("--------");
return state.counter*state.counter;
},
//乘以一个数字
mathSqrtsNumber(state,getters){
return getters.mathSqrts*3;
},
//传递参数
mathSqrtsNumbers(state,getters){
return function (number){
return number;
}
}
}
# 3.使用
- 1.{{$store.getters.mathSqrts}}
- 2.{{$store.getters.mathSqrtsNumber}}
- 3.{{$store.getters.mathSqrtsNumbers(3)}}
13.UI引入
13.1 CSS
less saas
1.<style>和style属性这个引入的css只能作用于本页面,而且和html是混排的,也不推荐,推荐用单独CSS文件控制
2.CSS文件里,空格和制表符等等,其实是占用流量的,一般部署到服务器都是压缩去掉这些字符的
3.一般CSS里写的比较少注释,这是因为前段可以通过debug,找到某个元素,然后看它引入的css文件,然后找到对应的CSS文件进行修改即可
4.CSS前面某段代码若是错误的,并不会影响后面代码的执行,CSS需要使用分号;结束
5.CSS里可以通过 @import url("commom/munus.css"); 这种形式导入新的CSS文件内容
6.安装easy less 插件,当我们保存.less文件后,会自动生成CSS文件,CSS文件里会把各个属性的调用关系列举出来
7.安装live server 可以编写代码边预览
8.选择器:
*:全部选择
a,h1,h2{...} 可以多个标签指定相同属性
.名字:类选择器
#名字:Id选择器 Id还有其他js会用到,一般不建议使用ID来做CSS选择
多个选择器申明:
class = .名字 .名字 .名字
结构选择器:
main article h2,article h1{...} article标签下的所有H2,H1标签都会变化
main article>h2{...} 只管自己的孩子,孙子其他的不管
main article h1~h2{...} h1后面的兄弟元素h2都会生效,但h1不会
main article h1+h2{...} 只有紧挨h1标签的h2会生效,后面的h2都不会生效,h1也不会生效
<h1 title>...</h1> h1[title]{...} :具有title属性的才生效, 属性选择器
<h1 title="www">...</h1> h1[title="www"]{...} :具有title属性且值为www的才生效, 属性选择器
<h1 title^="www">...</h1> h1[title="www"]{...} :具有title属性且值以www为前缀的才生效, 属性选择器
<h1 title$="www">...</h1> h1[title="www"]{...} :具有title属性且值以www为结束的才生效, 属性选择器
<h1 title*="www">...</h1> h1[title="www"]{...} :具有title属性且值有www字符的才生效, 属性选择器
后代选择器:
article :first-child{...} : 表示凡是该节点和该节点的后代节点下的第一个节点,都会生效
article>:first-child{...} : 表示凡是该节点下的第一个节点,会生效
9.权重计算
字体:
1.应该定义多个字体,因为有些用户浏览器缺少字体,定义多个,这样不同用户的浏览器,可以识别后面的字体进行显示
看到了P28
2.字体百分比,若上一个节点设置了字体大小,那么百分比就是参照上一个来显示的
3.1em等于一个字符的宽度,等同于100%比例
浮动,在哪个盒子里,就参考哪个盒子的大小或位子
使用浮动,可以把行级元素变成块级元素
浮动盒子必须要设置高度,不然的话,就感受不到内部盒子的高度大小,内部盒子会溢出来
因为子元素浮动,已经脱离了文档流,父类元素感受不到
设置浮动,就会脱离原来的标准文档流了,后面的元素就会去占用前面浮动元素的空间
若后面元素,设置了clear属性,就会清除浮动的影响,即原来在什么位置,就在什么位置,不会顶替前面浮动的位子
若前面有浮动元素,那么后面标准流里的元素会感知到,所有,前面浮动元素占用的空间,标准流是不能去顶替的,只能在后面,这种我们可以在父类和子类自适应高度的时候,用到,即在父类最后一个加一个空div就可以撑开了
定位一般是文档流或者浮动不好排版后,才用这种方式的
相对定位,原来占据空间的还是会占据,即使移动到了其他位置
绝对定位,不再占据空间,相当于PS里的图层一样,是覆盖在父元素上一层的
当父元素有position属性后,子元素的定位就参考父元素,若没有,子元素则参考文档定位
有多个父元素,那么就参考最近的一个有position的
fixed固定元素,是参考文档位置的
参考: https://www.bilibili.com/video/BV1tJ411Y7fB?from=search&seid=3188297667789092636
13.2 Bootstrap
1.下载bootstrap压缩包,解压出来
2.只需要css和fonts文件里的样式,然后导入到项目静态目录中即可
3.在main.js里加入 引入css代码即可
//配置vue使用bootstrap css
import '@/assets/bootstrap/css/bootstrap.css'
Vue.config.productionTip = false
/* eslint-disable no-new */
new Vue({
el: '#app',
router,
components: { App },
template: '<App/>'
})
4.在项目中就可以直接引用样式了
<template>
<div>
<div class="container-fluid">
<div class="row" style="margin-top: 70px;">
<div class="col-sm-6 col-sm-offset-3">
<form action="" class="form-horizontal">
<div class="form-group">
<label class="col-sm-2 control-label">用户名:</label>
<div class="col-sm-10">
<input type="text" class="form-control" v-model="admin.username">
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label">密码:</label>
<div class="col-sm-10">
<input type="text" class="form-control" v-model="admin.password">
</div>
</div>
<input type="button" value="登录" class="btn btn-primary btn-block" @click="login">
</form>
</div>
</div>
</div>
</div>
</template>
13.3 Element ui
参考:
2.前后端分离