1 Vue
- 官网:
Vue.js
2 Node、NPM
- NPM是Node提供的模块管理工具,可以非常方便地下载安装很多前端框架。
1、Node.js
2、NPM
Node.js自带了NPM,在控制台输入
npm -v
即可查看版本信息。NPM默认的仓库地址在国外,速度较慢,建议设置到淘宝镜像。切换镜像比较麻烦,推荐使用切换镜像的工具:nrm。
安装nrm,
-g
表示全局安装:npm install nrm -g
nrm ls
:显示所有镜像。nrm use [name]
:使用指定镜像。
3 Vue快速入门
3.1 创建
1、新建空项目
2、初始化
- 在项目目录下执行命令:
npm init
。 - 项目中会多出一个文件:
package.json
(相当于XML配置文件)。
3、安装Vue
- 在项目目录下执行命令:
npm install vue —save
。 - 项目中会多出一个文件:
node_modules
,其中就有Vue。
- 同时,
package.json
中也会增加Vue的依赖。
4、Hello Vue
<!DOCTYPE html> <html lang="en" xmlns:v-on="http://www.w3.org/1999/xhtml"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <!--Vue对象的HTML模板--> <div id="app"> <h1>{{name}}</h1> <!--双向绑定:v-model--> <input type="text" v-model="num"> <h1>{{num}}</h1> <!--v-on:事件名:定义事件--> <input type="button" value="num++" v-on:click="num++"> <input type="button" value="num++" v-on:click="incre"> </div> </body> <script src="node_modules/vue/dist/vue.js"></script> <script> // 初始化一个Vue实例 const app = new Vue({ el: "#app", // element缩写,"#app"选择器 data: { // 定义数据模型 name: "Hello Vue", num: 100 }, methods: { // 定义方法 incre() { this.num++; } } }); </script> </html>
3.2 生命周期、钩子函数
每个Vue实例在被创建时都要经过一系列的初始化过程:创建实例、装载模板、渲染模板等。
Vue为生命周期中的每个状态都设置了钩子函数(监听函数)。
每当Vue实例处于不同的生命周期时,对应的函数就会被触发调用。
常用:
created() { // 实例化之后,渲染之前:获取数据 // 1、获取数据:Ajax // 2、绑定数据:this.name = result }
3.3 指令
- 指令是带有
v-
前缀的特殊特性。 - 指令特性的预期值是:单个JavaScript表达式。
- 指令的职责是:当表达式的值改变时,将其产生的连带影响,响应式的作用域DOM。
1、数据绑定
花括号(会有闪烁问题)
{{表达式}}
v-text
、v-html
(没有闪烁问题)<h1>xxx<span v-text="name">默认值</span>xxx</h1>
v-model:双向绑定,用在表单元素中。
2、事件绑定:v-on
、@
绑定事件。
语法:
v-on:事件名="函数名" @事件名="函数名"
在响应函数里,可以指明使用event内置的参数对象。该对象表示当前事件,可以通过使用event.target.value来获得当前事件对象的value值。
changeMajor(event) { this.msg = event.target.value; }
可以使用data()中的数据进行数据传递:
<template> <div> {{count}} <button type="button" @click="addBtn">add</button> <p>myStep: <input type="text" v-model="myStep"></p> </div> </template> <script> export default { name: 'HelloWorld', data () { return { count: 0, myStep: 1 } }, methods: { addBtn() { var myNum = this.myStep - 0; this.count += myNum; } } } </script>
也可以直接在函数中进行传递数据:
<template> <div> {{count}} <button type="button" @click="addBtn">add</button> </div> </template> <script> export default { name: 'HelloWorld', data () { return { count: 0, } }, methods: { addBtn(step) { this.count += step; } } } </script>
Vue为
v-on
提供了事件修饰符:.stop
:阻止事件冒泡到父元素。.prevent
:阻止默认事件发生。.capture
:使用事件捕获模式。.self
:只有元素自身触发事件才执行(冒泡或捕获的都不执行)。.once
:只执行一次。v-on.click.prevent="num++:"
按键修饰符:
@keyup.13
、@keyup.enter
:回车事件。- ……
组合按钮:
.ctrl
、.ctrl.67
。.alt
。- ……
3、遍历数据:v-for
语法:
v-for="item in items" v-for="(item, index) in items" :key="index" v-for="(val, key, index) in users" :key="index"
同时使用
:key
可以增加效率。案例:
<!DOCTYPE html> <html lang="en" xmlns:v-on="http://www.w3.org/1999/xhtml"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <!--Vue对象的HTML模板--> <div id="app"> <ul v-for="item in arr"> <li v-text="item"></li> </ul> <ul v-for="(item, index) in arr" :key="index"> <li>{{index}}-{{item}}</li> </ul> </div> </body> <script src="node_modules/vue/dist/vue.js"></script> <script> // 初始化一个Vue实例 const app = new Vue({ el: "#app", // element缩写,"#app"选择器 data: { // 定义数据模型 arr: [1, 2, 3, 4, 5, 6, 7, 8,] } }); </script> </html>
4、条件渲染:v-if
、v-show
v-if
:当布尔表达式的值为true时,显示该元素。值为false时,不渲染该元素,效率更高。可以与
v-else-if
、v-else
联用。v-if="布尔表达式"
v-show
:当布尔表达式的值为true时,显示该元素。始终渲染,当值为false时,设置为display:none
,效率更低。v-show="布尔表达式"
5、属性绑定:v-bind
、:
- 绑定属性(主要用于绑定class属性)。
<template> <div> <div class="mydiv" :class="{red: isRed}"></div> <p><button type="button" @click="changeBtn">改变颜***utton></p> <div class="mydiv" :class="myColor"></div> <p>颜色:</p> <p>红色<input type="radio" v-model="myColor" value="red" name="myColor"></p> <p>蓝色<input type="radio" v-model="myColor" value="blue" name="myColor"></p> <p>黑色<input type="radio" v-model="myColor" value="black" name="myColor"></p> </div> </template> <script> export default { name: 'HelloWorld', data () { return { isRed: false, myColor: '' } }, methods: { changeBtn() { this.isRed = !this.isRed; } } } </script> <style scoped> .mydiv { width: 500px; height: 500px; } .red { background-color: red; } .blue { background-color: blue; } .black { background-color: black; } </style>
6、计算属性:computed
computed:
里定义方法,方法必须要有返回值。像普通数据一样使用,不用加()。计算属性基于它们的依赖进行缓存,只有在它的相关依赖发生改变时才会重新求值。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <!--Vue对象的HTML模板--> <div id="app"> <p>{{birth}}</p> </div> </body> <script src="node_modules/vue/dist/vue.js"></script> <script> // 初始化一个Vue实例 const app = new Vue({ el: "#app", // element缩写,"#app"选择器 data: { // 定义数据模型 birthday: 14564687945121, }, computed: { // 计算属性 birth() { var date = new Date(this.birthday); return date; } } }); </script> </html>
7、监听:watch
watch:
里定义方法,方法名必须与被监听的数据名一致。通常在方法里发送异步请求,根据监听的数据值的变化进行即时查询。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <!--Vue对象的HTML模板--> <div id="app"> <input type="text" v-model="search"> </div> </body> <script src="node_modules/vue/dist/vue.js"></script> <script> // 初始化一个Vue实例 const app = new Vue({ el: "#app", // element缩写,"#app"选择器 data: { // 定义数据模型 search: "" }, watch: { // 监听 search (newVal, oldVal) { // 方法名与监听的数据名必须一致 // 发送异步请求,根据监听的值进行查询 console.log(newVal + " " + oldVal); } } }); </script> </html>
3.4 组件化
- 在大型应用开发的时候,页面可以划分成很多部分。往往不同的页面,会有相同的部分。
- 如果每个页面都独自开发,会增加开发的成本。所以,将页面的不同部分拆分成独立的组件,在不同的页面***享这些组件,可以避免重复开发。
- 在Vue里,所有Vue实例都是组件。
1、全局组件:Vue.component()
组件的
data
必须是函数,保证了复用。可以在任何实例中使用。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <div id="app"> <counter></counter> <counter></counter> <counter></counter> </div> </body> <script src="node_modules/vue/dist/vue.js"></script> <script> Vue.component("counter", { template: "<button @click='num++'>num++:{{num}}</button>", data() { return { num: 0 } } }) const app = new Vue({ el: "#app", }) </script> </html>
2、局部组件
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <div id="app"> <myhello></myhello> </div> </body> <script src="node_modules/vue/dist/vue.js"></script> <script> const hello = { template: "<div>{{name}}</div>", data() { return { name: "Xianhuii" } } }; const app = new Vue({ el: "#app", components: { myhello: hello } }) </script> </html>
3、父向子传递数据:props
父组件使用子组件时,使用自定义属性传递数据:
- 属性名任意,为子组件的数据名。
- 属性值为父组件的数据名。
子组件使用
props
,通过自定义属性的属性名(即子组件的数据名),接收父组件的数据。<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <div id="app"> <counter :number="num"></counter> </div> </body> <script src="node_modules/vue/dist/vue.js"></script> <script> Vue.component("counter", { template: "<button @click='number++'>num++:{{number}}</button>", props: ["number"] }) const app = new Vue({ el: "#app", data: { num: 0 } }) </script> </html>
4、子向父传递数据:$emit()
父:
<template> <div> <Sub @paramFun="supFun($event)"></Sub> {{num}} {{supMsg}} </div> </template> <script> export default { name: 'Sup', data() { return { num: 0, supMsg: '' } }, methods: { supFun(value) { this.num++; this.supMsg = value } } } </script>
子:
<template> <div> <button @click='subFun()'>num++</button> </div> </template> <script> export default { name: "Sub", data() { return { subMsg: 'subMsg' } }, methods: { subFun() { this.$emit("paramFun", this.subMsg); } } } </script>
5、全局注册
- 在main.js中:
import Header from './components/Header' import Content from './components/Content' Vue.component('myheader',Header) Vue.component('mycontent',Content)
6、局部注册
在特定Example.vue中:
<script> import Header from './Header' import Content from './Content' export default { name: 'HelloWorld', components: { 'myheader': Header, 'mycontent': Content } } </script>
3.5 路由:vue-router
1、安装
在项目目录下,使用以下命令:
npm install vue-router --save
安装成功后,在
node_modules
目录下会新增vue-router
模块:
2、引入
- 在引入Vue之后引入:
<script src="../node_modules/vue/dist/vue.js"></script> <script src="../node_modules/vue-router/dist/vue-router.js"></script>
3、使用
<script> const router = new VueRouter({ routes: [ { path: "/login", // 路由路径,必须以“/”开头 component: loginForm // 对应的组件 }, { path: "/register", component: registerForm } ] }) const app = new Vue({ el: "#app", router // 注册router }) </script>
4、案例
组件1:
login.js
// 组件内的template只能有一个跟标签 const loginForm = { template: ` <div> <h1>登录页</h1> <p>用户名:<input type="text"></p> <p>密 码:<input type="password"></p> <p><input type="submit" value="登录"></p> </div> ` }
组件2:
register.js
// 组件内的template只能有一个跟标签 const registerForm = { template: ` <div> <h1>注册页</h1> <p>用 户 名:<input type="text"></p> <p>密  码:<input type="password"></p> <p>确认密码:<input type="password"></p> <p><input type="submit" value="注册"></p> </div> ` }
主页面:
index.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <div id="app"> <span><router-link to="/login">登录</router-link></span> <span><router-link to="/register">注册</router-link></span> <hr> <router-view></router-view> </div> </body> <!--引入vue--> <script src="../node_modules/vue/dist/vue.js"></script> <!--引入vue-router--> <script src="../node_modules/vue-router/dist/vue-router.js"></script> <!--引入login组件--> <script src="js/login.js"></script> <!--引入register组件--> <script src="js/register.js"></script> <script> const router = new VueRouter({ routes: [ { path: "/login", // 路由路径,必须以“/”开头 component: loginForm // 对应的组件 }, { path: "/register", component: registerForm } ] }) const app = new Vue({ el: "#app", router // 注册router }) </script> </html>
3.6 axios
- 官网:axios
1、添加axios
项目根目录下,在命令行中输入:
vue add axios
在Vue项目中的plugins目录下新增axios.js插件:
2、使用axios
在Example.vue中的<script>标签的函数中可以直接使用axios调用方法,如下可以将从后端得到的数据赋值给books数组:
<script> export default { name: "Example", data() { return { books: [] } }, created() { const _this = this axios.get('http://localhost:8181/book/findAll') .then(function(resp) { _this.books = resp.data }) } } </script>
GET请求:
const axios = require('axios'); // Make a request for a user with a given ID axios.get('/user?ID=12345') .then(function (response) { // handle success console.log(response); }) .catch(function (error) { // handle error console.log(error); }) .then(function () { // always executed }); // Optionally the request above could also be done as axios.get('/user', { params: { ID: 12345 } }) .then(function (response) { console.log(response); }) .catch(function (error) { console.log(error); }) .then(function () { // always executed }); // Want to use async/await? Add the `async` keyword to your outer function/method. async function getUser() { try { const response = await axios.get('/user?ID=12345'); console.log(response); } catch (error) { console.error(error); } }
POST请求:
axios.post('/user', { firstName: 'Fred', lastName: 'Flintstone' }) .then(function (response) { console.log(response); }) .catch(function (error) { console.log(error); });
4 项目
4.1 项目技巧
1、安装package.json
中的依赖
npm install
2、运行
npm run dev # 或者 npm start
4.2 Vue UI框架
Vuetify:
快速开始 - Vuetify.js
4.3 域名
1、域名解析相关概念
本地hosts文件
ip 域名
DNS服务器
ip 域名
2、本地修改域名
- SwitchHosts修改IP地址
- 在项目的
build/webpack.dev.conf.js
中:devServer: { disableHostCheck:true // 添加 }
4.4 Ngnix
1、Ngnix简介
- Ngnix是一个高性能的Web服务器和反向代理服务器。
- 更多的时候,我们把Ngnix作为网关,因为它具备网关必备的功能:
- 反向代理。
- 负载均衡。
- 动态路由。
- 请求过滤。
2、Web服务器
- Web服务器:Apache服务器、Ngnix、IIS。
- Web应用服务器:tomcat、resin、jetty。
- Web服务器只能处理JS、CSS、HTML等静态资源,不能解析JSP等页面。
- Web服务器的并发能力远高于Web应用服务器。
3、代理
- 代理(代理客户端):通过客户机的配置,实现让一台服务器代理客户机,客户的所有请求都交给代理服务器处理。
- 反向代理(代理服务器):用一台服务器,代理真实服务器,用户访问时,不再是访问真实服务器,而是代理服务器。
4、安装目录
5、启动、重新加载
启动:
start ngnix
重新加载:
nginx -s reload
6、配置:nginx.conf
worker_processes 1; events { worker_connections 1024; } http { include mime.types; default_type application/octet-stream; sendfile on; keepalive_timeout 65; server { listen 80; # 监听端口 server_name manage.leyou.com; # 监听域名 location / { # 代理路径 proxy_pass http://127.0.0.1:9001; proxy_connect_timeout 600; proxy_read_timeout 60; } error_page 500 502 503 504 /50x.html; location = /50x.html { root html; } } }
7、访问解析过程
- 访问:
http://manage.leyou.com
。 - 在
hosts
文件中找到对应IP地址:manage.leyou.com
→127.0.0.1
。 - 默认端口为
80
(即此时Nginx监听的端口),找到Ngnix。 - Ngnix中对
manage.leyou.com
配置的代理路径为:http://127.0.0.1:9001
,即对应的Web项目(此Web项目正在监听9001端口)。