Vue知识点

vue特点:

1.声明式渲染(把数据显示在页面上)

2.数据驱动视图(先有数据,再有视图)

3.双向数据绑定(数据变化,视图也变化。视图变化,数据也变化)

4.组件化开发(类似于函数的提炼)

三大件:
el: 用来指定vue实例管理的容器 
    //可以是选择器,也可以是dom结构
    //只能是普通dom,不能是html,body
    //不在此容器的dom,不会受vue实例影响

data:它是一个对象,用来规定数据
    //它的作用是把数据显示在页面上,data就是用来约定数据的
    //在后面学习,这个部分的数据会是从ajax接口中获取

methods:它是一个对象,用来定义函数表达式
    //推荐写法 es6定义函数方法
    changName (){
        ...
    }
    
   

插值表达式:{{}}
作用:输出值
{{}} 中可以写data数据字段名
     data数据表达式运算(字符串拼接,算数运算,三元表达式...)

{{}} 不能写js语句:(定义变量,if,for...)
     不能访问不是vue实例中的实例

指令:

v-text和v-html

    new Vue({
        el: '#app',
        data: {
            str: 'vue',
            strHtml: '<h1>vue</h1>'
        }
    })
---------html
    <div id="app">
        <p>{{str}}</p>
        //v-text 设置标签中全部内容 但是不解析标签
        <p v-text='str'></p>

        //v-html 可以转义内容中的html标签 
        <p v-html='strHtml'></p>
    </div>

v-if和v-show

//显示与隐藏
 v-if='布尔值'  v-show='布尔值'
    <!-- 用法相似:可以显示隐藏元素
        但是:
        v-iffalse 时 直接移除元素

        v-show为false 时 display:none
    -->
双向数据绑定 v-model:

v-model 双向绑定表单控件

<div id="app"> 
    <p>{{message}}</p>
</div>
<input type="text" v-model="message">
//v-model 是个特殊属性 
    //当数据变化时,dom会自动更新,
    //表单值变了时,数据也会发生改变
   
new Vue({
    el:'#app',
    data:{
        message:'hello'
    }
})

v-model修饰符:
.lazy   默认情况下,v-model在每次input事件触发后都会将输入框的值与数据进行同步
当添加了 lazy 修饰符后 将会在鼠标失去焦点时或change事件后进行同步
//
.number 失去焦点后 将会解析输入的内容 如果是纯数值 将被parseFloat解析 返回数字类型
如果输入的是 "112adas " 以数字开头的将会 解析为 112 ,其他的无法解析将返回原值
//
.trim   自动过滤掉首尾空格
事件绑定

v-on:事件名=“事件处理函数”

v-on: 可以简写成 @

<div id="app">  
  <input type='number' v-model='number'>
  <button v-on:click="increment">点击+1</button>
</div>
  事件处理函数写在methods中:
      const app = new Vue({
        el: '#app',
        data: { //属性
            number: 1
        },
        methods: { //方法
            increment: function () {
                this.number++
            }
        }
    })
事件合并:

用一个事件触发另一个事件,避免多次触发

@事件名 = $event.target.触发的事件名

体验:

<div id="app">
  <p>{{ message }}</p>
</div>

// 实例化
    const app = new Vue({
        el: '#app',  //管理id为app的入口节点,也就是说#app所有节点都被vue管理
        data: {  //响应式数据  就是数据发生改变 所有绑定数据的都会改变
            message: 'Hello Vue.js'
        }
    })
    console.log(app.message) // Hello Vue.js
    app.message = '可以改变所有的message'
    // 所有绑定了{{ message }}  的在message改变时也会跟着改变

阻止冒泡:
vue中的事件也有冒泡机制
在子元素上的点击事件,也会触发父元素的点击事件

如果要阻止冒泡,只需要给事件添加修饰符 .stop

v-on:click.stop=''


阻止默认行为:
阻止默认行为
添加修饰符.prevent
<a href='www.baidu.com' v-on:click.prevent></a>

也可以既不跳转也不冒泡
v-on:click.prevent.stop
v-for 列表渲染
快速批量生成列表结构
格式1:完整格式
<ul>
  <li v-for="(item,index) in arrhao" :key="index"> {{item}} </li>
</ul>
格式2:简写格式
可以省略 :key 和索引变量
<li v-for='item in aihao'>{{item}}</li>
v-bind:

动态绑定标签上的属性的值

可简写为 :

<img src='' art='' title=''/>
<img v-bind:src='imgSrc' :art='***'/>
new Vue({
el:'#app',
data:{
    imgSrc:'img/1.jpg'
}
})

v-bind绑定class:
通过动态绑定class 来控制类样式

三元表达式形式: <div class='box' :class='cls ? 'red':'blue'></div>
    解析:如果cls=true 则添加red 反之 blue

对象形式: <div :class='{red : 为true的值或表达式 }'></div>
         <div :class='redObj'></div>  vue实例中 data:{redObj:{red:true}}
    解析: {red : ### } 如果为true 才会添加到class  为false则什么都不做

数组形式: <div :class='redArry'></div>  vue实例中 data:{redArry : ['red','algin']}
    解析: 所有在数组中的类都将会被添加到 class 中
v-bind绑定style:
通过动态绑定style 来控制行内样式

对象形式: <div :style='{color:'red' , 'font-size':'20px'}'></div>

数组形式: <div :style="[{color:'red'},{},{}...]"></div>
过滤器:
本质就是一个函数 将原来的值当形参传入 修改后返回来 
如:将字符串用0补足  ES6新方法 .padStart(6,'*')
如:将单词首字母大写
        // 格式:
        // filters: {
        //     过滤器名:function(value,其他参数){
        //      return String(val).padStart(5,0)
        //     }
        // }
<p> {{ msg | f1 }} </p>  //相当于f1(msg) 得到 00vue
data:{
    msg:'vue'
},
filters:{
    f1(val){
      return String(val).padStart(5,0)
    }   
}

全局过滤器:
Vue.filter(过滤器名, 函数)
全局过滤器定义格式与局部相同 , 只是位置不同
千分位:
let s=1561.2;
let b = s.toFixed(2).replace(/(\d)(?=(\d{3})+.)/g,'$1,');
// 1,561.20
// 正则表达式解析 : (/(\d)(?=(\d{3})+\.)/g, '$1,')
// 一个数字(\d) 他的后面要有三个数字加. 每隔3个数 加一个 , 
自定义指令:
定义:
directives:{
    指令1:{
        inserted(el){ 
        }
    },
    指令2:{
        inserted(el){           
        }
    },
}

使用:
<元素 v-指令名></元素>

注意: 指令名为小写   inserted 为固定写法 inserted参数为使用自定义指令的那个dom标签

模糊查询:

http://localhost:3000/list ?name_like=头

计算属性 :computed
作用: 对现有的数据进行加工(运算) ,得到新的数据项

格式:   computed: {
            num() {
                return this.num1 + this.num2
            }
        }

使用: 在模板中 {{ 计算属性名  }}
	 在实例内部 this.计算属性名
生命钩子: created
在vue实例创建完成后调用    -> 可以设置页面初始化的渲染

组件:

  • 是可复用的vue实例
定义一个组件 :
    components : {
        组件1:{ 配置项 }    //组件名建议用大驼峰
        //配置项与vue实例中的基本一致 (没有el)  data(){ return {} }
        //data 格式固定写法
    }

使用一个组件 :
	在父组件中以标签形式使用   
        <div id="app">
        <zujian1></zujian1>
        </div>
	

props:
  • 用于接收父组件传递的值
组件之间的通讯:
父传子 :
	把父组件中定义的数据传给子组件
    
    原理:父组件通过自定义属性传给子组件,在子组件中通过  props  属性接收 
    
    父组件--: 自定义属性 = '数据' 
    子组件--: props: ['自定义属性名']  再用this.自定义属性  就能得到数据
     
 
子传父 :
	父组件 定义自定义事件触发函数  -- @abc='fn' 
	子组件触发 this.$emit('父组件的自定义事件名', 数据)
	父组件 methods:{
	  fn(obj){
          obj为子组件传递过来的数据
		}
	}
全局组件:
格式 :  
	Vue.component('mybtn' ,{
        template:`<button>全局组件</button>`
	})
适用场景: 方便于代码共享

路由:

  • 根据地址栏变化(不发请求),去局部更新不同的页面内容—> 根据哈希值 hash
  • SPA:单页面应用程序 一个系统的所有功能在一个页面上实现(移动端比较多)
    • 优点:整体不刷新,用户体验好
    • 缺点: 首次加载比较慢
vue-router插件:
链接 : https://cdn.bootcss.com/vue-router/3.1.3/vue-router.min.js 
使用:
//VueRouter 构造器创建路由实例 
   const router=new VueRouter({
	router : [
		{path:'路径' ,component : 组件名 }
        {path:'路径' ,component : {template:`<div></div>`} }
	 ]
   })
//使用路由实例
   new Vue ({
       el:'#app',
       router : 路由对象名  // 路由对象名与router一致的话可以直接写 router
   })
//设置路由出口      就是渲染在哪就放到哪
        <div id="app">
        <router-view></router-view>
        </div>
路由链接导航:
router-link 组件

        <div id="app">
        <router-link to='跳转地址'>登录</router-link>
        <router-link to='跳转地址'>注册</router-link>
        <router-view></router-view>
        </div>

router-link 将会被解析成 a 标签
  • router-link的不同写法

    • 声明式导航

      字符串写法: <router-link to='/list'>列表</router-link>
      
      对象写法: <router-link :to='{path:'/list'}'>主页</router-link>
      

      带查询参数的对象写法:

      带路径参数的对象写法:

      语法中path与params不能同存在 用name 代替path

    • 编程式导航

      通过 js 调用一个导航函数 (this.$router.push)
      
      格式 : 
      	字符串 --- this.$router.push('/login')
      	对象   --- this.$router.push({path:'/login'})
      	路径传参--- this.$router.push({name:"login" ,params:{id:'100'}})
      	查询传参--- this.$router.push({path:'login' ,query: {id:'002'}})
      	
      
  • 动态路由

    • 不同的路由地址,指向同一个组件,此时需要使用动态路由
      +

vue声明周期:

beforeCreate:

数据初始化之前调用
特点: 获取不了数据
使用场景: 几乎不用
created:(重要)
数据初始化之后调用
特点: 获取数据/方法
场景: ajax请求,获取本地数据

beforeMount: 编译挂载之前调用

特点: 打印DOM标签是之前的 {{ name }}
Mount: 编译挂载后使用 (操作DOM)
打印编译DOM标签之后 {{ 张三 }}
场景: 操作DOM + 发送ajax

beforeUpdate: 更新数据之前调用

特点: 在数据更新之前调用可以 获取更新之前的数据

Update: 数据更新后调用

特点: 获取更新之后的数据

beforeDestroy : 销毁之前

清除开发者自己的一些实例销毁后还会执行的(如:定时器)

Deatroyed: 销毁之后

侦听器:watch

侦听数据变化

侦听普通属性值:
 watch : {
     name(newVal,oldVal) {
         newVal为最新的值
         oldVal为旧值
     }
 }

侦听对象的属性: 
 watch : {
     obj : {
         deep: true,
         handler(newVal) {
             newVal为对象最新的
         }
     }
 }

侦听数组的变化:
watch : {
    arry () {
        handler(newVal) {
             newVal为数组最新的
        }
    }
}

响应式原理:
响应式流程: data => obServer => defineReactive => defineProperty => data(get/set) => 响应式数据
动态添加的数据不是响应式的:
  1. 对象:
const vm = new Vue({
    data: {
        a: 1,
        obj: {
            
        }
    }
})
vm.a = 3 是响应式的
vm.b = 2 非响应式
this.obj.age = 18 非响应

必须在 data 上才能走过响应式流程,转换成响应式数据

解决方法:

格式: Vue.set(obj, propertyName, value)

Vue.set(vm, 'b' , 2)  响应式数据

对象 => 
Vue.set(this.obj, 'age' , 18) 方法1
this.$set(this.obj, 'age' , 18) 方法2

2.数组

const vm = new Vue({
    data: {
        arr: [1,2,3]
    }
})

this.arr[1] = 6 非响应 
this.arr.length = 1 非响应 

Vue底层封装了数组的七个方法可以实现将其转换为响应式数据

push , pop , shift , unshift , splice , sort , reverse

解决方法:

$set :
 this.$set(this.arr , 1 , 6)   arr数组 ,  将索引1 , 改为6

封装的 splice 方法 :
 this.arr.splice (1 , 1 , 6)
 参数1 : 下标开始
 参数2 : 删除一个
 参数3 : 新增/替换


处理长度: 
	this.arr.splice(1) 从下标1开始 删除到最后
异步DOM更新及$nextTick
vue中数据发生改变,dom中的数据也会跟着改变,但是这个过程是异步的 vue的数据发生改变之后,DOM不会立即更新,等渲染完成的时候才会更新DOM 这样我们只能获取到改变之前的值

在实际开发中,有可能需要在数据改变之后,获取到DOM数据
这时候就可以使用 $nextTick 函数
当vue更新完DOM后 ,会自动调用$nextTick函数 确保获取到最新值

this.$nextTick(() => {
    let result = document.querySelector('p').innerText
    result将会是最新的数据
})
其他写法: 
1.
Vue.nextTick(()=> {...})
2.
Vue.nextTick(() => {...}).then()
3.
await Vue.nextTick()
...
数据组件间传递:
事件总线:
1. 创建一个 空Vue实例
const bus = new Vue()

2. 发布事件
bus.$emit('事件名', 要发布到总线上的数据 ) 

3. 接收到事件
bus.$on('事件名', 处理函数) // 回调函数参数为发布的数据
子传父:
1. 在子组件标签上创建自定义事件 <son @sons="fn"></son>

2. 父组件在methods定义 这个 fn () {  }

3. 在子组件中调用这个自定义事件
	created () {
        this.$emit('sons', 要传递给父组件的数据)
    }
2.1 返回父组件, 在父组件中接收
 fn (val) { 参数为子组件传递过来的数据 }
父传子:
1. 在子组件标签上定义自定义属性 <son :sons='son'></son>

2. 在子组件中通过props 配置项, 来接收指定的数据
props: ['son']

3. 在子组件中就能正常的调用 son 这个值

{{son}}   this.son

跨域:

反向代理:
    // 反向代理
    devServer: {
        // 设置代理
        proxy: {
            "/": {  //  "/cats" 以什么开头的要跨域
                target: 'http://api.zhuishushenqi.com/', // 域名
                ws: true, // 是否开启websockets
                changOrigin: true, // 开启代理: 在本地会创建一个虚拟服务器,然后发送请求                                       的数据,并同时接受请求的数据,
                // 这样服务器和服务端进行数据交互就不会有跨域问题
                pathRewrite: {
                    "^/cats": "/cats"
                }
            }
        }
    }


注意: 关闭axios 设置的全局请求域名

VueX

开始:
    下载引入: 
    // index.js  引入vuex 包
        import Vue from 'vue'

        import Vuex from 'vuex'
        // 加载
        Vue.use(Vuex)

    // main.js 
        import store from './index.js'
        new Vue({
            store // 绑定到Vue上
        })
使用
//index.js 
	创建store
    const store  = new Vuex.Store({
        state: { //状态容器
             count: 10,
        }
    })
    
//组件中 foo.vue
    mapState: 管理多个状态, 生成计算属性

    import { mapState } from 'vuex'  //引入辅助函数 mapState
	//计算属性中
	computed: {
        ...mapState({
            count: 'count' // 如果与自定义计算属性的名称相同,将会覆   							盖自定义计算属性
        })
    }
// 使用: 
 <p> {{count}} </p>  // 10
状态改变
改变store中的值: 
     <p> {{count}} </p>  // 10
	 <button @click="insts">自增</button> // 点击自增count
//index.js 

mutations: 改变store 中状态的唯一途径 就是 提交 (commit)mutation
mutations一旦提交就会形成一条历史记录
	// 与 state (状态容器)同级
	mutations: {  
        increment(state){
            state.count ++ 
        }
    }


//foo.vue
    methods: {
        insts(){
			this.$store.commit('increment')
        }
    }


store中的计算属性: Getter
// index.js
state: {
    todos: [
        { id: 1, text: '吃饭', done: true },
        { id: 2, text: '吃饭1', done: false },
        { id: 3, text: '吃饭2', done: false },
    ]
},
    
getters: {
    remaining: state => {
        return state.todos.filter(item => 
            item.done === false
        ).length
    }
}

//foo.vue

引入 mapGetters 
mapGetters 辅助函数仅仅是将 store 中的 getter 映射到局部计算属性

    import { mapGetters } from './index.js'

    computed: { 
		...mapGetters({
            remaining: 'remaining'
        })
    }
<p> todos未完成的数量为: {{ remaining }} </p>
计算属性中的 返回一个函数调用

//index.js 
    getters: {
		getTodoById:state => {
           return id => {
             return state.todos.find(item => item.id === id)
            }
        }
    }

//foo.vue
	...mapGetters({
        getTodoById: 'getTodoById'
    })
	
    <p>todos第二个的名字是: {{ getTodoById(2).text }} </p>
Mutation: 同步函数(同步事务)
//foo.vue
methods: {
    insts(){
        this.$store.commit('increment', {num:2})
    }
}

//index.js
mutation:{
    increnent(state, payload){
        state.count += payload.num
    }
}


// 对象方法简写: 
// foo.vue
methods: {
    insts(){
        this.$store.commit({
            type: 'increment',
            num: 2
        })
    }
}
//index.js 不变
使用常量替代 Mutation 事件类型   
// mutation-types.js
export const SOME_MUTATION = 'SOME_MUTATION'


// index.js 
import { SOME_MUTATION } from './mutation-types.js'
import { mapMutations } from 'vuex'
mutations: {
    [SOME_MUTATION](state){
        state.message = '你好, 世界'
    }
}

// foo.vue
methods: {
    ...mapMutations(['SOME_MUTATION'])
    //或
    ...mapMutations(
        {changeMutation :'SOME_MUTATION'})
}

<button @click="SOME_MUTATION"> 更改 message </button>
//或
<button @click="changeMutation"> 更改 message </button>

Action :分发 Action
// index.js 

actions : {
    increment({commit}, {num: }){
        setTimeout(()=> {
            commit({
                type: 'increment',
                num
            })
        })               
    }
}

// foo.vue
<button @click="asyncIncrement">异步按钮(增加)</button>

asyncIncrement(){
	this.$store.dispatch('increment', {
        num: 3
    })
}
Module : 将 store 分割成模块
const moduleA = {
    state: {...},
    mutations: {...},
    actions: {...},
    getters: {...},
    ...
}
const moduleB = {
    state: {...},
    mutations: {...},
    actions:{...},
    ...
}
             
// 绑定    
const store = new Vuex.Store({
    modules: {
       a: moduleA,
       b: moduleB
    }
})
// 使用
store.state.a 
store.state.b 
              
// 创建modules文件夹
// 创建foo.js ,bar.js , index.js

// foo.js
   export default{
       state: {
         a: 123   
       },
       mutations: {...}
   }
// index.js
   // 引入modules         
   import foo from './modules/foo'
   // 注册
 const store = new Vuex.Store({
    modules : {
        foo
    }
 })
                
//foo.vue 使用
     <p> {{ $store.state.foo.a }} </p>   // 123
    
    

命名空间问题
// module 模块内部的action, mutation , getter 是注册在全局的        $store命名空间上的

// 如果想要一个模块具有高度的封装度 和 复用性 , 可以通过添加
namespaced: true的方式使其成为带命名空间的模块, 当模块被注册后,它的所有getter,action及mutation都会自动根据模块注册的路径调整命名

// index.js  注册为 index
export default {
    namespaced: true;
    gettrts: {
        abc(state){
            return state.a + '...'
        }
    }
}

//加命名空间后调用
<p> {{$store.getters['index/abc'] }} </p>

----------- 局部 ------------

// foo.vue
// 映射局部模块的 state
...mapState('foo',{  // 模块名称
    a: 'a'
})
使用: 
<p> {{ a }} </p>


// 映射局部模块的 getters
 ...mapGetters('foo', ['abc'])
使用:
<p> {{ abc }} </p>
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值