VUE-入门
什么是VUE?
VUE是一套用于构建用户界面的渐进性框架,Vue被设计可以自底向上逐层应用,Vue只关注视图层。易上手。
MVVM模式的实现者
Model:模型层,在这里表现JavaScript对象
View:视图层,在这里表示DOM
ViewModel:连接视图和数据的中间件,能够观察到数据的变化,并对视图对应的内容进行更新;能够监听到视图的变化,并能够通知数据发生改变。
为什么要使用MVVM
主要目的是分离视图和模型
- 低耦合
- 可复用
- 独立开发
- 可测试
第一个Vue程序
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>主页</title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
//View层
<div class="app">{{message}}</div>
</body>
<script>
var ve=new Vue({
el: ".app",
//model层 数据
data:{
message:"hello vue"
}
});
</script>
</html>
标签
v-bind
<body>
<div class="app">
<span v-bind:title="message">//鼠标悬停出现文字
nihao</span>
</div>
</body>
<script>
var ve=new Vue({
el: ".app",
data:{
message:"hello vue"
}
});
V-if
<body>
<div id="app">
<h1 v-if="type==='A'">A</h1>
<h1 v-else-if="type=='B'">B</h1>
</div>
</body>
<script>
var vm=new Vue({
el: "#app",
data: {
ok: true,
type: "A"
}
})
</script>
v-for
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
<div id="app">
<h1 v-for="(item,index) in items">{{item.message}}{{index}}</h1>
</div>
</body>
<script>
var vm=new Vue({
el: "#app",
data: {
items: [
{message: 'java'},
{message: 'html'},
{message: 'hadoop'}
]
}
})
</script>
</html>
函数
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
<div id="app">
<button v-on:click="sayhi">点击</button>
</div>
</body>
<script>
var vm=new Vue({
el: "#app",
data: {
message: "free"
},
methods: { //方法必须定义再Vue的method对象中
sayhi: function () {
alert(this.message)
}
}
})
</script>
</html>
双向绑定,组件
数据双向绑定,当数据发生变化的时候,视图也就跟着发生变化,当视图发生变化的时候,数据也跟同步变化
V-model
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
<div id="app">
scannner<input type="text" v-model="message"/>
{{message}}
</div>
<select v-model="message">
<option value=" " disabled>qinngxuanz</option>
<option value="a" >a</option>
<option value="b" >b</option>
<option value="c">c</option>
</select>
<span>{{message}}</span>
</body>
<script>
var vm=new Vue({
el: "#app",
data: {
message: "free"
}
})
</script>
</html>
什么是组件conponent
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
<div id="app">
<wangyun v-for="item in items" v-bind:wang="item"></wangyun>
</div>
</body>
<script>
Vue.component("wangyun",{
props: ['wang'],
template: '<li>{{wang}}<li>'
})
var vm=new Vue({
el: "#app",
data: {
items: [
"java","html","aini"
]
}
})
</script>
</html>
网络通信
什么是Axios
Axios是一个基于Promise(ES6中用于处理异步的)的HTTP库(HTTP客户端),用于浏览器和node.js中,API。
Vue的生命周期
Vue的实例有一个完整的生命周期,也就是从开始创建,初始化数据,编译模板,挂载DOM,渲染 更新 渲染 卸载称为Vue的生命周期。
beforecreate
: 一般使用场景是在加 loading事件 的时候created
:处于loading结束后,还做一些初始化,实现函数自执行(data数据已经初始化,但是DOM结构渲染完成,组件没有加载)beforemount
:处于组件创建完成,但未开始执行操作mounted
:处于发起后端请求,获取数据,配合路由钩子执行操作(DOM渲染完成,组件挂载完成 )beforeupdate
、updated
:处于数据更新的前后beforeDestroy
:当前组件还在的时候,想删除组件destroyed
:当前组件已被销毁,清空相关内容
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<style>
[v-cloak]{
display: none;
}
</style>
</head>
<body>
<!--cloak解决闪烁问题-->
<div id="app" v-cloak>
{{info.name}}
</div>
</body>
<script>
var vm=new Vue({
el: "#app",
data(){
return{
info:{
name: null
}
}
},
mounted(){
axios.get('data.json').then(Response=>this.info=Response.data)
}
})
</script>
</html>
计算属性
什么是计算属性?
是属性,简单来说就是可以将计算结果缓存起来的属性(将行为转化为静态的属性)
computed:
调用方法时,每次都需要进行计算,主要特性就是为了将不经常变化的计算结果进行缓存,以节约我们的系统开销。
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>狂神说Java</title>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.js"></script>
</head>
<body>
<div id="vue">
<!--注意,一个是方法,一个是属性-->
<p>调用当前时间的方法:{{currentTime1()}}</p>
<p>当前时间的计算属性:{{currentTime2}}</p>
</div>
<script type="text/javascript">
var vm = new Vue({
el: '#vue',
data: {
message: 'Hello Vue'
},
methods: {
currentTime1: function () {
return Date.now();
}
},
computed: {
//currentTime2 ,这是一个属性!不是方法
currentTime2: function () {
this.message;
return Date.now();
}
}
});
</script>
</body>
</html>
注意:methods 和 computed 里的东西不能重名
- methods:定义方法,调用方法使用 currentTime1(),需要带括号
- computed:定义计算属性,调用属性使用 currentTime2,不需要带括号;this.message 是为了能够让 currentTime2 观察到数据变化而变化
- 如何在方法中的值发生了变化,则缓存就会刷新!可以在控制台使用
vm.message="qinjiang"
,改变下数据的值,再次测试观察效果!
结论:
内容分发
插槽
在vue中可以通过元素作为承载分发内容的出口。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
</head>
<body>
<div id="app">
<todo>
<todo-title slot="todo-title" :title="title"></todo-title>
<todo-items slot="todo-items" v-for="item in todoItems" :item="item"></todo-items>
</todo>
</div>
</body>
<script>
//插槽
Vue.component("todo",{
template: '<div>\
<slot name="todo-title"></slot>\
<ul>\
<slot name="todo-items"></slot>\
</ul>\
</div>'
});
Vue.component("todo-title",{
props: ['title'],
template: '<div>{{title}}</div>'
});
Vue.component("todo-items",{
props: ['item'],
template: '<li>{{item}}</li>'
})
var vm=new Vue({
el: "#app",
data: {
title: "hello,vue",
todoItems: ['java','html','css']
}
})
</script>
</html>
自定义事件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
</head>
<body>
<div id="app">
<todo>
<todo-title slot="todo-title" :title="title"></todo-title>
<todo-items slot="todo-items" v-for="(item,index) in todoItems" :item="item"
:index="index" v-on:remove="removeItem(index)" v-bind:key="index"></todo-items>
</todo>
</div>
</body>
<script>
//插槽
Vue.component("todo",{
template: '<div>\
<slot name="todo-title"></slot>\
<ul>\
<slot name="todo-items"></slot>\
</ul>\
</div>'
});
Vue.component("todo-title",{
props: ['title'],
template: '<div>{{title}}</div>'
});
Vue.component("todo-items",{
props: ['item','index'],
template: '<li>{{index}}{{item}} <button @click="remove">del</button></li>',
methods:{
remove: function (index) {
//自定义事件分发
this.$emit('remove',index)
}
}
});
var vm=new Vue({
el: "#app",
data: {
title: "hello,vue",
todoItems: ['java','html','css']
},
methods: {
removeItem:function (index) {
console.log("删除了"+this.todoItems[index]);
this.todoItems.splice(index,1);
}
}
})
</script>
</html>
Vue-cli
什么时Vue-cli
vue-cli官方提供了一个脚手架,用户快速生成一个vue的项目模板
作用:
- 统一的目录结构
- 本地调试
- 热部署
- 单元测试
- 集成打包上线
需要node.js的环境
切换淘宝镜像源:npm install npm -g
下载模板包:cnpm install vue-cli
查看下载列表 npm list
创建一个webpack 网站包
管理员身份运行cmd,进入目录,npm init webpack myvue
修复工具
启动:
输入localhost:8080
module.exports = {
dev: {
// Paths
assetsSubDirectory: 'static', //静态资源文件夹
assetsPublicPath: '/', //
proxyTable: {},
// Various Dev Server settings
host: 'localhost', // can be overwritten by process.env.HOST
port: 8080, // 端口号can be overwritten by process.env.PORT, if port is in use, a free one will be determined
autoOpenBrowser: false,
errorOverlay: true,
notifyOnErrors: true,
poll: false, // https://webpack.js.org/configuration/dev-server/#devserver-watchoptions-
什么是webpack
webpack是一个模块打包器(module bundler),webpack视HTML,JS,CSS,图片等文件都是一种 资源 ,每个资源文件都是一个模块(module)文件,webpack就是根据每个模块文件之间的依赖关系将所有的模块打包(bundle)起来。
npm install webpack -g
npm install webpack-cli -g
配置
创建webpack.config.js配置文件
- entry:入口文件,指定webpack用哪个文件作为项目的入口
- output:输出,指定webpack把处理完的文件放在指定路径
- module:模块,用于处理各种类型的文件
- plugins:插件
- resolve:设置路径指向
- watch:监听,用于设置文件改动后直接打包
路由
cnpm install vue-router --save-dev
创建content main的两个组件
contend.vue
<template>
<div>
<h1>wangyun</h1>
</div>
</template>
<script>
export default {
name: "Content"
}
</script>
<style scoped>
</style>
main.vue
<template>
<div>
<h1>wangyun</h1>
</div>
</template>
<script>
export default {
name: "main"
}
</script>
<style scoped>
</style>
安装路由,在src目录下,创建文件夹router,专门存放路由
import Vue from 'vue'
// 导入路由插件
import Router from 'vue-router'
// 导入上面定义的组件
import Content from '../components/Content'
import main from '../components/main'
import Wang from "../components/Wang";
// 安装路由
Vue.use(Router);
// 配置路由
export default new Router({
routes: [
{
// 路由路径
path: '/content',
// 路由名称
name: 'Content',
// 跳转到组件
component: Content
}, {
// 路由路径
path: '/',
// 路由名称
name: 'main',
// 跳转到组件
component: main
},{
// 路由路径
path: '/wang',
// 路由名称
name: 'wang',
// 跳转到组件
component: Wang
}
]
});
在main.js中配置路由
import Vue from 'vue'
import App from './App'
// 导入上面创建的路由配置目录
import router from './router'
//来关闭生产模式下给出的提示
Vue.config.productionTip = false;
new Vue({
el: '#app',
// 配置路由
router,
components: { App },
template: '<App/>'
});
在App.vue中使用路由
<template>
<div id="app">
<!--
router-link: 默认会被渲染成一个 <a> 标签,to 属性为指定链接
router-view: 用于渲染路由匹配到的组件
-->
<router-link to="/">首页</router-link>
<router-link to="/content">内容</router-link>
<router-link to="/wang">内容</router-link>
<router-view></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>
实战
- 创建一个名为hello-vue的项目。(需要管理员)
vue init webpack hello-vue
- 进入目录,输入
npm install vue-router --save-dev //路由
- 创建element-ui
npm i element-ui -S
- 安装依赖
npm install
- 安装Sass加载器
cnpm install sass-loader node-sass --save-dev
解释:Npm命令解释:
npm install moduleName
:安装模块到项目目录下npm install -g moduleName
:-g 的意思是将模块安装到全局,具体安装到磁盘哪个位置,要看 npm config prefix 的位置npm install -save moduleName
:–save 的意思是将模块安装到项目目录下,并在 package 文件的 dependencies 节点写入依赖,-S 为该命令的缩写npm install -save-dev moduleNam
e:–save-dev 的意思是将模块安装到项目目录下,并在 package 文件的 devDependencies 节点写入依赖,-D 为该命令的缩写
目录介绍
build和config:webPack配置文件
node_modules:用于存放npm install 安装的依赖文件
src:项目源码目录
static:静态资源文件
-
.babelrc:Babel 配置文件,主要作用是将 ES6 转换为 ES5
-
.editorconfig:编辑器配置
-
eslintignore:需要忽略的语法检查配置文件
-
.gitignore:git 忽略的配置文件
-
.postcssrc.js:css 相关配置文件,其中内部的 module.exports 是 NodeJS 模块化语法
-
index.html:首页,仅作为模板页,实际开发时不使用
-
package.json:项目的配置文件
- name:项目名称
- version:项目版本
- description:项目描述
- author:项目作者
- scripts:封装常用命令
- dependencies:生产环境依赖
- devDependencies:开发环境依赖
-
assets:用于存放资源文件
-
components:用于存放 Vue 功能组件
-
views:用于存放 Vue 视图组件
-
router:用于存放 vue-router 配置
测试
创建首页视图,在 views 目录下创建一个名为 Main.vue 的视图组件
<template>
<div>
首页
</div>
</template>
<script>
export default {
name: "Main"
}
</script>
<style scoped>
</style>
创建登录页视图在 views 目录下创建一个名为 Login.vue 的视图组件,其中 el-* 的元素为 ElementUI 组件
<template>
<div>
<el-form ref="loginForm" :model="form" :rules="rules" label-width="80px" class="login-box">
<h3 class="login-title">欢迎登录</h3>
<el-form-item label="账号" prop="username">
<el-input type="text" placeholder="请输入账号" v-model="form.username"/>
</el-form-item>
<el-form-item label="密码" prop="password">
<el-input type="password" placeholder="请输入密码" v-model="form.password"/>
</el-form-item>
<el-form-item>
<el-button type="primary" v-on:click="onSubmit('loginForm')">登录</el-button>
</el-form-item>
</el-form>
<el-dialog
title="温馨提示"
:visible.sync="dialogVisible"
width="30%"
:before-close="handleClose">
<span>请输入账号和密码</span>
<span slot="footer" class="dialog-footer">
<el-button type="primary" @click="dialogVisible = false">确 定</el-button>
</span>
</el-dialog>
</div>
</template>
<script>
export default {
name: "Login",
data() {
return {
form: {
username: '',
password: ''
},
// 表单验证,需要在 el-form-item 元素中增加 prop 属性
rules: {
username: [
{required: true, message: '账号不可为空', trigger: 'blur'}
],
password: [
{required: true, message: '密码不可为空', trigger: 'blur'}
]
},
// 对话框显示和隐藏
dialogVisible: false
}
},
methods: {
onSubmit(formName) {
// 为表单绑定验证功能
this.$refs[formName].validate((valid) => {
if (valid) {
// 使用 vue-router 路由到指定页面,该方式称之为编程式导航
this.$router.push("/main");
} else {
this.dialogVisible = true;
return false;
}
});
}
}
}
</script>
<style lang="scss" scoped>
.login-box {
border: 1px solid #DCDFE6;
width: 350px;
margin: 180px auto;
padding: 35px 35px 15px 35px;
border-radius: 5px;
-webkit-border-radius: 5px;
-moz-border-radius: 5px;
box-shadow: 0 0 25px #909399;
}
.login-title {
text-align: center;
margin: 0 auto 40px auto;
color: #303133;
}
</style>
创建路由,在 router 目录下创建一个名为 index.js 的 vue-router 路由配置文件
import Vue from 'vue'
import Router from 'vue-router'
import Login from "../views/Login"
import Main from '../views/Main'
Vue.use(Router);
export default new Router({
routes: [
{
// 登录页
path: '/login',
name: 'Login',
component: Login
},
{
// 首页
path: '/main',
name: 'Main',
component: Main
}
]
});
配置路由,修改入口代码,修改 main.js 入口代码
import Vue from 'vue'
import VueRouter from 'vue-router'
import router from './router'
// 导入 ElementUI
import ElementUI from 'element-ui'
import 'element-ui/lib/theme-chalk/index.css'
import App from './App'
// 安装路由
Vue.use(VueRouter);
// 安装 ElementUI
Vue.use(ElementUI);
new Vue({
el: '#app',
// 启用路由
router,
// 启用 ElementUI
render: h => h(App)
});