1、#模板语法:双括号语法,他可以单独使用,也可以嵌套在任何标签内部
表现形式:{{ 语法 }}
Vue组件(Helloworld.vue)包含三个部分:
<template>:视图
<script>:逻辑部分
<style>:样式部分
单独使用
{{hello}}
{{1+1}}
{{ 0<10 ? '对的' : '错的'}}
{{注意:只能使用单行语句,并且不能执行在html元素中}}
嵌套使用:
<p>{{ flag }}</p>
通过下面的代码绑定,hello要与return 那个名字相同
export default {
name: 'HelloWorld',
data () {
return {
hello:"hello vue",
flag:"我是flag"
}
}
}
#vue基本指令
v-html:渲染文本
v-text:渲染文本
她两的区别在于v-html只在于渲染文本,而v-text可渲染文本也可以渲染标签等
v-bind:绑定 {{}}也可用于数据绑定 它们的区别就在于{{}}不可以用于html元素
v-bind的简写:(:)
#条件渲染:v-if v-else
需要注意的是:同样的标签之间是不可以嵌套的,比如a带href属性,p,这样嵌套之后就是兄弟关系,而不是想要的父子关系,也就是只要是承载内容的标签是不可以嵌套为父子关系的。用v-else时v-if v-else搭配使用
template是一个承载容器不会渲染为一个组件,因为v-if就是一个指令,所以必须要把她添加到一个元素上,但是如果想要切换多种元素,就可以把template元素当作不可见的包裹元素,并且在上面使用v-if结果不包含template元素
v-else-if
v-show
v-show与v-if的区别:
v-if是真正的条件渲染,因为他会确保在切换过程中条件块内的事件监听器和子组件适当的被销毁和重建
v-if是懒惰性的,如果在初始渲染时条件为假的时候,就什么也不做,一直到条件为真,也就是连模块也不加载,相比之下。v-show就简单得多,不管初始条件是什么。,元素总是会被渲染的,不管是true是false就算是false他也会加载也就是display为none,而v-if这个模块都没有
一般来说v-if有更高的切换开销,而v-show有更高的初始渲染开销,所以,如果需要很频繁的切换,就是用v-show,如果运行时条件很少改变,则使用v-if比较好
#列表渲染:
v-for:根据一组数组(不是对象)的选项列表进行渲染,v-for指令需要使用item in items的特殊语法,items是元数据数组,item是数组的迭代名,item也可以是两个,(name,index) in items v-bind: key="index" 增加key方便寻找index
每个列表尽可能的添加key
#事件处理
事件监听:v-on:监听DOM元素的变化或是执行某些操num++等
事件处理方法:methods:事件函数,里面是某一个button或者是别的标签所绑定的函数,这里面牵扯到的是this,this来索引的是当前data中的数据,指向当前的组件,(函数中如果要改变data中的某些操作时 就会牵扯到this)
事件参数:事件中的默认参数应该是event对象,如果想要访问真正的DOM,可以通过$event来进行传event对象getInforName($event)
创建一个新的vue组件:
首先其中必须包括三个部分,template script style
其次,想要外部可以访问这个组件也就是这个组件的内容可以显示在页面,需要在App.vue的<script>中通过import Events from "./components/Event"引入这个vue组件,然后通过 components: {
HelloWorld,
Events
}绑定这个组件,最后在template中 <Events />
事件修饰符:stop,prevent,capture,self,once(只生效一次)
submit click都具有,v-on:click.once=""
为什么会有事件修饰符,它解决了什么问题?
在事件处理程序中调用event.preventDefault和event.stopProgation是一个常见的需求,一个是阻止默认事件一个是阻止冒泡,但是更好的方式是不去操作DOM细节而使用数据逻辑操作,所以为了v-on提供了事件操作符
按键操作符:监听按键信息,v-on:keyup,通过监听这个,可以看到键盘上的每个按键的keycode,所以他会有按键别名。.enter .tab .delete .esc .up..down .left .right,监听或者说绑定键盘上的某个键要做的事情 比如enter键
v-on:keyup.enter=""
简写方法:@代替v-on
下面的是由事件引发的一些数组的关系:
数组更新检测:变异方法,替换数组
变异方法引起视图更新
push pop shift unshift solice sort reverse
替换数据不会引起视图更新
filter concat slice
显示过滤排序结果:filter
#计算属性与观察者
计算属性computed
计算属性和methods的区别:我们可以将同一个函数定义为一个方法而不是一个计算属性,两种方式的最终结果是完全相同的,然而不同的是计算属性是基于他们的以来进行缓存的。计算属性只有相关依赖发生改变时才会重新求值,只要message还没有改变,多次访问计算属性会立即返回之前的计算结果,而不必再次执行函数。而methods是每执行一次都会执行一次函数
#表单的输入绑定
v-model:双向数据绑定
用watch来监听表单内部的变化,也就是可以提取到框里面的内容
修饰符:lazy 失去焦点时才进行你的输入响应 number trim
计算属性和监听属性watch:当有一些数据需要随着其他数据的改变而变动时,很容易滥用watch,所以更好的选择是使用计算属性而不是watch,因为计算属性的特性是当改变的时候才进行重新加载
#class与style的绑定:
绑定class样式:1|v-bind:class=" {active:isactive, isage:age...}"
2|绑定的数据对象放在data中或者放在计算属性中,
3|数组 v-bind:class="[1,2]"
4|:class="{[可以进行操作比如active%2==0时才class才绑定这个类名],..}"
[在data中定义的,{'':如果后面的计算为真时,前面的字符串也就是类名回生效}]
绑定内联样式:v-bind:style
绑定class也就是:字符串拼接''+对象 或者true or false 数组
2、1、组件由三个部分组成:
1/template
里面只能存在一个根元素,也就是只能存在一个div
2/script
必须导出当前的组件,就是name:
data:用来绑定数据的,所有数据都要先进行初始化
3/style
scoped:样式只在当前组件内生效,也就是局部作用,不影响其他组件.防止命名冲突 样式错乱。
而App.vue中style中定义的样式实在全局中生效的,还有初始化样式都会放在这里面的style标签中
2、子父级组件交互(通信)
因为组件实例的作用域是孤立的,这意味着不能也不应该向子组件内的模板内直接引用父组件的数据,父组件的数据通过props才能下发到子组件
父->子:props
传递静态数据,首先父组件先把需要传递的数据准备好通过在视图template中的引入子组件的标签中传递过去,子组件在逻辑层script与data同级添加props:[]接收
传递动态数据:也就是传递的数据是改动的,意思就是父组件改动数据。子组件可以接收到这个改动的数据。需要加入绑定 :
也可以实时的获取父组件传递给子组件的数据 用v-module
验证数据类型:通过子组件在props中指定传递数据的类型来进行验证,还可以通过对象required为true指定必选项和通过default:10指定默认值,如果不传递子组件那就取的默认值
如果验证的是数组或者对象时,要用function return 指定默认值
子->父:$emit 通过自定义事件来进行传递
一个流程中有可能会父传子子进行一定运算之后再传给父里面会涉及到props emit computed event
3、代码在slots中插槽:传递的是视图 父组件向子组件扔东西,子组件通过slot来容纳父组件传递的东西
插槽与组件的区别在于 它用于传递视图,应用是如果有两个页面相似的页面,数据相同,但是页面的某些位置不同,那么就通过插槽用视图显示出来
单个插槽
具名插槽 通过name绑定slot,在父组件中指定那个名字,若有多个数据要传递 则给父元素指定sloat="s1"
作用域插槽:数据是子传父,因为视图由父级提供的,而数据源是由子集决定的,视图由父级决定,而组件式父亲给儿子传递,父亲是数据源,儿子是决定视图的 slot-scope
<div class="parent">
我是父组件
<Child>
<!--具名插槽 通过指定插槽的name-->
<div slot="s1">
<p>我是插槽1</p>
<p>我是插槽11</p>
</div>
<p slot="s2" slot-scope="props">
{{props.text}}
</p>
</Child>
</div>
<div class="child">
我是子组件
<slot name="s1"></slot>
<hr />
<slot name="s2" text="我是数据传递"></slot>
</div>
4、代码在comkeep中。动态组件:通过保留的component元素,动态的绑定它的is特性,我们可以让多个组件使用同一个挂载点,并且动态的切换。可以自己写方法,也可以通过<component v-bind:is="currentview">,这样的做法就是可以进行组件之间的切换。当组件之间来回切换的时候其实是重新加载的,但是如果不让他重新加载节省内存 就用keep-alive
什么情况下缓存?如果不需要实时更新数据的情况就缓存下来,不用重新加载节省内存。
5、代码在anim中。css的过度与动画
在css过渡和动画中自动应用class
过度类名:
v-enter:进入开始
v-enter-active:执行过程中
v-enter-to:结束动画
v-leave:离开开始
v-leave-active:离开过程
v-leave-to:结束离开过程
动画:@keyframes v-enter-active v-leave-active animation
引入第三方库,在index.html中引入之后在transizition中直接用enter-active-class leave-active-class来指定需要效果的类名就好了,第三方库比如:animate.css
6、自定义指令
全局指令:在main.js中通过vue.directive指定
vue.directive('focus',{
inserted:function(el){
//这里是要做的事情
}
})
局部指令:在expot default中添加directives
7、过滤:filters配合 | 使用
3、Axios:
1、安装
npm install axios
2、引入加载
import Axios from "axios"
Vue.prototype.$axios=Axios;
3、请求
get请求:
created(){
this.$axios("http://www.wwtliu.com/sxtstu/blueberrypai/getIndexBanner.php")//
this.$axios("端口地址“,{
prames:{
type:
counr=""
}
})
.then(res=>{
console.log(res);
this.names=res.data.banner;
})
.catch(
error=>{
console.log(error);
}
)
}
post请求:
注意:axios接受的post请求参数的格式是form-data格式
form-data格式:?name=iwen&age=20
x-www-form-urlencoded:{name:"",age:""}
`引入第三方库qs stringify 把form-data格式变为下面那种
this.$axios.post("端口地址",qs.stringify({
}))
引入第三方库 import qs from "qs"
全局axios的配置
axios.defaults.baseURL="域名"//可以在其他组件中的端口号不用每次都写域名
axios.defaults.headers.common['Authorization']=AUTH_TOKEN
axios.defaults.headers.post['Content-Type']='application/x-www-form-urlencoded'
axios拦截器
4、跨域处理
第一步在index.js中的proxyTable中加入”/api“:{
target:服务器端口地址
changeOrigin:true,
pathRewrite:{
'^/api':''
}
}
在main.js中添加HOST
Vie.prototype.HOST='/api'
这样完成之后,写url就不像之前那样写了。
var url=this.HOST+""
this.$axios.get(url,{
params:{
count:10,
start:10
}
})
this.$axios.post(url,{
count:10,
start:10
})这样做完之后要注意不要再去设置他的全局配置这样的话做出的跨域处理是没有作用的 还有就是要重新启动服务器
这样的跨域方案,只能适用于测试阶段,打包的时候不会具备服务器,后端解决
5、Mock数据模拟
1、自己创建JSON文件使用get请求形式访问数据
优点:方便快捷
缺点:只能存在get请求
1、项目集成服务器,模拟各种接口
优点:模拟真实线上环境
缺点:增加开发成本
3、直接使用线上数据
优点:真实
缺点:不一定每个项目都存在
4、数据模拟库:mockjs(待学)
路由:
1、安装路由
npm install --save vue-router
2、在main.js中引入路由
import VueRouter from "vue-router"
Vue.use(VueRouter)
3、配置路由文件
var router = new VueRouter({
routes:[{
path:"/",
component: helloworld
},{
path:"/new",
component: newrouter
}]
})
new Vue({
el: '#app',
components: { App },
router,
template: '<App/>'
})
4、在App.vue中用<router-view></router-view>引入进行承载
这些都是在main.js中引入的,axios和自定义指令都在main.js中指定,这样main.js这个文件会太庞大,所以需要将把路由放在一个单独的文件中用export default导出在main.js中用import引入
单独文件:
import Vue from 'vue'
import VueRouter from "vue-router"
import helloworld from "../components/HelloWorld"
import newrouter from "../components/newrouter"
Vue.use(VueRouter)
export default new VueRouter({
routes:[{
path:"/",
component: helloworld
},{
path:"/new",
component: newrouter
}]
})
main.js引入:
import router from "./router"
Vue.config.productionTip = false
/* eslint-disable no-new */
new Vue({
el: '#app',
components: { App },
router,
template: '<App/>'
})
5、跳转路由
《1》<router-link to="路由path"></router-link>在这种情况下,他其实会被渲染成一个a标签,也可以通过a标签来跳转路由,<a href="/#/new"></a>,但是建议使用router-link 为什么?
无论是H5history模式还是hash模式,它的表现形式一致,所以当你要切换路由是在IE9降级使用hash模式不需要任何的变动
在H5history下,router-link会守卫点击事件,让浏览器不再重新加载页面
在H5history下使用bash后所有的to属性后都不需要写路径
《2》这个to是可以动态的,通过v-bind来绑定,也可以通过写path
//通过v-bind绑定来动态的添加路由
<router-link :to="urldata.hellonew">hello</router-link>
</li>
</ul>
</div>
<script>
export default {
name:"NaveList",
data(){
return {
urldata:{
helloworld:"/",
hellonew:"/new"
}
}
}
}
<router-link :to="{path:'/new'}">hello</router-link>path后面也可以是对象
路由嵌套:childeren 也要给定显示的位置
{
path:"/course",
name:"Course",
component: Course,
//默认页面一进来就是java页面
//redirect:"/course/java",
children:[{
path:"/java",
name:"java",
component:java
},{
path:'/web',
name:"web",
component:web
}]
}
几级路由就有几个router-view
默认显示:在父路由下面指定redirect
路由传递参数:master
通过name传递参数,传递的参数可以是单个值也可以是多个值值的类型也可以复杂一些比如对象什么的
<li><router-link :to="{name:'Master',params:{count:100,type:obj}}">专家</router-link></li>
{
path:"/Master/:count/:type",
name:"Master",
component:Master
}
索引处理:exact 指定类名:.active-link-class
<li>
<router-link exact to="/">首页</router-link>
</li>
第二种:在全局index.js中配置全局linkActiveClass:"active",在app.vue中设置.active:red样式
设置mode:"history"路由会记录所有所点的记录
其实路由的加载都是在统一的路由文件index.js中
1、安装element
1.1npm i element-ui -S
npm install babel-plugin-component -D
1.2修改.babelrc
{
"presets": [["es2015", { "modules": false }]],
"plugins": [
[
"component",
{
"libraryName": "element-ui",
"styleLibraryName": "theme-chalk"
}
]
]
}
1.3引入import { Button, Select } from 'element-ui';
Vue.use(Button)
Vue.use(Select)
https://github.com/surmon-china/vue-awesome-swiper
2、使用swiper
安装
npm install vue-awesome-swiper --save
引用
//全局引用
import VueAwesomeSwiper from 'vue-awesome-swiper'
import 'swiper/dist/css/swiper.css'
Vue.use(VueAwesomeSwiper)
//局部引用
import 'swiper/dist/css/swiper.css'
import { swiper, swiperSlide } from 'vue-awesome-swiper'
export default {
components: {
swiper,
swiperSlide
}
}
3、使用lazyload
首先先安装:npm install vue-lazyload --save-dev
配置:在main.js中引入
import VueLazyload from 'vue-lazyload'
Vue.use(VueLazyload)
使用: data(){
return{
//引入图片。如果是在js中必须require进来
imgobj: {
src: require("../assets/logo.png"),
error: require("../assets/error.jpg"),
loading: require("../assets/timg.gif"),
}
}
}
<img v-lazy="imgobj" />
4、rem与less
安装less npm install less less-loader
在webpack.base.config.js中配置:
{
test: /\.less$/,
use:[
"style-loader",
"css-loader",
"less-loader"
]
}
在package.json中看有没有css-loader style-loader 如果没有得话需要安装
npm install css-loader style-loader
在index.html中添加一个js、
vuex是一个状态管理模式,能保证在每一个组件中你所拿到的值是相通的,更是一个共享状态的一个东西,因为单项数据流如果有太多的共享状态时可能会遭到破坏,就比如一个外带的组件要去共享一个子父级组件,是没有办法获取的这两个组件的内容的,要去获取的话也需要同一个父级。
什么情况下要使用vuex?
如果不打算开发大型的单页面应用,使用vuex是比较繁琐的
vuex状态管理,
view->(dispatch)Action ->(commit) Mutations ->(Mutate) state -> (render)view
注意:actions不是必需品,所以不一定非要需要他来提供state和mutations的互通,在异步的情况下有可能会有actions
使用vuex,先安装npm install vuex
引入 import vuex from 'vuex'
vue.use(vuex)
每一个vuex应用的核心就是store仓库,store基本上就是一个容器,包含着应用中大部分的状态state
vuex和单纯的全局对象有两个不同:
1、vuex的状态管理存储是响应式的,当vue组件从store中读取状态的时候,如果store中的状态发生了变化,那么相应的组件也会得到高效更新
2、不可以直接改变store中的状态,改变store中的状态的唯一方法就是commit mutation,这样使得我们可以方便的跟踪每一个状态的变化,
创建store仓库
const store=new Vuex.Store({
state:{
state:{
count:0
}
}
})
通过这个读取
computed:{
getcount(){
return this.$store.state.count;
}
}
vuex的相关操作(state mutations action)
状态变更:通过store.state来获取状态对象,以及通过store.commit方法触发状态变更
const store=new Vuex.Store({
state:{
count:0
},
mutations:{
incrent(state){
state.count++;
}
}
})
methods:{
add(){
this.$store.commit("incrent")
}
}
上面的操作让我们知道虽然是两个互不相关的组件,但是也可以用vuex实现数据共享,在一个页面中调用++方法count++ 在另外一个组件中的数据也在加加即使这个页面没有调用加加的这个方法,这就类似于淘宝购物车和结算页面,他们的数据始终是保持共享的。
actions: actions:{
//context:承接上下文
incrent(context){
context.commit("incrent");
},
unincrent(context){
context.commit("unincrent");
}
}
在页面中也不是用commit来变换数据了,而是使用dispach
Action提交的是mutation 而不是直接变更状态
Action可以包含任何异步状态:mutatio是不能有异步的,如果只是当前本地数据的修改就只用mutation就好了 如果需要网络请求来使用数据的话就必须使用
action
Getter:
目的:对数值的获取有一个计算方案,上面的操作是直接获取的是state,这样是不合理的
module:目的是管理的状态过多,按照模块化的操作管理
4