狂神js(狂神–Vue)
概述
前端三要素HTML(结构) :超文本标记语言(Hyper Text Markup Language) ,决定网页的结构和内容
CSS(表现) :层叠样式表(Cascading Style sheets) ,设定网页的表现样式
JavaScript (行为) :是一种弱类型脚本语言 ,其源代码不需经过编译 ,而是由浏览器解释运行 ,用于控制网页的行为
JavaScript框架jQuery:大家熟知的JavaScript框架 ,优点是简化了DOM操作 ,缺点是DOM操作太频繁 ,影响前端性能;在前端眼里使用它仅仅是为了兼容IE6 、7 、8;
Angular:Google收购的前端框架 ,由一群Java程序员开发 ,其特点是将后台的MVC模式搬到了前端并增加了模块化开发的理念 ,与微软合作 ,采用TypeScript语法开发;对后台程序员友好,对前端程序员不太友好;最大的缺点是版本迭代不合理(如: 1代-> 2代 ,除了名字 ,基本就是两个东西;截止发表博客时已推出了Angular6)
React:Facebook出品,一款高性能的JS前端框架;特点是提出了新概念 【虚拟DOM】 用于减少真实DOM操作 ,在内存中模拟DOM操作 ,有效的提升了前端渲染效率;缺点是使用复杂 ,因为需要额外学习一门 【JSX】 语言;
Vue:一款渐进式JavaScript框架 ,所谓渐进式就是逐步实现新特性的意思 ,如实现模块化开发 、路由 、状态管理等新特性 。其特点是综合了Angular(模块化)和React(虚拟DOM)的优点;
Axios:前端通信框架;因为Vue 的边界很明确 ,就是为了处理DOM ,所以并不具备通信能力 ,此时就需要额外使用一个通信框架与服务器交互;当然也可以直接选择使用jQuery提供的AJAX通信功能;
前端三大框架:Angular 、React 、Vue
UI框架Ant-Design:阿里巴巴出品 ,基于React的UI框架
ElementUl ,iview , ice:饿了么出品 ,基于Vue的UI框架
Bootstrap:Twitter推出的一个用于前端开发的开源工具包
AmazeUl:又叫"妹子U1" ,一款HTML5跨屏前端框架Vue.js
iView
iview是一个强大的基于Vue的UI库,有很多实用的基础组件比elementui的组件更丰富 ,主要服务于PC界面的中后台产品 。使用单文件的Vue组件化开发模式基于npm + webpack +babel开发 ,支持ES2015高质量 、功能丰富友好的API ,自由灵活地使用空间 。ElementUI
Element是饿了么前端开源维护的Vue UI组件库 ,组件齐全 ,基本涵盖后台所需的所有组件 ,文档讲解详细 ,例子也很丰富 。主要用于开发PC端的页面 ,是一个质量比较高的Vue UI组件库 。 了解前后分离的演变史 MVC时代为了降低开发的复杂度 , 以后端为出发点 , 比如:Struts 、Spring MVC等框架的使用 , 就是后端的MVC时代;
以SpringMVC流程为例 。发起请求到前端控制器(Dispatcher Servlet)
前端控制器请求HandlerMapping查找Handler ,可以根据xml配置 、注解进行查找
处理器映射器HandlerMapping向前端控制器返回Handler
前端控制器调用处理器适配器去执行Handler
处理器适配器去执行Handler
Handler执行完成给适配器返回ModelAndView
处理器适配器向前端控制器返回ModelAndView ,ModelAndView是SpringMvc框架的一个底层对象 ,包括Model和View
前端控制器请求视图解析器去进行视图解析 ,根据逻辑视图名解析成真正的视图(JSP)
视图解析器向前端控制器返回View
前端控制器进行视图渲染,视图渲染将模型数据(在ModelAndView对象中)填充到request域
前端控制器向用户响应结果 基于AJAX带来的SPA时代时间回到2005年A OAX(Asynchronous JavaScript And XML , 异步JavaScript和XML ,老技术新用法)被正式提出并开始使用CDN作为静态资源存储, 于是出现了JavaScript王者归来(在这之前JS都是用来在网页上贴狗皮膏药广告的) 的SPA(Single Page Application) 单页面应用时代 。
前端为主的MV*时代MVC(同步通信为主) :Model 、View 、Controller
MVP(异步通信为主) :Model 、View、Presenter
MVVM(异步通信为主):Model 、View 、View Model为了降低前端开发复杂度 ,涌现了大量的前端框架 ,比如:Angular JS、React 、Vue.js 、Ember JS等 , 这些框架总的原则是先按类型分层 , 比如Templates 、Controllers 、Models , 然后再在层内做切分 ,如下图:第一个Vue程序
什么是MVVM
MVVM源自于经典的MVC(Model-View-Controller)模式 。MVVM的核心是ViewModel层 ,负责转换Model中的数据对象来让数据变得更容易管理和使用 。
该层向上与视图层进行双向数据绑定 向下与Model层通过接口请求进行数据交互为什么要使用MVVM
低耦合:视图(View)可以独立于Model变化和修改 ,一个ViewModel可以绑定到不同的View上 ,当View变化的时候Model可以不变 ,当Model变化的时候View也可以不变 。
可复用:你可以把一些视图逻辑放在一个ViewModel里面 ,让很多View重用这段视图逻辑 。
独立开发:开发人员可以专注于业务逻辑和数据的开发(ViewMode) ,设计人员可以专注于页面设计 。
可测试:界面素来是比较难以测试的,而现在测试可以针对ViewModel来写。 ViewView是视图层 , 也就是用户界面 。前端主要由HTH L和csS来构建 , 为了更方便地展现vi eu to del或者Hodel层的数据, 已经产生了各种各样的前后端模板语言 , 比如FreeMarker ,Thyme leaf等等 , 各大MV VM框架如Vue.js.Angular JS , EJS等也都有自己用来构建用户界面的内置模板语言 。
ModelModel是指数据模型 , 泛指后端进行的各种业务逻辑处理和数据操控 , 主要围绕数据库系统展开。这里的难点主要在于需要和前端约定统一的接口规则
ViewModelViewModel是由前端开发人员组织生成和维护的视图数据层 。在这一层 , 前端开发者对从后端获取的Model数据进行转换处理 , 做二次封装 , 以生成符合View层使用预期的视图数据模型 。
需要注意的是View Model所封装出来的数据模型包括视图的状态和行为两部分 , 而Model层的数据模型是只包含状态的比如页面的这一块展示什么 ,那一块展示什么这些都属于视图状态(展示)
页面加载进来时发生什么 ,点击这一块发生什么,这一块滚动时发生什么这些都属于视图行为(交互)
视图状态和行为都封装在了View Model里 。这样的封装使得View Model可以完整地去描述View层 。由于实现了双向绑定 , View Model的内容会实时展现在View层 , 这是激动人心的, 因为前端开发者再也不必低效又麻烦地通过操纵DOM去更新视图 。
MVVM框架已经把最脏最累的一块做好了 , 我们开发者只需要处理和维护View Model , 更新数据视图就会自动得到相应更新 ,真正实现事件驱动编程 。
View层展现的不是Model层的数据 , 而是ViewModel的数据 , 由ViewModel负责与Model层交互 , 这就完全解耦了View层和Model层 , 这个解耦是至关重要的 , 它是前后端分离方案实施的重要一环 。 VueVue(读音/vju/ , 类似于view) 是一套用于构建用户界面的渐进式框架 , 发布于2014年2月 。与其它大型框架不同的是 , Vue被设计为可以自底向上逐层应用 。Vue的核心库只关注视图层 , 不仅易于上手, 还便于与第三方库(如:vue-router ,vue-resource ,vue x) 或既有项目整合 。
MVVM模式的实现者Model:模型层, 在这里表示JavaScript对象
View:视图层 , 在这里表示DOM(HTML操作的元素)
ViewModel:连接视图和数据的中间件 , Vue.js就是MVVM中的View Model层的实现者
在MVVM架构中 , 是不允许数据和视图直接通信的 , 只能通过ViewModel来通信 , 而View Model就是定义了一个Observer观察者ViewModel能够观察到数据的变化 , 并对视图对应的内容进行更新
ViewModel能够监听到视图的变化 , 并能够通知数据发生改变
至此 , 我们就明白了 , Vue.js就是一个MV VM的实现者 , 他的核心就是实现了DOM监听与数据绑定 为什么要使用Vue.js轻量级 , 体积小是一个重要指标 。Vue.js压缩后有只有20多kb(Angular压缩后56kb+ ,React压缩后44kb+)
移动优先 。更适合移动端, 比如移动端的Touch事件
易上手 ,学习曲线平稳 ,文档齐全
吸取了Angular(模块化) 和React(虚拟DOM) 的长处, 并拥有自己独特的功能 ,如:计算属性
开源 ,社区活跃度高第一个Vue程序
<!DOCTYPE HTML> <HTML lang="en"> <head> <meta charset="UTF-8"> <title>Hello World</title> </head> <body> <div id="app">{{message}}</div> </body> <script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script> <script type="text/javascript"> var app = new Vue({el:#app,data:{message:"Hello World"}}); </script> </HTML>基础语法指令
v-bind
<!DOCTYPE HTML> <HTML lang="en"> <head> <meta charset="UTF-8"> <title>v-bind</title> </head> <body> <div id="app"> <span v-bind:title="message"> 过来过来过来!!!!!!!! </span> </div> </body> <script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script> <script type="text/javascript"> var app = new Vue({el:#app,data:{message:Hello World+ new Date().toLocaleString()}}); </script> </HTML>v-if,v-else
<!DOCTYPE HTML> <HTML lang="en"> <head> <meta charset="UTF-8"> <title>v-if##v-else</title> </head> <body> <div id="app"> <h1 v-if="ok">Yes</h1> <h2 v-else>No</h2> </div> </body> <script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script> <script type="text/javascript"> var app = new Vue({el:#app,data:{ok:true}}); </script> </HTML>v-for
<!DOCTYPE HTML> <HTML lang="en"> <head> <meta charset="UTF-8"> <title>v-for</title> </head> <body> <div id="app"> <li v-for="(item,index) in items"> {{item.message}}----{{index}} </li> </div> </body> <script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script> <script type="text/javascript"> var app = new Vue({el:#app,data:{items:[{message:白日依山尽},{message:黄河入海流},{message:欲穷千里目},{message:更上一层楼}]}}); </script> </HTML>v-on
<!DOCTYPE HTML> <HTML lang="en"> <head> <meta charset="UTF-8"> <title>v-on</title> </head> <body> <div id="app"> <button v-on:click="hello">按钮</button> </div> </body> <script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script> <script type="text/javascript"> var app = new Vue({el:#app,data:{message:hello world},methods:{hello:function(event){alert(this.message)}}}); </script> </HTML>v-model
<!DOCTYPE HTML> <HTML lang="en"> <head> <meta charset="UTF-8"> <title>v-model</title> </head> <body> <div id="app"> 请输入的文本: <input type="text" v-model="message" value="hello"/>{{message}} </div> <div id="app1"> 多行文本: <textarea v-model="message"></textarea> {{message}} </div> <div id="app2"> 单复选框: <input type="checkbox" id="checkbox" v-model="checked"/> <label for="checkbox">{{checked}}</label> </div> <div id="app3"> 多复选框: <input type="checkbox" id="jack" value="Jack" v-model="checkedNames"> <label for="jack">Jack</label> <input type="checkbox" id="join" value="Join" v-model="checkedNames"> <label for="join">Join</label> <input type="checkbox" id="mike" value="Mike" v-model="checkedNames"> <label for="mike">Mike</label> <span>选中的值:{{checkedNames}}</span> </div> <div id="app4"> 单选框按钮 <input type="radio" id="one" value="One" v-model="picked"> <label for="one">One</label> <input type="radio" id="two" value="Two" v-model="picked"> <label for="two">Two</label> <span>选中的值:{{picked}}</span> </div> <div id="app5"> 下拉框: <select v-model="pan"> <option value="" disabled>---请选择---</option> <option>A</option> <option>B</option> <option>C</option> <option>D</option> </select> <span>value:{{pan}}</span> </div> </body> <script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script> <script type="text/javascript"> var app = new Vue({el:#app,data:{message:""}}); new Vue({el:#app1,data:{message:"白日依山尽 ,黄河入海流。欲穷千里目 ,更上一层楼 。"}}); new Vue({el:#app2,data:{checked:true}}) new Vue({el:#app3,data:{checkedNames:[]}}) new Vue({el:#app4,data:{picked:Two}}) new Vue({el:#app5,data:{pan:}}) </script> </HTML>component
<!DOCTYPE HTML> <HTML lang="en"> <head> <meta charset="UTF-8"> <title>component</title> </head> <body> <!-- <div id="app"> <pan></pan> </div> --> <div id="app1"> <pan v-for="item in items" v-bind:panh="item"></pan> </div> </body> <script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script> <script type="text/javascript"> Vue.component("pan",{props:["panh"],template:<li>{{panh}}</li>}); // new Vue({el:"#app"}); new Vue({el:"#app1",data:{items:["java","c++","c#","go"]}}) </script> </HTML>axios
<!DOCTYPE HTML> <HTML lang="en"> <head> <meta charset="UTF-8"> <title>axios</title> </head> <body> <style> /* 解决闪烁问题 */ /* [v-cloak]{ display: none; } */ </style> <div id="app"> <div>姓名: {{info.name}}</div> <div>地址:{{info.address.country}}--{{info.address.city}}--{{info.address.street}}</div> <div>连接:<a v-bind:href="https://www.cnblogs.com/When6/archive/2023/02/24/info.url" target="_bank">{{info.url}}</a></div> </div> </body> <script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script> <script src="https://unpkg.com/axios/dist/axios.min.js"></script> <script type="text/javascript"> new Vue({el:"#app",data(){return{info:{name:null,address:{country:null,city:null,street:null},url:null}}},mounted(){axios.get(http://172.30.3.216:3000/mock/465/get).then(response=>(this.info=response.data))}}); </script> </HTML> { "name": "狂神说Java", "url": "https://blog.kuangstudy.com", "page": 1, "isNonProfit": true, "address": { "street": "含光门", "city": "陕西西安", "country": "中国" }, "links": [ { "name": "bilibili", "url": "https://space.bilibili.com/95256449" }, { "name": "狂神说Java", "url": "https://blog.kuangstudy.com" }, { "name": "百度", "url": "https://www.baidu.com/" } ] }computed
<!DOCTYPE HTML> <HTML lang="en"> <head> <meta charset="UTF-8"> <title>computed</title> </head> <body> <div id="app"> <div>time:{{time()}}</div> <div>time1:{{time1}}</div> </div> </body> <script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script> <script src="https://unpkg.com/axios/dist/axios.min.js"></script> <script type="text/javascript"> var vm = new Vue({el:"#app",data:{message:11},mounted(){},methods:{time:function(){return Date.now()}},computed:{time1:function(){ this.message; return Date.now();}}}); </script> </HTML>slot
<!DOCTYPE HTML> <HTML lang="en"> <head> <meta charset="UTF-8"> <title>slot</title> </head> <body> <div id="app"> <todo> <todo-title slot="todo-title" :title="title"></todo-title> <todo-input slot="todo-input" v-on:add="add_method"></todo-input> <todo-items slot="todo-items" v-for="(item,index) in todoitems" :item="item" :index="index" v-on:remove="remove_method(index)" :key="index"></todo-items> </todo> </div> </body> <script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script> <script type="text/javascript"> Vue.component("todo",{template:<div>\ <slot name="todo-title"></slot>\ <slot name="todo-input"></slot>\ <ul>\ <slot name="todo-items"></slot>\ </ul>\ </div>}); Vue.component(todo-title,{props:["title"],template:<div>{{title}}</div>}); //仿写插入 Vue.component(todo-input,{ template:<div><form>\ 请输入: <input type="text" v-model="arr" value="请输入"><br>\ <button type="button"@click="add_component">提交</button>\ </div>, props:["arr"], methods:{ add_component:function(){this.$emit(add,this.arr);}} }) Vue.component(todo-items,{ props:["item","index"], template:"<li>{{index+1}},{{item}} <button @click=remove_component>删除</button></li>", methods:{remove_component:function(index){this.$emit(remove,index);}} }) var vue = new Vue({ el:"#app", data:{title:"登鹳雀楼",todoitems:[白日依山尽,,黄河入海流.,欲穷千里目,,更上一层楼.],arr:}, methods:{ remove_method:function(index){ console.log("删除了"+this.todoitems[index]+"OK"); this.todoitems.splice(index,1); }, add_method:function(arr){ console.log("添加元素"+arr); this.todoitems.splice(this.todoitems.size,0,arr); } } }) </script> </HTML>Webpack
npm install webpack
vue-router
npm install vue-router --save-dev
项目
创建项目
vue init webpack hello-vue #进入工程目录 cd hello-vue #安装vue-routern 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 run devsass-loader node-sass 老是安装失败 ,后来发现和node版本有关系, 解决办法:
PS C:\代码\vue> node -v v14.17.1 安装版本为: "node-sass": "^4.14.1", "sass-loader": "^7.3.1",目录结构
assets:用于存放资源文件 components:用于存放Vue功能组件 views:用于存放Vue视图组件 router:用于存放vue-router配置代码
views/user/User.vue <template> <div> <h1>个人信息</h1> {{$route.params.id}} </div> </template> <script> export default { name: "User", beforeRouteEnter: (to, from, next) => { console.log("准备进入个人信息页"); next(vm => { //进入路由之前执行getData方法 vm.getData() }); }, beforeRouteLeave: (to, from, next) => { console.log("准备离开个人信息页"); next(); }, methods:{ getData: function(){ this.axios({ method: get, url: http://localhost:8080/static/user.json }).then(function (response) { console.log(response) }) } } } </script> <style scoped> </style> views/user/UserList.vue <template> <div> <h1>用户列表</h1> {{id}} </div> </template> <script> export default { name: "UserList", props: [id] } </script> <style scoped> </style> views/Login.vue <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:"密码不可为空",tigger:"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> views/Main.vue <template> <div> <el-container> <el-aside width="200px"> <el-menu :default-openeds="[1]"> <el-submenu index="1"> <template slot="title"><i class="el-icon-caret-right"></i>用户管理</template> <el-menu-item-group> <el-menu-item index="1-1"> <!--插入的地方--> <!-- <router-link to="/user/user">个人信息</router-link> --> <router-link :to="{name:User,params:{id:1}}">个人信息</router-link> </el-menu-item> <el-menu-item index="1-2"> <!--插入的地方--> <!-- <router-link to="/user/userlist">用户列表</router-link> --> <router-link :to="{name:UserList,params:{id:222}}">用户列表</router-link> </el-menu-item> <el-menu-item index="1-3"> <router-link to="/goHome">回到首页</router-link> </el-menu-item> </el-menu-item-group> </el-submenu> <el-submenu index="2"> <template slot="title"><i class="el-icon-caret-right"></i>内容管理</template> <el-menu-item-group> <el-menu-item index="2-1">分类管理</el-menu-item> <el-menu-item index="2-2">内容列表</el-menu-item> </el-menu-item-group> </el-submenu> </el-menu> </el-aside> <el-container> <el-header> <el-dropdown> <i class="el-icon-setting"></i> <el-dropdown-menu slot="dropdown"> <el-dropdown-item>个人信息</el-dropdown-item> <el-dropdown-item>退出登录</el-dropdown-item> </el-dropdown-menu> </el-dropdown> </el-header> <el-main> <!--在这里展示视图--> <router-view /> </el-main> </el-container> </el-container> </div> </template> <script> export default { name: "Main" } </script> <style scoped lang="scss"> .el-header { background-color: #B3C0D1; color: #333; line-height: 60px; } .el-aside { color: #333; } </style> views/NotFound.vue <template> <div> <h1>404,你的页面走丢了</h1> </div> </template> <script> export default { name: "NotFound" } </script> <style scoped> </style> router/index.js import Vue fromvue //导入路由插件 import Router from vue-router //导入上面定义的组件 import Main from "../views/Main"; import Login from "../views/Login"; import User from "../views/user/User"; import UserList from "../views/user/UserList"; import NotFound from ../views/NotFound //安装路由 Vue.use(Router) ; //配置路由 export default new Router({ //路径不带 # 符号 mode: history, routes:[ { //路由路径 path:/main, //路由名称 name:main, children: [ { // path: /user/user/, path: /user/user/:id, name: User, component: User, }, { path: /user/userlist/:id, name: UserList, component: UserList, props: true }, ], //跳转到组件 component:Main },{ //路由路径 path:/, //路由名称 name:login, //跳转到组件 component:Login },{ path: /goHome, redirect: /main },{ path: *, component: NotFound } ] }); main.js // The Vue build version to load with the `import` command // (runtime-only or standalone) has been set in webpack.base.conf with an alias. import Vue from vue import App from ./App //导入上面创建的路由配置目录 import router from ./router//自动扫描里面的路由配置 import ElementUI from element-ui import element-ui/lib/theme-chalk/index.css import axios from axios import VueAxios from vue-axios // Vue.config.productionTip = false Vue.use(router); Vue.use(ElementUI); Vue.use(VueAxios, axios); /* eslint-disable no-new */ new Vue({ el: #app, router, render:h=>h(App) })创心域SEO版权声明:以上内容作者已申请原创保护,未经允许不得转载,侵权必究!授权事宜、对本内容有异议或投诉,敬请联系网站管理员,我们将尽快回复您,谢谢合作!