vue01 : vue基本语法
vue02 : 博彩项目采用vue方式实现
vue03 : 博彩项目采用vue方式实现
传统的Web项目 : 后台逻辑,html数据的渲染thymeleaf,jsp
web项目: 后台程序只负责提供数据, 前端负责去展现html数据
介绍
简单来说,Vue是一套渲染UI的强大前端框架。
主要特性:
- 学习曲线非常平缓,只要有html/css,js基础即可上手
- 响应式的支持,让我们从传统的JQuery的面向DOM编程,转变为面向数据编程
- 丰富的语法支持
- 优雅的单文件组件
- 完善的组件动画支持
- 成熟的生态,比如vue-cli,VueRouter,Vuex等相关配套的工具
其中,最重要最核心的特性就是:响应式和组件化。
安装
-
通过
<script></script>
引用<script src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js"></script>
-
通过vue-cli安装全套开发环境,项目开发推荐
快速尝鲜
通过一个简单的例子,来快速感受一下Vue的特性。
例子中使用:值填充以及响应式的UI刷新,
-
v-model实现输入项双向绑定特性
-
v-for循环
-
v-if条件判断
-
v-on:click单击事件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js"></script>
</head>
<body>
<div id="app">
{{msg}}
<input type="text" v-model="username"><span>{{username}}</span>
<ul>
<li v-for="item in list">{{item}}</li>
</ul>
<h3 v-if="isShow">我在某些条件下才显示</h3>
<button @click="isShow=!isShow">点我隐藏上面的文字</button>
</div>
<script>
let vm = new Vue({
el: '#app',
data:{
msg: "我是Vue",
list:[
'a', 'b', 'c'
],
isShow: true,
username: "aaaa"
}
});
setTimeout(()=>{
vm.msg = "我的值被改变了,会响应式的刷新到UI上";
vm.list.push("dd");
}, 2000)
</script>
</body>
</html>
Vue实例
数据和方法
每一个Vue实例,都可以有自己的数据和自定义方法。自定义方法一般用来获取数据或者对数据进行处理。
let vue = new Vue({
el: "#app",
data: {
content: "aaa"
},
template: "<div><button v-on:click="handleClick">点我让content变化</button> : {{content}}</div>",
methods: {
handleClick(){
this.content = "bbb"
}
}
});
生命周期钩子
所谓的生命周期其实就像我们人,从出生到成长到死亡的过程一样.在Vue中生命周期指的是Vue实例从初始化,创建,显示,更新以及销毁的整个过程,而生命周期钩子指的是每个过程都有一个回调函数,Vue中把回调函数称为钩子。
- beforeCreate : 开始创建实例
- created : 实例创建出来了,vue的实例基本上被初始化
- beforeMount : 模版与数据相结合,页面渲染之前,执行的函数
- mounted: 模版和数据结合完成,会将Vue实例挂载到dom树上
- beforeDestroy : 实例要被回收的时候执行
- destroyed : 实例回收完成的时候调用
- beforeUpdate: 数据发生改变,还没有渲染之前
- updated : 渲染完成
再次回顾一下什么是Vue生命周期钩子? 生命周期钩子就是Vue实例在某个时间点自动执行的回调函数.我们常用的生命周期钩子有: created,mounted
<script>
let vm = new Vue({
el:'#app',
template:'<span>{{msg}}</span>',
data:{
msg:'hahaha'
},
beforeCreate(){
console.log("beforeCreate...")
},
created(){
console.log("created...")
},
beforeMount(){
console.log("beforeMount..."+this.$el.innerHTML)
},
mounted(){
console.log("mounted..."+this.$el.innerHTML)
},
beforeDestroy(){
console.log("beforeDestory...")
},
destroyed(){
console.log("destoryed...")
},
beforeUpdate(){
console.log("beforeUpdate...")
},
updated(){
console.log("updated")
}
})
</script>
计算属性
计算属性和方法都可以对数据进行处理。但是计算属性有基于依赖数据的智能缓存,当计算属性所依赖的值发生改变,计算属性才会重新计算, 所以性能更高,我们应该优先考虑使用。
如果是普通的方法实现相同的功能,每当页面数据任何数据发生改变的时候,方法都会被执行一次
let vue = new Vue({
el: "#app",
data: {
firstName: "Xiao",
lastName: "Kaikai",
age:30
},
computed: {
// 计算属性有基于依赖数据的缓存
fullName(){
console.log("计算属性执行了一次");
return this.firstName + this.lastName;
}
} ,
methods: {
getFullName(){
console.log("自定义方法执行了");
return this.firstName + this.lastName;
}
}
});
侦听器
侦听器可以用来侦听数据的改变. 如果一个功能,方法能实现,计算属性能实现,侦听器也能实现,我们应该优先选择计算属性
let vm = new Vue({
el:'#app',
data:{
firstName:'Kaikai',
lastName:'Xiao',
age:30,
fullName:"Kaikai Xiao"
},
methods:{
getFullName(){
console.log("getFullName执行了一次运算")
return this.firstName + ' ' + this.lastName;
}
},
watch:{
firstName(newVal,oldVal){
this.fullName = this.firstName + this.lastName;
console.log('newVal:'+newVal+" oldVal:"+oldVal);
},
lastName(){
this.fullName = this.firstName + this.lastName;
}
}
}
class动态绑定
Vue允许我们给DOM元素动态绑定一些class。
<body>
<div id="app">
<div class="c1" :class="{c2:isShow,c3:isShow}" @click="isShow=!isShow" >{{name}}</div>
class动态绑定数组的语法
<div class="c1" :class="classes" @click="isShow=!isShow" >{{name}}</div>
</div>
</body>
<script>
let vm = new Vue({
el:'#app',
data:{
name:'zhangsan',
isShow:true,
classes:['c1','c2','c3']
}
});
</script>
<style>
.c1{
font-size: 10px;
color: green;
background-color: yellow;
}
.c2{
font-size: 30px;
}
.c3{
background-color: red;
}
</style>
条件渲染
v-show
<div v-show="isShow">页面内容v-show</div>
v-if
v-else-if
v-else
<div id="app" >
<div v-if="isLogin">您好,刘德华</div>
<div v-else><button @click="isLogin=true">登录</button></div>
<!--对于需要频繁切换显示隐藏的场景,用v-show,因为性能更高-->
<!--<div v-show="isLogin">您好,刘德华2</div>-->
</div>
<script>
let vue = new Vue({
el: "#app",
data: {
isLogin: false
}
});
</script>
列表渲染
当我们去使用v-for的时候,最好去给它指定一个唯一的key值,这样的会方便vue复用dom节点,从而提高性能
遍历数组
使用的语法: v-for="(item,index) in 数组" 若写了:key,那么它的值需要是唯一的值
<div id="app" >
<div>最好吃的水果:</div>
<div v-for="item in list">{{item}}</div>
<input type="text" v-model="fruit"><button @click="handleClick">添加</button>
<div>
<button @click="handleDelete">删除第</button><input type="text" v-model="index">个
</div>
</div>
<script>
let vm = new Vue({
el: "#app",
data: {
list:[
"苹果","西瓜","哈蜜瓜"
],
fruit: "",
index: 0
},
methods:{
handleClick(){
this.list.push(this.fruit);
this.fruit = "";
},
handleDelete(){
this.list.splice(this.index, 1);
}
}
});
</script>
注意:当我们去修改数组的时候,不能使用下标的方式,否则数据添加进去了,页面不会刷新,我们需要借助数组提供的一些方法来修改,我们常用的数组方法有:
- push : 添加元素
- pop : 取出末尾元素
- splice : 根据角标删除元素
- sort : 排序
- forEach : 循环处理
遍历对象
v-for="(item,key,index) in 对象"
<div v-for="item,key,index in user">{{item}}--{{key}}--{{index}}</div>
let vm = new Vue({
el:'#app',
data:{
user:{
username:"haha",
password:123,
age:100
}
}
});
注意: 我们如果直接添加一个属性,页面上并不会跟着刷新
Vue中的set方法
当我们去修改某一个对象的内容的时候,由于vue中并不知道对象内容发生了改变,所以也就不会重新渲染了,若想当对象内容发生改变页面重新渲染,我们需要借助Vue给我们提供的一下方法
使用全局的方法: Vue.set(对象,改变的key,改变的值)
使用实例的方法: vm.$set(对象,改变的key,改变的值)
数组中使用set方法: vm.$set(对象,要改变的下标,改变的值)
ToDoList
用上面学的语法,实现一个ToDoList。
<body>
<div id="app">
<h3>添加今日要完成任务</h3>
<input type="text" v-model="currentInput" /><button @click="handleAdd">添加</button>
<ul>
<li v-for="item in todos" :class="{done:item.isDone}" >
{{item.text}}
<button @click="handleComplete(item)" >标记完成</button>
<button @click="handleDelete(item)">删除</button>
</li>
</ul>
</div>
</body>
<style>
.done{
background-color: red;
}
</style>
<script>
let vm = new Vue({
el:'#app',
data:{
todos:[],
currentInput:""
},
methods:{
handleAdd(){
//判断是否为空
if(this.currentInput === ""){
return ;
}
//检查是否有重复的内容
for(let i=0;i<this.todos.length;i++){
//数组中的每一项
let item = this.todos[i];
//判断是否有重复
if(item.text === this.currentInput){
return;
}
}
//获取输入项的内容,将输入项的内容存到todos
this.todos.push({text:this.currentInput,isDone:false});
//清空输入项的内容
this.currentInput = ""
},
handleComplete(item){
item.isDone = true;
},
handleDelete(item){
//从todos中删除这个item
let index = this.todos.indexOf(item);
//调用数组中删除的方法
this.todos.splice(index,1);
}
}
});
</script>
</html>
组件
组件是Vue的核心之一,任何一个大的系统都可以由多个小的组件共同构成。组件的复用性,也大大提高了前端开发的效率。
组件注册
组件的注册有全局注册和局部注册两种方式。
全局注册: 注册之后可以用在任何新创建的 Vue 根实例 (new Vue
) 的模板中
全局组件
<script>
/*定义一个全局组件*/
Vue.component('title-bar',{
template:`<div><h1>首页标题栏</h1></div>`
});
/*定义一个全局组件*/
Vue.component('MenuBar',{
template:`<div><h1>底部菜单栏</h1></div>`
});
let vm = new Vue({
el:'#app'
});
</script>
局部组件
局部注册: 全局注册往往是不够理想的。比如,如果你使用一个像 webpack 这样的构建系统,全局注册所有的组件意味着即便你已经不再使用一个组件了,它仍然会被包含在你最终的构建结果中。这造成了用户下载的 JavaScript 的无谓的增加。
<script>
<!--定义局部组件-->
let TitleBar = {
name:'title-bar',
template:`<div><h1>{{title}}标题部分</h1></div>`,
data(){
return {
title:'首页'
}
}
}
/*定义一个局部组件*/
let MenuBar = {
name:'menu-bar',
template:`<div><h1>底部菜单部分</h1></div>`
}
//根实例
let vm = new Vue({
el:'#app',
components:{
TitleBar,
MenuBar
}
});
</script>
父子组件数据通信
父子组件之间往往不是独立的,需要进行数据的通信。从父到子,用props;从子到父,用$emit。
<div id="app">
<ul>
<li v-for="item,index in list"><todo-item :content="item" :index='index' @delete-item="handleDeleteItem"></todo-item></li>
</ul>
<child :text="text"></child>
</div>
<script>
// 全局注册
Vue.component("todo-item", {
props:['content','index'],
data() {
return {
}
},
template: "<div @click='handlerClick'>{{content}}</div>",
methods: {
handlerClick(){
this.$emit("delete-item", this.index);
}
}
});
// 子组件不要去直接修改父组件的数据
Vue.component("child", {
props:['text'],
data() {
return {
myText: this.text
}
},
template: "<div @click='changeText'>{{myText}}</div>",
methods: {
changeText(){
this.myText = "修改了的文字";
}
}
});
let vue = new Vue({
el: "#app",
data: {
list: [
"吃饭", "睡觉", "打豆豆"
],
text: "文字"
},
methods:{
handleDeleteItem(index){
this.list.splice(index, 1);
}
}
});
</script>
组件绑定原生事件
如果我们在自定义组件上绑定事件是没有效果的,因为组件上定义的事件都是自定义的,想要触发需要我们在子组件内部调用$emit派发.但是这样做又很麻烦,所以当我们想使用点击事件,我们可以使用Vue提供的绑定原生事件方式,我们只需要使用@click.native
<div id="app">
<child :text="text" @click.native="handleChildClick"></child>
</div>
<script>
//全局组件
Vue.component('child',{
template:`<div>子组件的内容展示</div>`
/*template:`<div @click="handleChildClick">子组件的内容展示</div>`,
methods:{
handleChildClick(){
console.log("child click");
this.$emit('click');
}
}*/
});
//根实例 ,父组件
let vm = new Vue({
el:'#app',
methods:{
handleFatherClick(){
console.log("father click")
}
}
});
</script>
组件插槽
有时候我们组件的内容是不确定的,我们定义组件的时候使用slot留出空白,外界使用的时候动态插入,这就是插槽。
<body>
<div id="app">
<child >
<div slot="header">header</div>
<!--<div slot="footer">footer</div>-->
</child>
</div>
</body>
<script>
//定义子组件
Vue.component('child',{
template:`<div>
<slot name="header"></slot>
<div>内容不变</div>
<slot name="footer">默认页脚</slot>
</div>
`
});
//根实例 ,父组件
let vm = new Vue({
el:'#app',
});
</script>
动态组件:is
动态组件可以非常方便的切换几个不同的组件,而且支持缓存。
<body>
<div id="app">
<component :is="currentName"></component>
<button @click="handleClick('home')">首页</button>
<button @click="handleClick('my')">我的</button>
</div>
</body>
<script>
Vue.component('home',{
template:`<div>这是网站首页的内容</div>`
});
Vue.component('my',{
template:`<div>这是我的个人页面</div>`
})
//根实例 ,父组件
let vm = new Vue({
el:'#app',
data:{
currentName:'home'
},
methods:{
handleClick(name){
this.currentName = name;
}
}
});
</script>
Vue-cli
以上内容是项目开发中常用的基础知识点。但是做项目开发,我们需要考虑一下几点:
- 编写的代码需要打包工具进行打包压缩,图片处理
- 为了效率,希望有一个HotReload功能,不用手动刷新
- Vue单文件组件的支持
- 第三方JS编译器的使用,如babel
- 第三方CSS预处理器的使用,如stylus,sass
- 第三方插件的使用,如ESLint。PostCSS
而Vue-cli就为了解决上面的问题而生的,它给我们打包好了所有能用到的好工具,提供一个开箱即用的项目开发环境。所以,我们需要用它来创建项目。
vue-cli官网:https://cli.vuejs.org/,官网写的是3.0版本的使用,2.xx才是稳定版。
vue-cli github主页:https://github.com/vuejs/vue-cli
创建工程
vue-cli的github网站默认是3.0的测试版本分支,需要切换为主分支。
npm install -g vue-cli
vue init webpack xxx
?Project name lottery
?Project description this is a niubility project
?Author xiaokaikai
?Vue build (选择一种构建的形式)
> Runtime + Compiler: recommended for most users
?Install vue-router?(Y/n) Y --这里说是否安装路由插件
?Use ESLint to lint your code? N-- 是否检查代码格式
?Pick an ESLint preset Standard -- 选择一种代码检查的规范
?Set up unit tests N 是否进行单元测试
?Setup e2e tests with Nightwatch N 是否使用e2e工具进行构建
?Should we run 'npm install' for you after the project has been created? npm --选择npm方式安装
输入完成之后,工具就开始构建我们的工程啦!
工程目录结构
- build:构建相关目录
- config:开发相关配置
- src:要编写的代码
- static:不需要webpack处理的静态文件,比如压缩后的资源,可以直接访问
Vue-Router
传统的路由是后端来做,简单说就是请求一个url,后端根据请求的参数内容渲染出相应的html返回。由于JS可以感知到浏览器URL的变化,因此可以做到在url变化的时候去加载不同的DOM内容,这就是前端路由,和后端没有任何关系了。
单页应用(SPA)的用户体验比传统的多页应用要好很多,所以越来越多的公司开始尝试单页应用。单页应用就将原来的多个页面做成一个html,JS根据url的变化切换DOM的内容。这样不用再去请求服务器的整个html内容,只需要请求对应的json数据,因此速度会快很多。
Vue-Router为前端路由提供了封装和简化,并结合组件的使用。让我们可以一个url对应一个组件,轻松编写大型的SPA应用。
<router-view> 显示当前路径所对应的组件内容
<router-link to="要跳转去的组件的路径">
总结:
根实例 : let vm = new Vue({参数})
el
template
data
methods
computed
watch
props
生命周期钩子
vue中属性
v-model
v-show
v-if
v-else-if
v-else
v-for
v-html
v-text
使用属性: :属性名称
绑定事件:@事件名称
全局组件和局部组件
父子组件之间通讯
父-->子 : props
子 --> 父: $emit(事件名称)
@click.native 组件绑定原生事件
动态组件: <component :is=组件的名称