[前端系列]Vue入门03

77 阅读3分钟

继续深入Vue

本节我们继续深入Vue的核心部分内容

收集表单数据

Vue管理各类表单元素的值示例如下

<body>
    <div id="root">
        <form>
            账号:<input type="text" v-model="account"> <br/><br/>
            密码:<input type="password" v-model="password"> <br/><br/>
            性别:
            男<input type="radio" name="sex" v-model="sex" value="male"> 
            女<input type="radio" name="sex" v-model="sex" value="female"> <br/><br/>
            爱好:
            学习<input type="checkbox" v-model="hobby" value="study">
            打游戏<input type="checkbox" v-model="hobby" value="game">
            吃饭<input type="checkbox" v-model="hobby" value="meal">
            所属校区
            <select v-model="city">
                <option value="">请选择校区</option>
                <option value="beijing">北京</option>
                <option value="shanghai">上海</option>
            </select>
            <br/><br/>
            <textarea v-model="other"></textarea>
            <br/><br/>
            同意<input type="checkbox" v-model="arg">
            <button>提交</button>
        </form>
    </div>
​
    <script>
        const vm=new Vue({
            el:'#root',
            data:{
                account:'',
                password:'',
                sex:'',
                hobby:[],
                city:'',
                other:'',
                arg:false,
​
            }
        })
    </script>
</body>

v-model也有修饰符,如下:

1.number表示输入的是数字(类型转换)

2.lazy表示失去焦点才收集

3.trim去除前后空格

内置指令

v-text:向其所在的标签插入文本(会覆盖标签内的文本内容)注意:不解析字符串

<div v-text="name"></div>//name是一个data里的属性

v-html:与v-text类似都可以插入文本,但是v-html会解析html元素

v-once:只被Vue渲染一次

<h2 v-once>{{name}}</h2>

v-pre:跳过节点的编译过程,可以用它跳过没有指令语法,插值语法的节点,会加快编译过程,使用跟v-once一样,也没有值

自定义指令

借助directives配置项,我们可以配置新的指令

directives里面直接写函数即可,该函数接受两个参数,分别是对应的元素的真实DOM,和一个绑定对象,绑定对象我们更关注的是绑定对象的value属性,它决定了调用该指令的节点的文本内容

directives里函数调用的时机:

1.指令与元素成功绑定时

2.指令所在的模板被重新解析时调用

示例1:

<body>
    <div id="root">
        <h2 v-big="n"></h2>
    </div>
​
    <script>
        const vm=new Vue({
            el:'#root',
            data:{
                n:1
            },
            directives:{
                big(rdom,binding){
                    rdom.innerText = binding.value*10
                }
            }
        })
    </script>
</body>

示例2:设计一个v-fbind指令,有默认获取焦点并绑定值的功能

<body>
    <div id="root">
        <h2 v-big="n"></h2>
        <input type="text" v-fbind:value="">
    </div>
​
    <script>
        const vm=new Vue({
            el:'#root',
            data:{
                n:1
            },
            directives:{
                big(rdom,binding){
                    rdom.innerText = binding.value*10
                },
                //对象式写法
                fbind:{
                    //绑定成功时调用
                    bind(rdom,binding){
                        rdom.innerText=binding.value
                    },
                    //指令所在元素被插入页面时
                    inserted(rdom,binding){
                        rdom.focus()
                    },
                    //指令所在模板被重新解析时 
                    update(rdom,binding){
                        rdom.innerText=binding.value
                    }                   
                }
            }
        })
    </script>
</body>

生命周期

Vue的生命周期如下:

1.beforeCreate:最早的初始化,还没开始数据代理

2.created:数据代理、数据监测,此时,已经可以访问data和methods

3.beforeMount:还未解析DOM

4.mounted:DOM解析完成,页面显示出内容

5.beforeUpdate:页面是旧的,数据是新的

6.updated:页面与数据同步完成

7.beforeDestroyed:data,methods这些东西即将销毁

8.destroyed:全部销毁

组件化编程

创建组件:

注意点:不能写el,data要写成函数

示例如下:

<body>
    <div id="root">
        <school></school>
    </div>
​
    <script>
        const school=Vue.extend({
            template:`
                <div>
                    <h2>{{name}}</h2>
                </div>    
            `,
            data(){
                return{
                    name:'Java'
                }
            }
        })
​
        const vm=new Vue({
            el:'#root',
            components:{
                school,
​
            }
        })
    </script>
</body>

Vue.component('xxx')可以全局注册组件

定义组件时规定name,这个name是开发者工具显示的名字,跟注册用的名字没有区别

不用Vue.extend直接写配置对象也可以

每调用一次Vue.extend,都会调用一次VueComponent构造函数

但是,每次调用,返回的对象都是一个新的对象

组件中的data,methods,watch,computed中的函数,它们的this都是VueComponent

Vue的实例对象与VueComponent实例对象关系:

1.二者所拥有的东西几乎全部都是一样的

2.vm中可以有el配置项,vc中不可以

Vue的原型对象就是VueComponent的原型对象的原型对象

render:用于解析模板

ref属性

ref被用于给元素或者子组件注册引用信息

ref可以理解为id的代替,可以用于获取DOM

如果放在了组件上,我们可以获取组件的实例对象(vc)

示例如下:

<template>
  <div>
    <h1 v-text="msg" ref="title"></h1>
    <button @click="showDOM">点我获取DOM</button>
    <SchoolInfo/>
  </div>
</template><script>
import SchoolInfo from './components/SchoolInfo.vue'export default {
  name: 'App',
  data(){
    return {
      msg:'欢迎!'
    }
  },
  components: {
    SchoolInfo,
  },
  methods:{
    showDOM(){
      console.log(this.$refs.title)
    }
  }
}
</script><style></style>

props配置

props可以给组件传数据,写法上,只要当作属性放在组件标签上面就可以了,如果加:,可以转换为JS表达式,props不用数组接受而是写对象式可以限制类型,不符合类型会报错

App.vue

<SchoolInfo name="黑马" address="南京"/>

SchoolInfo.vue

<script>
export default {
    name:'SchoolInfo',
    data(){
        return {
            msg:'欢迎'
        }
    },
    //props:['name','address'],
    props:{
        name:{
            type:String,
            required:true
        },
        address:{
            type:String,
            default:'北京'
        }
    }
}
</script>

props优先级比data高,注意不要重名,props不能使用保留字(比如'key')

另外,不要直接修改props,如果要修改的话最好配一个值相等的data属性

mixin混入

mixins混入配置项,可以导入把外部js的东西混入进去(以数组形式)

作用:mixin实现了复用配置项

混合不会覆盖冲突数据,但是生命周期会均生效

用Vue.mixin可以全局混入

插件

本质就是一个对象,但是必须要有install方法

使用插件时,可以用Vue.use这个API

install函数接受一个参数,就是Vue构造函数本身,除此以外,我们在use是,还可以传任意参数

那么我们就可以实现给Vue原型上加方法,定义指令,定义混入等等

export default {
    install(){
        console.log('hahah')
    }
}

scoped属性

在style标签上添加scoped属性,可以避免css重名冲突,也就是互不干扰

当然Vue里,我们添加lang属性,可以用less语法,但是要安装less-loader

浏览器的本地存储

下面展示向本地存储操作数据:

<body>
    <button onclick="saveData()">点我存数据</button>
    <button onclick="readData()">点我读数据</button>
    <button onclick="deleteData()">点我删数据</button>
    <script>
        let p={name:'张三',age:18}
        //写
        function saveData(){
            localStorage.setItem('msg','hello')
            localStorage.setItem('num',666)
            localStorage.setItem('person',JSON.stringify(p))//对象必须转换为JSON

        }
        //读
        function readData(){
            console.log(localStorage.getItem('msg'))
        }
        //删除
        function deleteData(){
            localStorage.removeItem('msg')
        }
        //清空
        function clearData(){
            localStorage.clear()
        }

    </script>
</body>

注意:读取的key不存在,会返回null

localStorage即使浏览器被关闭也不会消失

sessionStorage的API与localStorage一样,但是,浏览器被关闭就没了,localStorage则会在用户清缓存才消失

组件自定义事件

我们也可以自定义类似click,change这样的事件,但是,是给组件绑定的

绑定的时候,我们可以使用v-on:事件名称="demo"的方式绑定

也可以使用this.refs.student.refs.student.on('事件名称',回调函数)

触发用this.$emit('事件名称',数据)

解绑用this.$off('事件名称')多个事件解绑,写进数组里

全局事件总线

可以实现任意组件通信

本质就是找一个X作为中间人,每个组件都在X身上放一个自定义事件,以此来互相交流数据

因此,这个X就必须放在所有组件都能看到的地方,也就是Vue的原型对象上(一个重要关系那里讲过)

除此以外,X也必须能调用emit,emit,on,$off

emit,emit,on,offVue的原型对象上,此时,最好的办法,是在main.js里,在创建vm时,我们在Vue构造函数中,把X创建在beforeCreate这个生命周期钩子中,当然,这个X我们正式点,可以改个名叫off在Vue的原型对象上,此时,最好的办法,是在main.js里,在创建vm时,我们在Vue构造函数中,把X创建在beforeCreate这个生命周期钩子中,当然,这个X我们正式点,可以改个名叫bus

注意,组件在mounted绑定了自定义事件后,最好在beforeDestroy里面解绑

消息订阅与发布

消息订阅与发布,也是一种组件间通信的方式

首先,我们需要安装pubsub-js这个库

当然,mounted里面订阅消息,beforeDestroy要取消订阅,另外,订阅消息的回调函数需要用箭头函数

$nextTick

this.nextTick(function(){})里面的回调函数会在下一次碰到DOM更新时执行