Vue和Vue-Element-Admin(一):Vue基础和框架

当前的项目涉及数据仓库/分析后的前端展示,基于vue-element-admin的前端成熟框架进行前后端分离开发,它是一个vue+element ui的开源技术方案:vue-element-admin 码云地址,教程:vue-element-admin教程,界面简洁清爽;

Vue-element-admin涉及到的技术栈包括 vue、vuex、vue-router 、vue-cli 、axios、 element-ui,所以可以按照两个部分将vue框架本身( vue、vuex、vue-router 、vue-cli 、axios),以及vue-element-admin使用;

vue基础和框架

MVC和MVVC理解

按照之前流行的MVC框架,view视图层完成数据可视化的定义,假设前后端实现student类的展示,需要的步骤:① Student的bean类,即是model,实现Student的多个属性和方法的定义;② StudentController控制器,定义前端的的数据请求体(spring 使用RuquestMapping注解实现);③ 创建视图viewer,按照mybatis框架的方式,先定义查询接口StudentMapper(定义查询sql命名和返回类型),以及同名的静态StudentMapper.xml文件(封装sql条件查询语句);

MVC的优点是耦合性低、重用性高、可维护性高。优点也是缺点,增加了系统结构和实现的复杂性。对于简单的界面,严格遵循MVC,使模型、视图与控制器分离,会增加结构的复杂性,并可能产生过多的更新操作,降低运行效率。

前后端分离采用的是MVVM框架(Model—View—ViewModel)双向的数据绑定,其核心是 ViewModel 层,视图模型层是View和Model沟通的桥梁。一方面它实现了Data Binding,也就是数据绑定,将Model的改变实时的反应到View中,另一方面它实现了DOM Listener,也就是DOM监听,当DOM发生一些事件(点击、滚动、touch等)时,可以监听到,并在需要的情况下改变对应的Data。

 

vue的引入和demo

vue菜鸟教程,vue是个js框架,允许开发者声明式地将 DOM 绑定至底层 Vue 实例的数据,在底层的实现上Vue 将模板编译成虚拟 DOM 渲染函数,结合响应系统,Vue 能够智能地计算出最少需要重新渲染多少组件,并把 DOM 操作次数减到最少安装Vue的方式有很多:

1、你可以选择引入开发环境版本还是生产环境版本

<!-- 开发环境版本,包含了有帮助的命令行警告 --> 
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<!-- 生产环境版本,优化了尺寸和速度 -->
<script src="https://cdn.jsdelivr.net/npm/vue"></script>

2、下载和引入

开发环境 https://vuejs.org/js/vue.js 
生产环境 https://vuejs.org/js/vue.min.js

 3、NPM安装:后续通过webpack和CLI的使用

最简单的demo如下:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Vue 测试实例 - 菜鸟教程(runoob.com)</ti	tle>
<script src="https://unpkg.com/vue/dist/vue.js"></script>
</head>
<body>
<div id="app-5">
  <p>{{ message }}</p>
  <button v-on:click="reverseMessage">反转消息</button>
</div>

<script>
var app5 = new Vue({
  el: '#app-5',
  data: {
    message: 'Hello Vue.js!'
  },
  methods: {
    reverseMessage: function () {
      this.message = this.message.split('').reverse().join('')
    }
  }
})
</script>
</body>
</html>

vue包含一些特殊的标签,使用v-作为前缀,比如:

v-if:根据表达式的值的真假条件渲染元素,在切换时元素及它的数据绑定/组件被销毁并重建。v-if 控制元素的渲染 v-if 为假 该元素不会创建;

v-show:根据表达式之真假值,切换元素的display CSS 属性。 可以控制元素的显示隐藏通过display none

v-for:循环指令,基于一个数组或对象渲染一个列表,Vue 2.0 以上必须需配合key值使用。绑定一个 标签 循环一个数据源 数组 表格 数字 字符串

v-bind:动态地绑定一个或多个特性,或一个组件prop到表达式。 属性后面跟的是固定字符串 作用:属性绑定可以让属性后面 跟变量或者表达式

v-on:用于监听指定元素的DOM事件,比如点击事件。绑定事件监听器。 事件名=‘事件处理函数’ 事件名和原生JS一样

v-model:实现表单输入和应用状态之间的双向绑定。 相当于事件绑定v-on和属性绑定v-bind的综合(集合体)

v-pre:跳过这个元素和它的子元素的编译过程。可以用来显示原始Mustache标签。跳过大量没有指令的节点会加快编译

v-once:只渲染元素和组件一次,随后的重新渲染,元素/组件及其所有的子节点将被视为静态内容并跳过。这可以用于优化更新性能

vue很重要的一个特性是:组件化构建应用,可以使用小型、独立和通常可复用的组件构建大型应用,如li标签的模板+v-for循环+vue的component完成数据的遍历;

<div id="app-7">
  <ol>
    <!--
      现在我们为每个 todo-item 提供 todo 对象
      todo 对象是变量,即其内容可以是动态的。
      我们也需要为每个组件提供一个“key”,稍后再
      作详细解释。
    -->
    <todo-item
      v-for="item in groceryList"
      v-bind:todo="item"
      v-bind:key="item.id"
    ></todo-item>
  </ol>
</div>

Vue.component('todo-item', {
  props: ['todo'],
  template: '<li>{{ todo.text }}</li>'
})

var app7 = new Vue({
  el: '#app-7',
  data: {
    groceryList: [
      { id: 0, text: '蔬菜' },
      { id: 1, text: '奶酪' },
      { id: 2, text: '随便其它什么人吃的东西' }
    ]
  }
})

vue的options(选项)

一个vue实例里面可以定义data、methods、props、computed、watch这些关于数据的选项;

data:Vue 实例的数据对象

props:props 可以是数组或对象,用于接收来自父组件的数据;

computed:计算属性, 数据量大需要缓存的时候用;

methods:计算方法,不需要缓存时用(比如时间),以函数形式调用;

watch:一个对象,键是需要观察的表达式,值是对应回调函数;

同时,vue也能够定义一些生命周期的钩子选项,例如需要设置数据监听、编译模板、将实例挂载到 DOM 并在数据变化时更新 DOM 等。

标题

测试钩子函数的实例:

<!DOCTYPE html>
<html>
<head>
    <title>钩子函数</title>
    <meta charset="utf-8">
    <script src="http://cdn.bootcss.com/vue/2.1.10/vue.js"></script>
<body>

<div id="app">
    <p>{{ message }}</p>
    <input type="button" @click="change" value="更新数据" />
    <input type="button" @click="destroy" value="销毁" />
</div>

<script type="text/javascript">
    var vm = new Vue({
        el: '#app',
        data: {
            message : "Welcome Vue"
        },
        methods:{
            change() {
                this.message = 'Datura is me';
            },
            destroy() {
                vm.$destroy();
            }
        },
        beforeCreate: function () {
            console.group('beforeCreate 创建前状态===============》');
            console.log("%c%s", "color:red","el     : " + this.$el); //undefined
            console.log("%c%s", "color:red","data   : " + this.$data); //undefined
            console.log("%c%s", "color:red","message: " + this.message);//undefined
        },
        created: function () {
            console.group('created 创建完毕状态===============》');
            console.log("%c%s", "color:red","el     : " + this.$el); //undefined
            console.log("%c%s", "color:green","data   : " + this.$data); //[object Object]  =>  已被初始化
            console.log("%c%s", "color:green","message: " + this.message); //Welcome Vue  =>  已被初始化
        },
        beforeMount: function () {
            console.group('beforeMount 挂载前状态===============》');
            console.log("%c%s", "color:green","el     : " + (this.$el)); //已被初始化
            console.log(this.$el); // 当前挂在的元素
            console.log("%c%s", "color:green","data   : " + this.$data); //已被初始化
            console.log("%c%s", "color:green","message: " + this.message); //已被初始化
        },
        mounted: function () {
            console.group('mounted 挂载结束状态===============》');
            console.log("%c%s", "color:green","el     : " + this.$el); //已被初始化
            console.log(this.$el);
            console.log("%c%s", "color:green","data   : " + this.$data); //已被初始化
            console.log("%c%s", "color:green","message: " + this.message); //已被初始化
        },
        beforeUpdate: function () {
            alert("更新前状态");
            console.group('beforeUpdate 更新前状态===============》'); //这里指的是页面渲染新数据之前
            console.log("%c%s", "color:green","el     : " + this.$el);
            console.log(this.$el);
            console.log("%c%s", "color:green","data   : " + this.$data);
            console.log("%c%s", "color:green","message: " + this.message);
            alert("更新前状态2");
        },
        updated: function () {
            console.group('updated 更新完成状态===============》');
            console.log("%c%s", "color:green","el     : " + this.$el);
            console.log(this.$el);
            console.log("%c%s", "color:green","data   : " + this.$data);
            console.log("%c%s", "color:green","message: " + this.message);
        },
        beforeDestroy: function () {
            console.group('beforeDestroy 销毁前状态===============》');
            console.log("%c%s", "color:red","el     : " + this.$el);
            console.log(this.$el);
            console.log("%c%s", "color:red","data   : " + this.$data);
            console.log("%c%s", "color:red","message: " + this.message);
        },
        destroyed: function () {
            console.group('destroyed 销毁完成状态===============》');
            console.log("%c%s", "color:red","el     : " + this.$el);
            console.log(this.$el);
            console.log("%c%s", "color:red","data   : " + this.$data);
            console.log("%c%s", "color:red","message: " + this.message)
        }
    })
</script>
</body>
</html>

vue的组件化

组件化是Vue.js中的重要思想,它提供了一种抽象可以开发出一个个独立可复用的小组件来构造应用,任何的应用都会被抽象成一颗组件树,一般使用template模板方式定义组件:

在组件中,使用选项props来声明需要从父级接收到的数据,有时候需要父组件和子组件之间互相访问数据,比如在父页面和子页面之间的跳转时候,父组件访问子组件使用$children或$refs,子组件访问父组件使用$parent;

 

父子数据传递

vue的slot插槽

     许多前端组件它们也很多区别,但是也有很多共性,如何去封装这类的组件?(抽取共性,保留不同),预留了插槽就可以让使用者根据自己的需求决定插槽中插入什么内容,是搜索框,还是文字,还是菜单,由调用者自己来决定。

当子组件的功能复杂时,子组件的插槽可能并非是一个,比如封装导航栏的子组件,需要左边、中间、右边三个插槽,需要给插槽起一个名字,给slot元素一个name属性:<slot name='myslot'></slot>

vue的模块化

在网页开发的早期,js制作作为一种脚本语言,做一些简单的表单验证或动画实现等,那个时候代码很少,直接将代码写在<script>标签即可,随着ajax异步请求的出现慢慢形成了前后端的分离,客户端需要完成的事情越来越多,代码量也是与日俱增,为了应对代码量的剧增,将代码在多个js文件中进行维护,但是这种维护方式依然不能避免一些灾难性的问题,比如全局变量同名问题,另外这种代码的编写方式对js文件的依赖顺序几乎是强制性的,但是当js文件过多,比如有几十个的时候,需要弄清楚它们的顺序;

常见的模块化规范:CommonJS、AMD、CMD,也有ES6的Modules,模块化的2个核心是导出和导入:

某些情况下,一个模块中包含某个的功能,我们并不希望给这个功能命名,而且让导入者可以自己来命名,这个时候就可以使用export default(同一个模块中,不允许同时存在多个),在到main.js中,myFunc可以自己命名;

要想进行模块化开发,还需要处理模块间的各种依赖,并且将其进行整合打包,就必须借助于其他的工具,webpack可以进行模块化开发并处理模块间的依赖关系,不仅仅是JavaScript文件,CSS、图片、json文件等等在webpack中都可以被当做模块来使用,这就是webpack中模块化的概念,vue中使用webpack的模块化思想和配置;

vue脚手架vue-cli

在开发大型项目必然使用Vue CLI,因为需要考虑代码目录结构、项目结构和部署、热加载、代码单元测试等事情。手动完成这些工作效率比较低,所以通常使用一些脚手架工具来帮助完成这些事情。

NPM的全称是Node Package Manager,是一个NodeJS包管理和分发工具,已经成为了非官方的发布Node模块(包)的标准,一般使用NPM来安装一些开发过程中依赖包;

vue-cli 3 与 2 版本有很大区别,vue-cli 3 是基于 webpack 4 打造,vue-cli 2 还是 webapck 3;vue-cli 3 的设计原则是“0配置”移除的配置文件根目录下的,build和config等目录,vue-cli 3 提供了 vue ui 命令,提供了可视化配置,更加人性化;移除了static文件夹,新增了public文件夹,并且index.html移动到public中;

脚手架 2
脚手架 3

 

npm run bulid
npm rum dev

vue的状态管理vuex

Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式,它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化;状态管理可以简单理解是需要多个组件共享的变量全部存储在一个对象里面,然后将这个对象放在顶层的Vue实例中让其他组件可以使用;

在大型开发任务中多个状态需要在多个界面间的共享,比如用户的登录状态、用户名称、头像、地理位置、商品的收藏、购物车中的物品等等。这些状态信息可以放在统一的地方,对它进行保存和管理,而且它们还是响应式的;

首先,创建一个文件夹store,并且在其中创建一个index.js文件,在index.js文件中写入如下代码:

其次,让所有的Vue组件都可以使用这个store对象,来到main.js文件,导入store对象,并且放在new Vue中,这样在其他Vue组件中就可以通过this.$store的方式获取到这个store对象:

在其他组件中使用store对象中保存的状态,通过this.$store.state属性的方式来访问状态,通过this.$store.commit('mutation中方法')来修改状态,在这个count例子中通过提交mutation的方式,而非直接改变store.state.count,因为Vuex可以更明确的追踪状态的变化,不需要直接改变store.state.count的值。

Vuex有几个比较核心的概念:State、Getters、Mutation、Action、Module,Vuex使用单一状态树来管理应用层级的全部状态,单一状态树能够使用最直接的方式找到某个状态的片段,而且在之后的维护和调试过程中,也可以非常方便的管理和维护;

mutation是唯一可以更新状态的方式,Action类似于Mutation, 但是是用来代替Mutation进行异步操作的;

Vuex允许将store分割成模块(Module), 而每个模块拥有自己的state、mutations、actions、getters等

vue的路由vou-router

vue-router是Vue.js官方的路由插件,它vue.js是深度集成,适合用于构建单页面应用,路由用于将路径和组件映射起来;

使用vue-router的步骤:
第一步:创建路由组件
第二步:配置路由映射: 组件和路径映射关系
第三步: 使用路由: 通过<router-link>和<router-view>

 <router-link>: 该标签是一个vue-router中已经内置的组件, 它会被渲染成一个<a>标签;

vue的异步请求axios

vue后台交互获取数据使用的是axios库,它是基于promise的http库,可运行在浏览器端和node.js中,很多优秀的特性:拦截请求和响应、取消请求、转换json、客户端防御,首先在主入口文件main.js中引用,之后挂在vue的原型链上;

©️2020 CSDN 皮肤主题: 技术工厂 设计师:CSDN官方博客 返回首页