快速构建vue项目
- 先确保node,webpack,vue已经安装
- 安装vue-cli
npm install -g @vue/cli
- 如果要使用vue-cli-2.x
npm install -g @vue/cli-init
vue init webpack my-project
创建my-project项目- 创建完后
cd my-project
、npm insatll
、npm run dev
开启项目
基本指令
- {{ 变量 }}:只能存在单行语句
- v-once:只能渲染一次
<p v-once>{{ msg }}</p>
- v-html:解析HTML结构
<div v-html="hello"></div>
- v-bind:指令(解析属性中的对象)简写(:)
<a v-bind:href="url">百度</a>
- v-if:条件渲染
<h1 v-if='ok'>YES</h1> <h1 v-else>NO</h1>
- v-else-if:多种条件渲染
- v-show:条件渲染
- v-show与v-if的区别:
v-if 是“真正”的条件渲染,因为它会确保在切换过程中条件块内的事件监听器和子组件适当地被销毁和重建。
v-if 也是惰性的:如果在初始渲染时条件为假,则什么也不做——直到条件第一次变为真时,才会开始渲染条件块。
相比之下,v-show 就简单得多——不管初始条件是什么,元素总是会被渲染,并且只是简单地基于 CSS 进行切换。
一般来说,v-if 有更高的切换开销,而 v-show 有更高的初始渲染开销。因此,如果需要非常频繁地切换,则使用 v-show 较好;如果在运行时条件很少改变,则使用 v-if 较好。
列表渲染
- v-for:
<ul><li v-for="name in names">{{name}}</li></ul>
- v-for数组带下标渲染:
<ul><li v-for="(item,index) in names" :key="index">{{index}}--{{item}}</li></ul>
- v-for对象带key渲染:
<ul><li v-for="(value,key,index) in obj" :key="index">{{value}}--{{key}}--{{index}}</li></ul>
事件处理
- 事件改变data数据,data数据改变会引起视图的变化
- 事件传递参数 $event
- v-on:绑定事件,简写(@)
<button @click="clickHandler('haha',$event)"></button>
$event为事件参数
数组更新检测
- append,unshift 最开始讲数组的时候:老师在讲一个方法的时候会说,返回一个原数组还是新数组
- 变异方法:
改变原数组,则可以引起视图更新
不改变原数组,创建新数组,则无法引起视图更新
- filter()、concat() 和 slice() 。它们不会改变原始数组,而总是返回一个新数组。当使用非变异方法时,可以用新数组替换旧数组
计算属性
- computed:{} 如果数据没有改变不会重新计算
- menthods:{} 每次都会重新计算
- 计算属性缓存 vs 方法
- 我们可以将同一函数定义为一个方法而不是一个计算属性。两种方式的最终结果确实是完全相同的。然而,不同的是计算属性是基于它们的依赖进行缓存的。计算属性只有在它的相关依赖发生改变时才会重新求值。这就意味着只要 message 还没有发生改变,多次访问 reversedMessage 计算属性;
Class 与 Style的绑定
- 利用
v-bind:
绑定 <p :class="active"></p>
或者<p :class="{active:isActive}"></p>
- :class=“classObj” 可以是对象,也可以是数组,class="[isActive? activeClass: errorClass]"
- 应用中的样式: :class="[{helloC:classDemo,isActive? activeClass: errorClass}]" 注意对象中不可以拼接字符串,数组中可以;
- :style="{color:‘red’}"
表单输入与绑定
- v-model 双向数据绑定
<input type="checkbox" id="checkbox" v-model="checked">
复选框,单选框都这样<select v-model="selected"></select>
选择框
修饰符
- .lazy 懒惰输入,只有按回车才显示
- .number 将用户的输入转化为数字类型;
- .trim 去掉收尾空格;
监听数据变化
- watch:{ inputmsg(data){} //inputmsg是v-model绑定的,是变量就行}
组件
<template>只能存在一个根容器</template>
<script>
export default{
name:'组件名',
data(){
//data必须是函数
}
}
</script>
<style lang="css" scoped></style>
作用域- 使用时,在app.vue中导入
import name from "./components/name"
然后在components:{}中注册,然后在引用
组件传值
- 父传子:props 子组件利用props:[‘name’] 接收
- 子传父:事件传递
sendMsg(){this.$emit('getMsg','value')}
父组件用函数接收,在引用组件中绑定@getMsg=“接收函数” - 通过v-model也可以在父子组件之间传递数据
- 动态组件
<component v-bind:is="currentTabComponent"></component>
- 保存组件的状态
<keep-alive>
<component v-bind:is="currentTabComponent"></component>
</keep-alive>
Props
- props验证类型以及默认值
props:{
age:Number,
name:{
type:String,
reauired:true
},
gender:{
type:String,
default:1
} ,
hobby:{
type:object,
default:function(){
return {message:'hello'}
}
}
}
- 默认值如果是数组或者对象,必须返回一个function
- 也可以自定义验证函数
访问根实例
- 通过
this.$root.foo
访问或者修改 - 通过
this.$parent.foo
访问父组件 - 通过
this.$refs.foo
获取原生DOM或者访问子组件
插槽
<slot></slot>
可以实现插槽- 按name传内容
<slot name='v1'></slot>
传递内容<SlotDemo><template slot="v1"></template></SlotDemo>
- 作用域插槽
<SlotDemo><template slot-scope="v1">{{ v1.a }}</template></SlotDemo>
传递内容<slot a='传输的数据'></slot>
过渡动画
- 组件的过渡:
<transition name="fade">...</transition>
fade-enter,fade-enter-active,fade-enter-to
分别表示进入过渡的开始状态,中间过渡状态,结束状态fade-leave,fade-leave-active,fade-leave-to
分别表示离开过渡的开始状态,中间过渡状态,结束状态- 动画一定要脱离文档流
- 第三方css动画库
<transition
name="custom-classes-transition"
enter-active-class="animated tada"
leave-active-class="animated bounceOutRight"
>
...
</transition>
自定义属性
- 全局:
Vue.directive('focus',{ inserted:function(el) {el.focus();} })
使用v-focus
- 局部:在vue实例里 directives:{…}
钩子函数
- bind:只调用一次,指令第一次绑定到元素时调用。在这里可以进行一次性的初始化设置。
- inserted:被绑定元素插入父节点时调用 (仅保证父节点存在,但不一定已被插入文档中)。
- update:所在组件的 VNode 更新时调用,但是可能发生在其子 VNode 更新之前。指令的值可能发生了改变,也可能没有。
- componentUpdated:指令所在组件的 VNode 及其子 VNode 全部更新后调用。
- unbind:只调用一次,指令与元素解绑时调用。
- 钩子函数的参数 (即 el、binding、vnode 和 oldVnode)。
过滤
filters:{gl:function(value){....}}
使用{{ varName | gl }}
axios的使用
- 安装
npm install axios
- 运行
npm start
- 导入
import Axios from 'axios'
- 配置 :
Vue.prototype.$axios = Axios
axios.defaults.baseURL = 'https://api.example.com'; //请求的域名
// 添加请求拦截器
axios.interceptors.request.use(function (config) {
// 在发送请求之前做些什么
if(config.method === 'post'){
config.data = qs.stringify(config.data) //qs是post请求的参数格式转变,见下文post请求
}
return config;
}, function (error) {
// 对请求错误做些什么
return Promise.reject(error);
});
//响应拦截同理:见https://www.kancloud.cn/yunye/axios/234845
- 使用 : 和ajax用法差不多
//get请求
mounted(){
this.$axios.get(...,{params:{page:1}})
.then(res=>{...})
.catch(error=>{...}) }
//post请求
//import qs from "qs" 解决参数格式的转码问题,使用qs.stringify({参数})
mounted(){
this.$axios.post(...,{name1:value1,name2:vaule2})
.then(res=>{...})
.catch(error=>{...}) }
webpack配置解决跨域问题
- 在webpack文件中配置 vuehttp/config/index.js
proxyTable:{
'/doubai':{
target:'/要请求的网址',
pathRewrite:{
'^doubai':''
},
changeOrigin:true
}
}
- main.js文件配置
Vue.prototype.HOST = '/doubai'
- 使用
var url = this.HOST + '/page/...'
this.$axios.get(url)...
路由
- 路由 注意:项目在初始化的时候不要集成vue-router
- 安装:
cnpm install vue-router --save
- 如果在一个模块化工程中使用它,必须要通过 Vue.use() 明确地安装路由功能:
import Vue from 'vue'
import VueRouter from 'vue-router'
Vue.use(VueRouter)
- 创建路由
const router = new VueRouter({
routes:[
{
path:"/",
name:"HelloWorld",
component:HelloWorld
}
]
})
- 给出路由显示的位置
<router-view />
- 将路由对象注入Vue实例中
router
;可以在src文件夹下面新建一个router文件夹保存路由,然后export default导出; - 路由跳转
router-link
属性:tag - 动态路由(参数传递)/:id;组件接收{{ this.$route.params.id }}
- 路由嵌套
- 在路由里面加children[{path:‘base’,component:Base}]
- 编程式的导航
this.$router.push
this.$router.replace
this.$router.go
- 命名路由(参数传递)
- :to="{name:‘HelloWorld’,params:{}}"
- 路由重定向:routes:[{path:’*’,component:NotFound},{path:’/’,redirect:’/learn’}]
- 路由杂项方法…
- 路由高亮:
* `.router-link-active{样式}` 也可以修改类名,在router文件中 `linkActiveClass:'active'`这时active就是激活的link
* `.router-link-exact-active{样式}` 也可以修改类名,在router文件中 `linkExactActiveClass:'currentactive'`这时active就是精准激活的link
异步引用资源
- const LRC = Vue.component(‘lrc’,(resolve)=>require([’…/components/LRC’],resolve))