vue 笔记
vue 简介
- Vue.js 是目前最火的一个前端框架,React 是最流行的一个前端框架(React 除了开发网站,还可以开发手机 App,Vue 语法也是可以用于进行手机 App 开发的,需要借助才 Weex)
- Vue.js 是前端的主流框架之一,和 Angular.js、React.j3 一起,并称为前端三大主流框架;
- Vue.js 是一套构建用户界而的框架,只关注视图层,它不仅易于上手,还便于与第三方库或既有项目整合。(Vue 有配套的第三方类库,可以整合起来做大型项目的开发)
- 在 Vue 中,一个核心的概念,就是让用户不再操作 DOM 元素,Vue(React) 提供了虚拟 DOM,对比虚拟 DOM 与真实 DOM 不同之处,每次对不同部分进行渲染,渲染效率更高。
提高开发效率的发展历程:
- 原生 JS->Jquery 之类的类库->前端模板引擎->Angular.js/ Vue.js(能够帮助我们减少不必要的 DOM 操作;提高渲染效率;双向数据绑定的概念)
框架和库的区别
- 框架:是一套完整的解决方案;对项目的侵入性较大,项目如果需要更换框架,则需要重新架构整个项目
- 如node 中的 express;
- 库(插件):提供某一个小功能,对项目的侵入性较小,如果某个库无法完成某些需求,可以很容易切换到其它库实现需求。
- 从 Jquery 切换到 Zepto
- 从 EJS 切换到 art-template
vue 和 angular 的区别
- vue——简单、易学
- 指令以 v-xxx
- 一片 html 代码配合上 json,在 new 出来 vue 实例
- 个人维护项目
- 适合: 移动端项目,小巧
- vue 的发展势头很猛,github 上 start 数量已经超越 angular
- angular——上手难
- 指令以 ng-xxx
- 所有属性和方法都挂到$scope 身上
- angular 由 google 维护
- 合适: pc 端项目
安装使用
- 独立版本
- 直接下载并用 script 标签引入,Vue 会被注册为一个全局变量。
- 脚手架 vue-cli
- 全局安装:
npm install -g vue-cli
(或npm i -g vue-cli
) - 创建项目:
- 选择项目所在的位置,通过命令行进入该目录(或者直接在该目录,右键,打开命令行)。
- 使用脚手架安装项目:
vue init webpack demo
项目是基于 webpack 的- Project name(工程名):回车
- Project description(工程介绍):回车
- Author:作者名
- Vue build(是否安装编译器):回车
- Install vue-router(是否安装 Vue 路由):y
- Use EsLint to lint your code(是否使用 EsLint 检查 js 代码):n
- Set up unit tests(安装单元测试工典):n
- Set up e2e tests with Nightwatch(是否安装端到端测试一关):n
- Should we run npm install for you after the project has been created?(recommended):
No, I will handle that myself 回车。
- 启动项目
- 进入项目:cd demo 或 vscode 打开
- 安装项目所需要的依赖:
npm install
- 启动项目:
npm run dev
启动成功,浏览器打开
- 配置目录:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rGJaHIAh-1574426063682)(./assets/vue-content.png)]
- 全局安装:
Vue 的基本代码
<html>
<body>
<!-- 将来new的Vue实例,会控制这个元素中的所有内容-->
<!-- Vue实例控制这个元素区域,就是我们的v-->
<div id="app">
<!--使用v-block能解决插值表达式闪烁问题 -->
<p v-lock>{{msg}}</p>
</div>
<script src="./js/vue2.5.17.js"></script>
<script>
// 创建一个Vue的实例
// 当我们导入包之后,在浏览器的内存中,就多了一个Vue构造函数
// 注意:我们new出来的这个vm对象,就是我们MVVM中VM调度者
var vm = new Vue({
el: "#app", //表示,当前我们new出来的这个Vue实例,要控制页面上的哪个区域
data: {
//这里的data就是MVVM中的M,专门用来保存每个页面的数据的
//data属性中,存放的是el中要用到的数据
msg: "Vue" //通过Vue提供的指令,很方便的就能把数据渲染到页面上,不用在手动操作DOM元素了【前端的Vue、Angular之类的框架不提倡手动操作DOM元素了】
}
});
</script>
</body>
</html>
模板语法
- Vue.js 的核心是一个允许采用简洁的模板语法来声明式地将数据渲染进 DOM 的系统:
- Vue.js 使用了基于 HTML 的模版语法,允许开发者声明式地将 DOM 绑定至底层 Vue 实例的数据。
- 在底层的实现上, Vue 将模板编译成虚拟 DOM 渲染函数。结合响应系统,在应用状态改变时,Vue 能够智能地计算出重新渲染组件的最小代价并应用到 DOM 操作上。
Vue 指令
-
v-text 指令:绑定 html 元素的文本内容,会覆盖元素中原本的内容,不会解析
-
v-html 指令:绑定 html 元素的 html 标签,会覆盖元素中原本的内容,会解析
-
v-model 指令:实现数据的双向绑定
-
v-once 指令:仅渲染一次
-
v-show 指令:显示隐藏
-
v-cloak 指令:当模板未编译完成时,结合 display:none 使用,解决插值表达式闪烁问题。只替换自己的占位符,不会把整个元素的内容清空
-
v-bind 指令:v-bind:属性名称=“值” 绑定 html 元素的属性 v-bind 可省
-
v-on 指令:接收方法处理事件 语法 v-on:事件=“函数” 简写 @事件=“函数”
- 阻止冒泡 @事件.stop
- 阻止默认行为/事件 @事件.prevent
- 键盘事件@keydown, @keyup
- 回车 @keyup.13 @keyup.enter
- 上下左右
- @keyup.left/@keydown.left
- @keyup.right/@keydown.right
- @keyup.up/@keydown.up
- @keyup.down/@keydown.down
-
渲染指令
- 条件渲染 v-if v-else-if v-else
- 循环渲染 v-for
- 迭代对象:参数 1 属性值,参数 2 属性名称,参数 3 索引
<!-- 使用指令实例 --> <head> <style> [v-cloak] { display: none; } </style> </head> <body> <div id="app" v-cloak> <p>您的成绩:{{grade}},{{ grade >= 60?'合格':'不合格'}}</p> <p v-text="grade"></p> <p v-text="msg"></p> <p v-html="msg"></p> <input type="text" v-model="name" /> <h2>hello{{name}}</h2> <p v-once>{{name}}</p> <p> 您的成绩等级: <span v-if="grade>=80">优秀</span> <span v-else-if="grade>=70">良好</span> <span v-else-if="grade>=60">合格</span> <span v-else>合格</span> </p> <ul> <li v-for="item in courseList">{{item}}</li> </ul> <ul> <li v-for="(item,index) in courseList">{{item}}-{{index}}</li> </ul> <p v-for="(value,key,index) in student">{{value}}-{{key}}-{{index}}</p> <img v-bind:src="imgUrl" alt="" /> <img :src="imgUrl" alt="" /> <!-- <a href="url" :class="linkClass">baidu</a> --> <!-- <a href="url" :class="[linkClass,'active']">baidu</a> --> <!-- <a href="url" :class="{link:true,'active':isActive}">baidu</a> --> <a href="url" :style="{textDecoration:'none'}">baidu</a> </div> </body>
Vue 自定义指令
-
除了核心功能默认内置指令(v-model 和 v-show),Vue也允许自定义指令。
-
普通 DOM 元素进行底层操作要用到自定义指令
-
建议在给指令的命名采用小驼峰式的命名方式,比如 changeBackgroundColor,在使用的时候,采用烤串式写法 v-change-background-color
-
一个指令定义对象可以提供如下几个钩子函数:
- bind:只调用一次,指令第一次绑定到元素时调用。
- inserted:被绑定元素插入 DOM 中时调用
- update:所在组件的 VNode 更新时调用 ,但是可能发生在其子 VNode 更新之前。
- componentUpdated:指令所在组件的 VNode 及其子 VNode 全部更新后调用。
- unbind:只调用一次,指令与元素解绑时调用。
-
指令钩子函数会被传入以下参数:
- el:指令所绑定的元素,可以用来直接操作 DOM 。
- binding:一个对象,包含以下属性:
- name:指令名,不包括 v- 前缀。
- value:指令的绑定值。
- oldValue:指令绑定的前一个值,仅在 update 和 componentUpdated 钩子中可用。无论值是否改变都可用。
- expression:字符串形式的指令表达式。
- arg:传给指令的参数,可选。
- modifiers:一个包含修饰符的对象。
- vnode:Vue 编译生成的虚拟节点。
- oldVnode:上一个虚拟节点,仅在 update 和 componentUpdated 钩子中可用
new Vue({ el: "#app", data: { bgcolor: "orange" }, methods: {}, filters: {}, // 局部注册自定义指令(对指令绑定的元素进行DOM操作),添加directives directives: { changeBackgroundColor: { bind(el, binding) { console.log("el:", el, ",binding:", binding); el.style.backgroundColor = binding.value; } }, focus: { inserted(el) { // 触发元素的focus事件,让其获得焦点 el.focus(); } } } });
Vue 与后端的交互(axios 及跨域)
- 项目开发前面:前后端是各自开发:前端模拟假数据开发页面;后端开发 api
- 项目后面
- 后端提供数据接口,前端使用 ajax/axios 技术进行解析从而渲染数据到页面上
- 后端提供数据的格式一般是 json,如果不是,前端拿到数据后,转换为 json 格式,然后使用 ajax/axios 进行解析从而渲染页面
Vue 过滤器
- 过滤器用来格式化数据,过滤器能够用在表达式和指令中,使用一个管道字符(|)添加到表达式和指令中。{{msg | filter}}
// 局部注册过滤器:在Vue实例中添加filters选项 new Vue({ el: "#app", data: { price: 17, ammount: 4, time: new Date() }, methods: {}, filters: { // 过滤器函数:参数1-要格式化的数据,参数2-过滤器参数,必须有返回值(格式化之后的数据) currency: function(value, op = "$") { return op + value.toFixed(2); }, date: function(value) { // 常用日期过滤器 日期格式:yyyy-MM-dd HH:mm:ss let y = value.getFullYear(); let m = value.getMonth() + 1; let d = value.getDate(); let h = value.getHours(); let mi = value.getMinutes(); let s = value.getSeconds(); return `${y}-${m < 10 ? "0" + m : m}-${d < 10 ? "0" + d : d} ${ h < 10 ? "0" + h : h }:${mi < 10 ? "0" + mi : mi}:${s < 10 ? "0" + s : s}`; }, // 对数值进行格式化,保留小数位(默认3位)10,000.000 number: function(value, n = 3) { return value.toFixed(n); } // TODO filter过滤器,orderBy } });
Vue 生命周期
Vue 组件
-
组件中的数据共有三种形式:data、props、computed
-
注册组件(注意:html 中不能使用单标记)
- 全局注册
// (1)注册全局组件,所有Vue实例中可以直接引用此组件 /* 参数1:组件名称,命名以大驼峰或-连接(小写单词) 参数2:组件选项,template,data等 例:MyComponent my-component */ Vue.component("my-compoent", { template: "<div>Welcome to Vue!</div>" });
<div id="app"> <my-compoent></my-compoent> </div>
- 局部注册
// (2)注册局部组件,仅当前Vue实例可用 const My = { template: "<h2>{{msg}}</h2>", // data必须是函数 data() { //一个组件的 data 选项必须是一个函数,因此每个实例可以维护一份被返回对象的独立的拷贝 return { msg: "Hello Vue!" }; } }; // 建议将组件封装在一个独立的.js或.vue文件里面 new Vue({ el: "#app", data: {}, // 在Vue实例中添加componments选项来注册局部组件 components: { My // My:My } });
<div id="app"> <My></My> </div>
-
组件封装
-
将其封装至单独的.vue 文件中放在 components 文件夹下
-
单独的组件.vue 文件结构如下:
<template> </template> <style scoped> /* scoped局部作用域,只在当前vue文件中生效 */ </style> <script> export default {//默认导出vue文件,其中为vue实例的选项 //el不要加,自动挂载到template上 //data要写成函数形式 data(){ return{ } } } </script>
-
-
组件生命周期
- main beforeCreate
- main created
- main beforeMount
- App beforeCreate
- App created
- App beforeMount
- App mounted
- main mounted
- App beforeUpdate
- App updated
- App beforeDestroy
- Hello World destroyed
- App destroyed
-
父子组件间的通信 props down, events up
-
父组件通过 props 向下传递数据给子组件
- 父组件在引用子组件时,通过 v-bind:把需要传递给子组件的数据,传递到子组件内部,供子组件使用
- 把父组件传递过来的数据在 props 数组中定义一下
- 组件中的所有 props 中的数据,都是通过父组件传递给子组件的
- props 中的数据都是只读的,无法重新赋值
- 在子组件中使用 props 数组中定义好的数据
-
-
子组件向父组件传值(通过事件形式)
- 父组件使用事件绑定机制 v-on(@)定义事件属性传递给子组件
- 在子组件中定义一个方法,在方法中,利用
$emit
触发 组件传递过来的方法,挂载在当前实例上的事件,还可以传递参数 - 在子组件中调用方法,触发父组件传递过来的方法
//父组件App.vue <template> <div id="app"> <img src="./assets/logo.png"> <!-- 通过自定义属性,将值向下传递给子组件 --> <HelloWorld :number="count" @updCount="update"/> <button @click="update">App中更新</button> </div> </template> <script> import HelloWorld from './components/HelloWorld' export default { name: 'App', components: { HelloWorld }, data(){ return { count: 1 } }, methods:{ update(a,b,c){ console.log(a,b,c); this.count+=a; } } } </script> <style> </style>
//子组件 HelloWorld.vue <template> <div class="hello"> <p>计数器:{{number}}</p> <button @click="updateProps">子组件更新数据</button> </div> </template> <script> export default { name: 'HelloWorld', data () { return { } }, props: ['number'], methods:{ updateProps(){ // props中的数据是只读的 // this.number++;//不要直接更改props数据 // Events Up触发父组件的事件,让父组件去更新 // this.$emit('updCount'); this.$emit('updCount',2,3,4); } } } </script> <style scoped> </style>
- 全局注册
Vue 路由
- 将组件 (components) 映射到路由 (routes),然后告诉 Vue Router 在哪里渲染它们。
- 在 html 中使用
router-link
组件来导航,通过传入to
属性指定链接。 router-link 默认会被渲染成一个<a>
标签) - 使用
router-view
组件来定义路由出口,路由匹配到的组件将渲染在这里。 - 在路由 js 中导入 Vue 和 VueRouter, 调用 Vue.use(VueRouter)
- 定义路由组件,每个路由应该映射一个组件,可从其他文件 import 进来。
- 创建 router 实例,然后向 Vue 实例注入 routes 配置
- 挂载 Vue 实例
- 在 html 中使用
- 通过注入路由器,我们可以在任何组件内通过 this. r o u t e r 访 问 路 由 器 , 也 可 以 通 过 t h i s . router 访问路由器,也可以通过 this. router访问路由器,也可以通过this.route 访问当前路由
路由的基本配置
- 区分:
- 当前路由对象:
this.\$route
- 路由管理器对象:
this.\$router
- 安装 vue-router
npm i vue-router --save
- 在 router 中 index.js 配置路由
- 引入 vue 的路由管理器,自定义组件并引入路由组件
- 安装 vue-router 路由的功能
- 创建一个路由管理器对象并进行路由配置
//引入 vue 的路由管理器 import VueRouter from "vue-router"; // 引入路由组件 import Login from "@/components/Login"; import Registe from "@/components/Registe"; // 安装路由的功能 Vue.use(VueRouter); // 创建一个路由管理器对象 const router = new VueRouter({ // 添加配置参数routes routes: [ // path: 路由标记(路径),component: 路由标记对应的组件 { path: "/log", component: Login }, { path: "/reg", component: Registe }, // 根路由 { path: "/", redirect: "/log" } ] }); export default router;
- 在 App.vue 中设置路由导航和路由出口,路由导航会渲染成 a 标签,配置好路由的路由组件会渲染到路由出口
<!-- 路由导航:会渲染成a标签 --> <router-link to="/log">登录</router-link> <router-link to="/reg">注册</router-link> <!-- 路由出口:路由匹配到的组件会渲染在这里 --> <router-view></router-view>
- 当前路由对象:
带参数路由及路由嵌套
-
带参路由
- 一个"路径参数"使用冒号 : 标记。当匹配到一个路由时,参数值会被设置到 this.$route.params,可以在每个组件内使用。
//router下index.js文件配置路由 import Vue from 'vue' import Router from 'vue-router' import PhonesList from '@/pages/PhonesList' import Detail from '@/pages/Detail' Vue.use(Router) export default new Router({ routes: [ { path: '/', name: 'PhonesList', component: PhonesList }, { path: '/detail/:id', //路由带参数,在路由标记后面添加 /:参数名称 component: Detail } ] }) //PhonesList.vue传递参数 <template> <div> <ul> <li v-for="item in phones" :key="item.age"> <h3><router-link :to="`/detail/${item.id}`">{{item.name}}</router-link></h3> <p>{{item.snippet}}</p> </li> </ul> </div> </template> <script> export default { data(){return {phones: []}}, created(){ // 请求所有的手机列表数据 this.$axios.get('/static/data/phones.json').then(resp => { this.phones = resp.data; }); } } </script> <style scoped> </style> //Detail.vue 接收参数 <template> <div> <h4>{{phone.name}}</h4> <p>{{phone.description}}</p> <router-link to="/">返回首页</router-link> </div> </template> <script> export default { data(){return {phone: {}}}, beforeMount(){ // 所有的组件中都可以访问路由管理器this.$router(VueRouter对象),当前路由this.$route // 当前手机的id参数 let id = this.$route.params.id; this.$axios.get(`/static/data/${id}.json`).then(resp => { this.phone = resp.data }) } } </script> <style scoped> </style>
-
路由嵌套
- 要在嵌套的出口中渲染组件,需要在 VueRouter 的参数中使用 children 配置
//router下index.js配置路由 import Vue from 'vue' import Router from 'vue-router' import Nav from '@/components/Nav' import TopicList from '@/components/TopicList' Vue.use(Router) export default new Router({ routes: [ /* 重定向也通过 routes 配置 { path: '/a', redirect: '/b’ } //从 /a 重定向到 /b */ { path:'/nav', component: Nav, // 配置子路由 children:[ { // path:'/nav/TopicList/:tab',//访问的路由标记 path:'TopicList/:tab',//访问的路由标记/nav/TopicList component: TopicList }, // 默认子路由 { path:'', redirect:'TopicList/all' } ] } ] }) //App.vue <template> <div id="app"> <img src="./assets/logo.png"> <router-link to="/nav">导航</router-link> <router-view/> </div> </template> //Nav.vue外层 <template> <div> <ul> <li><router-link to="/nav/TopicList/all">全部</router-link></li> <li><router-link to="/nav/TopicList/good">精华</router-link></li> <li><router-link to="/nav/TopicList/ask">问答</router-link></li> </ul> <router-view></router-view> </div> </template> //TopicList.vue被嵌套的组件 <template> <div> <h2>{{tit}}</h2> </div> </template> <script> export default { data(){return {tit: ""};}, created() {console.log("TopicList created");}, watch: { $route: { // 监听当前路由的变化 handler: function() {this.tit = this.$route.params.tab; // 执行异步任务,比如请求后端接口中的数据 },immediate:true}} }; </script> <style scoped>ul{list-style: none;}</style>
导航守卫
- 导航守卫主要用来通过跳转或取消的方式守卫导航
- 全局守卫:是指路由实例上直接操作的钩子函数,特点是所有路由配置的组件都会触发,直白点就是触发路由就会触发这些钩子函数
- beforeEach(to,from,next)
- 在路由跳转前触发,用于登录验证
- beforeResolve(to,from,next)
- 在导航被确认之前,所有组件内守卫和异步路由组件被解析之后(beforeEach和beforeRouteEnter 之后,afterEach之前)调用。
- afterEach(to,from)
- 在路由跳转完成后触发,beforeEach和beforeResolve之后,beforeRouteEnter(组件内守卫)之前。这些钩子不会接受next函数也不会改变导航本身
- beforeEach(to,from,next)
- 路由守卫: 是指在单个路由配置的时候也可以设置的钩子函数
- beforeEnter(to,from, next)和beforeEach完全相同,如果两个都设置了,beforeEnter则在beforeEach之后紧随执行。在路由配置上直接定义beforeEnter守卫
- 组件守卫:是指在组件内执行的钩子函数,类似于组件内的生命周期,相当于为配置路由的组件添加的生命周期钩子函数。
- beforeRouteEnter(to,from, next)
- beforeRouteUpdadte(to,from, next)
- beforeRouteLeave(to,from, next)
export default{ data(){}, beforeRouteEnter (to, from, next) { // 在渲染该组件的对应路由被 confirm 前调用 // 不能获取组件实例 `this` // 因为当守卫执行前,组件实例还没被创建 }, beforeRouteUpdate (to, from, next) { // 在当前路由改变,但是该组件被复用时调用 // 举例来说,对于一个带有动态参数的路径 /foo/:id,在 /foo/1和/foo/2 之间跳转的时候, // 由于会渲染同样的 Foo 组件,因此组件实例会被复用。而这个钩子就会在这个情况下被调用。 // 可以访问组件实例 `this` }, beforeRouteLeave (to, from, next) { // 导航离开该组件的对应路由时调用 // 可以访问组件实例 `this` } }
- 全局守卫:是指路由实例上直接操作的钩子函数,特点是所有路由配置的组件都会触发,直白点就是触发路由就会触发这些钩子函数
- 路由守卫回调参数
- to:即将要进入的目标 路由对象
- from :当前导航正要离开的路由
- next: 一定要调用该方法来 resolve 这个钩子。执行效果依赖 next 方法的调用参数
- next() - 通过
- next(false) - 取消路由导航,停留在from
- next(’/xx’) - 跳转到指定的路由
//router.vue下index.js
import Vue from 'vue'
import Router from 'vue-router'
import HelloWorld from '@/components/HelloWorld'
import Login from '@/components/Login'
import New from '@/components/New'
import Cookies from 'js-cookie'
Vue.use(Router)
const router = new Router({
routes: [
{
path: '/',
name: 'HelloWorld',
component: HelloWorld
},
{
path: '/new',
name: 'New',
component: New,
// 添加路由元信息
meta:{
requireLogin:true
}
},
{
path: '/log',
name: 'Login',
component:Login,
meta:{
requireLogin:false
}
}
]
})
router.beforeEach((to, from, next) => {
console.log('当前导航正要离开的路由',from,'即将要进入的目标',to);
if(to.meta.requireLogin){/
let username=Cookies.get('username');
if(username){
next();
}else{
alert('请先登录');
next('/log');
}
}else{
next();
}
})
router.afterEach((to, from) => {
console.log('afterEach',to);
})
export default router;
//首页Helloworld.vue
<template>
<div class="hello">
<h1>{{ msg }}</h1>
</div>
</template>
<script>
export default {
name: 'HelloWorld',
data(){return {msg: '欢迎来到博客园'}}
}
</script>
<style scoped>
</style>
//tab切换页面App.vue
<template>
<div id="app">
<ul>
<li><router-link to="/">首页</router-link></li>
<li><router-link to="/New">新随笔</router-link></li>
</ul>
<!-- 渲染位置 -->
<router-view/>
</div>
</template>
<script>
export default {name: "App"};
</script>
<style>
</style>
//Login.vue主要代码登录页
<template>
<div>
<form>
<input type="text" placeholder="账号" v-model="account" />
<input type="password" placeholder="密码" v-model="password" />
<input type="button" value="登录" @click="login" />
</form>
</div>
</template>
<script>
import Cookies from "js-cookie";
export default {
data() {
return {
account: "",
password: ""
};
},
methods: {
login() {
// 在cookie中保存登录的用户信息
console.log("登录成功");
Cookies.set("username", this.account);
// 路由跳转
this.$router.push("/New");
}
}
};
</script>
vuex 原理
- Vuex 实现了一个单向数据流,在全局拥有一个 State 存放数据,当组件要更改 State 中的数据时,必须通过 Mutation 进行,Mutation 同时提供了订阅者模式供外部插件调用获取 State 数据的更新。而当所有异步操作(常见于调用后端接口异步获取更新数据)或批量的同步操作需要走 Action,但 Action 也是无法直接修改 State 的,还是需要通过 Mutation 来修改 State 的数据。最后,根据 State 的变化,渲染到视图上。
vuex状态管理模式
- Vuex是vue应用的状态管理器,管理Vue所有组件状态。
- 通过vuex提供的store进行管理我们的数据,而vue只负责UI渲染的问题;数据的状态变更,由vuex来处理。
- 应用场景:大型单页应用(SPA),会出现多个视图组件依赖同一个状态,来自不同视图的行为需要变更同一个状态。- 为什么要应用vuex?
- 把组件的共享状态抽取出来,当做一个全局单例模式进行管理。这样不管你在何处改变状态,都会通知使用该状态的组件做出相应修改。
- 安装vuex: npm install vuex --save(生产依赖)
- 引入及使用
- 新建store文件夹,在main.js中引入注册
import store from './store'
new Vue({
el: '#app',
router,
components: { App },
template: '<App/>',
// 注册store,在Vue组件内部通过this.$store来访问
store,//store:store
})
- 在store文件夹下index.js文件中安装Vuex并创建Store对象
import Vuex from 'vuex'
// 安装Vuex,在Vue实例中才能使用Vuex的功能
Vue.use(Vuex)
// Vuex中的核心是Store(仓库,存储的是组建的公共状态)
// 创建Store对象
const store=new Vuex.Store({
/*
四个属性
- state状态(组件之间传递数据或组件的状态)
- getters计算属性(将state中的某状态过滤后获取新状态)
- mutations 存放如何更改状态,只能进行同步操作
- actions commit mutations中方法来改变状态(不直接更改状态),可以进行异步操作。
*/
})
Vuex Store
- 每一个Vuex应用的核心就是store仓库。实际上Vuex.Store()方法接收的是一个对象作为参数。而对象包含state,mutations,actions,getters四个属性。
- state 用来存储所有组件公共数据
- mutation 存放状态的变化,只能进行同步操作
- 第一个参数是state,第二个参数是payload(自定义)
- 只能使用store.commit(type, payload)来调用
- getters 过滤公共数据,相当于store的计算属性
- actions 解决异步改变共享数据,类似mutations,不同在于
- actions提交的是mutations,而不是直接更改状态
- actions可以包含异步操作
- 使用store.dispatch(action,payload)来调用
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VUV6CtJ3-1574426063685)(./assets/vuex.png)]
ElementUI
- 官网:https://element.eleme.cn/#/zh-CN
- 安装:npm i element-ui -S
- 引入:
- 全部引入
import ElementUI from 'element-ui'; import 'element-ui/lib/theme-chalk/index.css'; Vue.use(ElementUI); new Vue({ el: '#app', render: h => h(App) })
- 按需引入(借助 babel-plugin-component)
- npm install babel-plugin-component -D
- .babelrc:
{ "presets": [["es2015", { "modules": false }]], "plugins": [ [ "component", { "libraryName": "element-ui", "styleLibraryName": "theme-chalk" } ] ] }
- 接下来,如果你只希望引入部分组件,比如 Button 和 Select,那么需要在 main.js 中写入以下内容:
import Vue from 'vue'; import { Button, Select } from 'element-ui'; import App from './App.vue'; Vue.component(Button.name, Button); Vue.component(Select.name, Select); /* 或写为 * Vue.use(Button) * Vue.use(Select) */
- 全部引入
new Vue({
el: ‘#app’,
render: h => h(App)
});
- Layout布局 24栅格系统
<!-- gutter:每列之间的间隙 -->
<el-row :gutter="10">
<el-col :span="6" class="bg-purple">java</el-col>
<el-col :span="6" class="bg-purple">web</el-col>
<el-col :span="6" class="bg-purple">Big Data</el-col>
<el-col :span="6" class="bg-purple">Python</el-col>
</el-row>
<el-row>
<el-col :span="10" class="bg-purple">one</el-col>
<el-col :span="10" :off-set="4" class="bg-purple">two</el-col>
</el-row>
</div>
- 常用容器组件
<i class="el-icon-eleme" style="font-size:20px;color:blue;"></i>
<el-button type="primary">主要按钮</el-button>
<el-button type="success">成功按钮</el-button>
<el-button type="danger">危险按钮</el-button>
<el-button type="danger" plain>危险按钮</el-button>
<el-button type="danger" round size="mini">危险按钮</el-button>
<el-button type="danger" circle icon="el-icon-delete"></el-button>
<el-button type="primary" :loading="true">登录中</el-button>
<el-button type="primary" icon="el-icon-search">搜索</el-button>
<el-button type="primary">上传<i class="el-icon-upload el-icon--right"></i></el-button>
- 表单
<template>
<div>
<el-form label-width="80px" :model="user">
<el-form-item label="账号">
<el-input v-model="user.account"></el-input>
</el-form-item>
<el-form-item label="密码">
<el-input v-model="user.password" show-password></el-input>
</el-form-item>
<el-form-item label="确认密码">
<el-input v-model="user.confirmPass" show-password></el-input>
</el-form-item>
<el-form-item label="性别">
<el-radio v-model="user.sex" :label="1">男</el-radio>
<!-- 数值 :label -->
<el-radio v-model="user.sex" :label="0">女</el-radio>
</el-form-item>
<el-form-item label="爱好">
<el-checkbox-group v-model="user.hobby">
<el-checkbox label="game">游戏</el-checkbox>
<el-checkbox label="旅游"></el-checkbox>
<el-checkbox label="编程"></el-checkbox>
<el-checkbox label="购物"></el-checkbox>
</el-checkbox-group>
</el-form-item>
<el-form-item label="居住地">
<el-select v-model="user.home" placeholder="请选择">
<el-option label="杭州" value="hangzh"></el-option>
<el-option label="宁波" value="ningb"></el-option>
</el-select>
</el-form-item>
<el-button @click="registe">登录</el-button>
</el-form>
</div>
</template>
<script>
export default {
data(){
return{
user:{
account:'',
password:'',
confirmPass:'',
sex:1,
hobby:[],
home:''
}
}
},
methods: {
registe(){
console.log(this.user);
}
},
}
</script>
<style scoped>
</style>