Vue 学习文档
Vue 学习文档
vue 起步
- 引包
- 启动
new Vue(options)
- options:
el
目的地(可以用类名、标签名等,也可以直接用mod元素)#elementId
.elementClass
div
document.getElementById('elementId')
template
内容data
数据
vue 基础语法
vue 指令
v-if
是否插入元素v-show
是否隐藏元素v-bind
给元素属性赋值,单向数据绑定- 简写::{属性名}=
v-model
在表单控件或者组件上创建双向绑定v-on
绑定事件- 简写: @{事件名}=
- 传参 直接在方法名后追加
(参数)
- 同时获取参数和event对象
v-on:click="warn('参数', $event)"
v-for
遍历-
循环数组 (item, index)
-
循环对象 (val, key, index)
<div v-for="(item, index) in items"></div> <div v-for="(val, key) in object"></div> <div v-for="(val, key, index) in object"></div>
-
vue 组件化
-
使用步骤:
- 编写子组件
- 声明子组件
- 使用子组件
-
父组件向子组件传递数据
-
父组件用
v-bind
传递,子组件必须props里先声明 -
props可以设置默认值
-
props可以指定数据类型(String/Number/Boolean/Array/Object/Date/Symbol/Function)
const MyHeader = { template: `<h1>我是头部</h1>` } const MyBody = { template: `<h1>我是中部 {{index}}</h1>`, //props: ['index'], props: { items: { // 必须提供字段 type: String, //指定类型 required: true }, index: { // 可选字段,有默认值 type: Number, default: 3 }, // 带有默认值的对象 propE: { type: Object, // 对象或数组默认值必须从一个工厂函数获取 default: function () { return { message: 'hello' } } }, // 自定义验证函数 propF: { validator: function (value) { // 这个值必须匹配下列字符串中的一个 return ['success', 'warning', 'danger'].indexOf(value) !== -1 } } } } let app = new Vue({ el: '#demo1', components: { 'my-header': MyHeader, 'my-body': MyBody, 'my-footer': MyFooter }, template: ` <div> <my-header/> <my-body :index="tip"/> </div> `, data: { tip: 1 } })
-
-
注册全局组件
Vue.component('组件名',组件对象)
-
全局组件不带 's'
过滤器-filter
-
全局过滤器:
Vue.filter('my-filter', function (value) { // 返回处理后的值 })
-
组件内的过滤器
filters:{ '过滤器名','过滤方式fn' }
- fn中的参数1是传递的数据,允许追加额外的参数
- return是返回显示的内容
- 使用:{{ myText | 过滤器名 }}
- 场景:处理后台返回数据
监控-watch
-
watch和v-model的区别:
- v-model仅仅是数据的同步,watch可以数据和行为挂钩
-
参数:(newVal,oldVal)
watch({'myText': function (newVal, oldVal) { // 做点什么 }})
-
无法监视复杂数据,watch监控的是引用地址
-
深度监视的方法:
watch({'myText': { deep: true, handler: function (newVal, oldVal) { // 旧值将与新值相同 } }})
计算-computed
-
凡是函数内部有this.相关属性,改变都会触发当前函数
-
计算属性默认只有 getter
computed: { // 计算属性的 getter fullName: function () { // `this` 指向 vm 实例 return this.firstName + ' ' + this.lastName } }
-
也可以提供一个 setter
computed: { fullName : { //this.firstName改变或this.lastName改变触发get方法 //this.fullName改变时执行set方法 get: function () { return this.firstName + ' ' + this.lastName }, set: function (newValue) { var names = newValue.split(' '); this.firstName: names[0]; this.lastName: names[names.length - 1]; } } }
具名插槽-slot
-
插槽可以让组件像原生标签一样使用
-
使用方法:定义的组件中包含
<slot>
组件: <a v-bind:href="url" class="nav-link" > <slot></slot> </a> 使用: <navigation-link url="/profile"> Your Profile </navigation-link>
-
插槽内可以包含任何模板代码,包括 HTML
-
<slot>
元素有一个特殊的特性:name。这个特性可以用来定义额外的插槽 -
可以在组件模板里的
<slot>
标签内部指定默认的内容
组件生命周期
- beforeCreate 组件创建前
- created 组件创建后
- 可以操作data中的数据
- 对应父组件
v-if=true
时触发
- beforeMount 组件装载前
- mounted 组件装载后
- beforeUpdate 组件更新前
- 可以获取原dom
- updated 组件更新后
- 数据发生改变触发
- 可以获取新dom
- beforeDestroy 组件销毁前
- destroyed 组件销毁后
- 对应父组件
v-if=false
时触发
- 对应父组件
注意:使用
v-if
频繁触发组件创建与销毁不合理,应该使用<keep-alive>
包裹组件
- activated
<keep-alive>
包裹的组件激活 - deactivated
<keep-alive>
包裹的组件停用
获取DOM元素/组件对象-ref
-
在组建的DOM部分,任意的标签中写上
ref="{自定义元素名}"
-
通过组件对象
this.$refs.{自定义元素名}
获取到元素 -
可以在mounted中操作DOM数据
-
在子组件标签中写入
ref="{自定义组件名}"
,获取到的就是组件对象 -
Vue中DOM更新是异步的,异步导致DOM未渲染,无法操作DOM元素的解决办法
this.$nextTick(function(){ //执行 })
vue 插件
vue-router的使用
-
路由原理:
- 添加hashChange事件,通过location.hash控制innerHTML
-
vue-router使用步骤:
- 引入vue-router.js
- 安装插件
- 创建一个路由对象
- 配置路由对象
- 将配置好的路由对象关联到vue实例中
- 制定路由改变局部的位置
Vue.use(VueRouter); var router = new VueRouter({ routes: [ { name:'login', path: '/login',component: Login }, { name:'register', path: '/register',component: Register } ] }) //也可以router.addRoutes([{},{}]) var app = { template:`<div> <router-link to="/login">登录</router-link> <router-link :to="{name:'register'}">注册</router-link> <router-view></router-view> </div>` }; new Vue({ el: "#app", router:router, components:{ app:App }, template: '<app/>' })
-
url传参数
- 查询字符串
- 配置:在router-link标签中注册参数内容
<router-link :to="{name:'register',query:{id:1}}">注册</router-link>
- 规则:
{ name:'register', path: '/register',component: Register }
- 生成:
<a href="/register?id=1">
- 获取: 子组件中使用
this.$route.query
获取参数对象
- 配置:在router-link标签中注册参数内容
- path方式
- 配置:
:to="{name:'register',params:{id:1}}"
- 规则:
{ name:'register', path: '/register/:id',component: Register }
- 生成:
<a href="/register/1">
- 获取:
this.$route.params
- 配置:
- 查询字符串
-
$router Vs. $route
- $router VueRouter路由对象
- $route 路由信息对象
-
嵌套路由
-
router-view套router-view,路由children路由
const Login = { template: `<div> 我是登录页 <router-link :to="{name:'login.woman'}">女性登录页</router-link> <router-view></router-view> </div>`, }; var router = new VueRouter({ routes: [{ name: 'login', path: '/login', component: Login, children: [{ name: 'login.woman', path: 'woman', component: Woman }]}, {name: 'register', path: '/register', component: MyHeader} ] })
-
-
权限控制
router.beforeEach((to,from,next) => {})
- 每次路由匹配后,渲染组件前
- to 跳转后路由信息对象
- from 跳转前路由信息对象
- next 放行
next()
- next 取消用户导航
next(false)
- next方法里添加参数可以重定向
next( { name:'login' } )
- 路由meta元数据 > 对于路由规则是否需要验证权限的配置
- 路由对象中和name属性同级
{meta:{isChecked:true}}
- 路由对象中和name属性同级
-
路由懒加载
- 优化流量,按需请求
axios
-
axios挂载到vue对象上:
Vue.prototype.$axios = axios;
-
合并请求
axios.all([getUerAccount(),getUserPermissions()]) .then(axios.spread(function(acc,pers){ //两个请求现在都完成 }));
-
取消请求
const CancelToken = axios.CancelToken; const source = CancelToken.source(); // 创建标识请求的源对象 this.source = source; // 讲对象存储到组件 cancelToken: source.token, // 请求的options属性 this.source.cancel(); // 取消到之前的那个请求 //前端的断电续传,及时获取当前上传的文件大小,储存起来 var file = <input type="file"/> .files[0].slice(文件开始部分,文件结尾部分) new FormData().append('file',file); // 后台就是接受多次文件,都往上传文件上追加
-
拦截器
-
请求拦截器:在发起请求之前,做的事
-
响应拦截器:在响应回来以后,做的事
axios.interceptors.request.use(function(config){ //在请求发送之前做一些事 return config; },function(error){ //当出现请求错误是做一些事 return Promise.reject(error); });
axios.interceptors.response.use(function(response){ //对返回的数据进行一些处理 return response; },function(error){ //对返回的错误进行一些处理 return Promise.reject(error); });
-
-
post发送数据为
"name='jack'"
时,数据类型为formData形式 -
参数
- this.$axios.defaults 修改公共配置
- transformRequest 加工请求体数据
- transformResponse 加工返回数据
- withCredentials:false 跨域请求默认不带cookie
- 携带token
- xsrfCookieName:'XSRF-TOKEN',//默认值
- xrsfHeadername:'X-XSRF-TOKEN',//默认值
webpack
- 源码分析
- 把所有模块的代码放入到函数中,用一个数组保存起来
- 根据require时传入的数组索引,能知道需要哪一段代码
- 从数组中,根据索引去除包含我们代码的函数
- 执行该函数,传入一个对象
module.exports
- 我们的代码,按照约定,正好是用
module.exports='xxx'
进行赋值 - 调用函数结束后,
module.exports
从原来的空对象就有值了 - 最终
return module.exports
所为require函数的返回值
Vuex
- 使用步骤
- 引入并安装vuex插件
- 创建store对象
const store = new Vuex.Store()
- 配置store中的数据/存/取
- 将vuex关联到vue实例中
- 数据获取
- 数据修改
this.$store.commit()
- 禁止使用
this.$store.state.xxx=
直接修改
其他
SPA 单页面应用程序
- vue-router默认使用hash模式,可以使用history模式去除#
- 在history模式下,可以scroll导航后滚动
- history模式实现其实基于服务器每次返回index.html而客户端根据
location.pathname
来做渲染
SEO 搜索引擎优化
- SPA下SEO必然较差
- 使用与渲染,固定的页面作为服务器响应的结果
常用点
父组件中调用子组件的方法:
- 先给子组件定义属性
ref="xxx"
- 生命周期中用
this.$refs.xxx
获取此子组件对象 - 由于组件是异步的,如果在created中调用会返回undefined,解决办法是
this.$nextTick(function(){ //执行 })
Element Ui组件Events事件使用方法
- 组件对象
methods
中定义回调方法 - 组件标签中引入
@close="handleClose"
eventbus使用
bus.$on('event', msg => {// 执行操作})
注册监听事件bus.$emit('event', msg)
触发监听操作
antd Form组件---mapPropsToFields
- 子组件的mapPropsToFields可以触发父组件change事件
- mapPropsToFields 里面返回的表单域数据必须使用 this.$form.createFormField 包装。
- this.form.setFieldsValue用于在表单生成以后设置值
自定义组件内部触发组件change事件
this.$emit('change', arguments);