vue01 : vue基本语法javascript
vue02 : 博彩项目采用vue方式实现css
vue03 : 博彩项目采用vue方式实现html
传统的Web项目 : 后台逻辑,html数据的渲染thymeleaf,jsp前端
web项目: 后台程序只负责提供数据, 前端负责去展示html数据vue
简单来讲,Vue是一套渲染UI的强大前端框架。java
官网地址:https://cn.vuejs.org/webpack
主要特性:git
其中,最重要最核心的特性就是:响应式和组件化。github
官方文档:https://cn.vuejs.org/web
经过<script></script>
引用
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js"></script>
经过vue-cli安装全套开发环境,项目开发推荐
经过一个简单的例子,来快速感觉一下Vue的特性。
例子中使用:值填充以及响应式的UI刷新,
v-model实现输入项双向绑定特性
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实例,均可以有本身的数据和自定义方法。自定义方法通常用来获取数据或者对数据进行处理。
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中把回调函数称为钩子。
再次回顾一下什么是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; } } }
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>
注意:当咱们去修改数组的时候,不能使用下标的方式,不然数据添加进去了,页面不会刷新,咱们须要借助数组提供的一些方法来修改,咱们经常使用的数组方法有:
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中并不知道对象内容发生了改变,因此也就不会从新渲染了,若想当对象内容发生改变页面从新渲染,咱们须要借助Vue给咱们提供的一下方法
使用全局的方法: Vue.set(对象,改变的key,改变的值)
使用实例的方法: vm.$set(对象,改变的key,改变的值)
数组中使用set方法: vm.$set(对象,要改变的下标,改变的值)
用上面学的语法,实现一个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>
动态组件能够很是方便的切换几个不一样的组件,并且支持缓存。
<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就为了解决上面的问题而生的,它给咱们打包好了全部能用到的好工具,提供一个开箱即用的项目开发环境。因此,咱们须要用它来建立项目。
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方式安装 输入完成以后,工具就开始构建咱们的工程啦!
传统的路由是后端来作,简单说就是请求一个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=组件的名称