Vue简介
  • 2014年诞生,2013年react,09年angularjs
  • 作者: 尤雨溪
  • 核心概念: 组件化 双向数据流(基于ES5中的defineProperty来实现的),IE9才支持
  • angular核心: 模块化 双向数据绑定(脏检测:一个数组($watch),性能弱)
    • 开发一个登陆模块,登陆需要显示的头部、底部、中部
    • 组件:组合起来的一个部件(头部、底部、中部)
    • 细分代码
      • 头部: 页面、样式、动态效果
      • 代码: templete style script
数据流
  • 1向:js内存属性发生改变,影响页面的改变
  • 1向:页面的改变影响js内存属性的改变
Vue实例对象
// 构造函数
var my = new Vue({
el: '#app', // 挂载点 (设置vue对象装载到页面位置)
template: '<div> {{ fruit }} </div>', // 模板
data: { // 数据
    fruit: 'apple'
}

});
data中的属性会被代理到 my 对象中,可以使用 my.fruit 来获取属性值
vue常用指令
  • v-text
  • v-html
  • v-if
  • v-show
  • v-model
  • v-bind

代码


<template>
<!-- 只能有一个根节点 -->
  <div>
    <pre>
            * v-text 是元素的innerText 只能在双标签元素中使用
        * v-html 是元素的innerHTML 不能包含<!-- {{ xxx }} -->
        * v-if   元素是否移出或插入
        * v-show 元素是否隐藏或显示
        * v-model双向数据绑定
        * v-bind 单向数据绑定(内存js改变影响页面,页面改变不影响内存js)
    </pre>

    v-text:
    <span v-text="text"></span>
    <hr />

    v-html:
    <span v-html="html"></span>
    <hr />

    v-if:
    <div v-if="isShow" style="height: 100px; background-color:red;"></div>
    <hr />

    v-show:
    <div v-show="isShow" style="height: 100px; background-color:green;"></div>
    <hr />

    v-model:
    <input type="text" name="username" v-model="username" />
    {{ username }}<br/>
    <!--给下面的input value赋值 用 v-bind:value="username" -->
    <input type="text" name="" v-bind:value="username"  />
    <hr />
  </div>
</template>

<script>
export default {
    data(){
        return {
            text: '我是v-text内容',
            html: `
                <ul>
                    <li>哈哈</li>
                    <li>呵呵</li>
                </ul>
            `,
            isShow: false,
            username: 'admin'
        }
    }
}
</script>

<style>

</style>
class结合v-bind使用
  • 需要根据可变的表达式的结果来给class赋值,就需要用到v-bind:class=”xxx”
  • v-bind:属性名=”表达式”,最终表达式运算结束的结果赋值给该属性
    • 简化的写法: :属性名="表达式"
  • class: 结果的分类
    • 一个样式: 返回字符串(三元表达式和 key和样式的对象清单)
    • 多个样式: 返回对象(样式做key,true或false做值)
<template>

  <div>
    <div v-bind:class="isRed? 'red' : 'green'">单个class样式</div>
    <ul>
        <!-- 当stu.score = A 时 匹配red,当stu.score= B 时匹配green  -->
        <li v-for="stu in stus" :class="{'A': 'red', 'B': 'green'}[stu.score]"> {{ stu.name }}</li>
    </ul>

    <div :class="{'red': true, 'big': true}">多个class样式</div>
  </div>
</template>

<script>
export default {
    data(){
        return {
            isRed: false,
            stus: [
                {
                    name: 'jack',
                    score: 'A'
                },
                {
                    name: 'lucy',
                    score: 'B'
                },
            ]
        }
    }
}
</script>

<style>
.red{
    background-color: red;
}
.green{
    background-color: green;
}
.big{
    font-size: 30px;
}
</style>
methods 和 v-on的使用
  • 绑定事件的方法
    • v-on:事件名="表达式||函数名"
    • 简写:@事件名="表达式||函数名"
  • 函数名如果没有参数,可以省略() 只给一个函数名称
  • 函数的声明需要在export default 这个对象的根属性加上 methods 属性中
  • 凡是在template中使用函数或变量,不需要使用this
v-on高级用法
  • 修饰符:

  • .stop - 调用 event.stopPropagation()。

  • .prevent - 调用 event.preventDefault()。
  • .capture - 添加事件侦听器时使用 capture 模式。
  • .self - 只当事件是从侦听器绑定的元素本身触发时才触发回调。
  • .{keyCode | keyAlias} - 只当事件是从特定键触发时才触发回调。
  • .native - 监听组件根元素的原生事件。
  • .once - 只触发一次回调。
  • .left - (2.2.0) 只当点击鼠标左键时触发。
  • .right - (2.2.0) 只当点击鼠标右键时触发。
  • .middle - (2.2.0) 只当点击鼠标中键时触发。
  • .passive - (2.3.0) 以 { passive: true } 模式添加侦听器

  • 用法:

绑定事件监听器。事件类型由参数指定。表达式可以是一个方法的名字或一个内联语句,如果没有修饰符也可以省略。

从 2.4.0 开始,v-on 同样支持不带参数绑定一个事件/监听器键值对的对象。注意当使用对象语法时,是不支持任何修饰器的。

用在普通元素上时,只能监听 原生 DOM 事件。用在自定义元素组件上时,也可以监听子组件触发的自定义事件。

在监听原生 DOM 事件时,方法以事件为唯一的参数。如果使用内联语句,语句可以访问一个 eventvon:click="handle(ok, event)”。

  • 示例:
<!-- 方法处理器 -->
<button v-on:click="doThis"></button>

<!-- 对象语法 (2.4.0+) -->
<button v-on="{ mousedown: doThis, mouseup: doThat }"></button>

<!-- 内联语句 -->
<button v-on:click="doThat('hello', $event)"></button>

<!-- 缩写 -->
<button @click="doThis"></button>

<!-- 停止冒泡 -->
<button @click.stop="doThis"></button>

<!-- 阻止默认行为 -->
<button @click.prevent="doThis"></button>

<!-- 阻止默认行为,没有表达式 -->
<form @submit.prevent></form>

<!--  串联修饰符 -->
<button @click.stop.prevent="doThis"></button>

<!-- 键修饰符,键别名 -->
<input @keyup.enter="onEnter">

<!-- 键修饰符,键代码 -->
<input @keyup.13="onEnter">

<!-- 点击回调只会触发一次 -->
<button v-on:click.once="doThis"></button>
<template>

  <div>
    <button v-on:click="isRed = !isRed">按钮</button>

    <button v-on:click="change()">按钮</button>

    <button @click="change">按钮</button>
  </div>
</template>

<script>
export default {
    data(){
        return {
            isRed: false,
            stus: [
                {
                    name: 'jack',
                    score: 'A'
                },
                {
                    name: 'lucy',
                    score: 'B'
                },
            ]
        }
    },
    // 声明函数,属于组件对象
    methods: {
        // 包含多个函数名称做key,函数提供做value
        change (){
            this.isRed = !this.isRed;
            this.stus.push({
                name: 'mick',
                score: 'A'
            });
        }
    }
}
</script>

<style>
.red{
    background-color: red;
}
.green{
    background-color: green;
}
.big{
    font-size: 30px;
}
</style>
v-for的使用
  • 可以使用操作数组(item,index)
  • 可以使用操作对象(value,key,index)

  • key 是类似于trank by的属性,为了告诉vue,js中的元素和页面的关联,当删除元素的时候,是单个元素的删除而不是整版的替换,所有需要其关联关系。2.0版本后必输设置(性能)

<template>
  <div>
    <ul>
        <li v-for="(stu, index) in stus" v-bind:key="index">
            index:{{ index }} - stu:{{ stu }}
        </li>

        使用对象的方式-滚动歌词(时间做key,内容作为value)<hr />
        <li v-for="(value, key, index) in person" v-bind:key="index">
            value:{{ value }}-key:{{ key }}-index:{{ index }}
        </li>
    </ul>
  </div>
</template>

<script>
export default {
    data(){
        return {
            isRed: false,
            stus: [
                {
                    name: 'jack',
                    score: 'A'
                },
                {
                    name: 'lucy',
                    score: 'B'
                },
            ],
            person: {
                name: 'zhangsan',
                realname: '张三'
            }
        }
    }
}
</script>

<style>
.red{
    background-color: red;
}
.green{
    background-color: green;
}
.big{
    font-size: 30px;
}
</style>
简单学生添加删除案例
<template>
  <div>
    <ul>
        <li v-for="(stu, index) in stus" :key="stu.id" :class="{'A':'red','B':'blue','C':'green','D':'pink'}[stu.score]">
            {{ stu.name }} - {{ stu.score }}    
            <button @click="del(index)">删除</button>
        </li>
    </ul>
    学生姓名:<input type="text" name="name" v-model="name"/><br/>
    学生成绩:<input type="text" name="score" v-model="score"/><br/>
    <button @click="addStu">添加学生</button>
  </div>
</template>

<script>
export default {
    data(){
        return {
            isRed: false,
            name:'',
            score:'',
            stus: [
                {
                    id: 1,
                    name: '张三',
                    score: 'A'
                },{
                    id: 2,
                    name: '张无忌',
                    score: 'B'
                },{
                    id: 3,
                    name: '赵敏',
                    score: 'C'
                },{
                    id: 4,
                    name: '殷素素',
                    score: 'D'
                },
            ]
        }
    },
    // 声明函数,属于组件对象
    methods: {
        // 添加
        addStu (){
            // 获取页面输入的值:v-model
            this.stus.push({
                id: 1,
                name: this.name,
                score: this.score
            });

            this.name = '';
            this.score = '';
        },
        // 删除
        del (index){
            this.stus.splice(index, 1);
        }
    }
}
</script>

<style>
.red{
    background-color: red;
}
.green{
    background-color: green;
}
.blue{
    background-color: skyblue;
}
.pink{
    background-color: hotpink;
}
</style>
父子组件使用(父传子)
  • 父需要声明子组件,引入子组件对象,声明方式如下:
// 引入子组件
import 子组件对象名 from './xxx.vue';

// 声明子组件

components: {
// 组件名(在模板中使用): 组件对象
}
  • 全局组件,使用更为方便,不需要引入和声明直接使用
  • 在main.js中引入异常,在main.js中使用 vue.component('组件名',组件对象);
  • 声明为全局组件后,就可以直接通过组件名使用
// 引入子组件对象
import headerVue from './components/header.vue';
import bodyVue from './components/body.vue';
import footerVue from './components/footer.vue';

// 声明为全局组件
Vue.component('headerVue', headerVue);
Vue.component('bodyVue', bodyVue);
Vue.component('footerVue', footerVue);
父组件向自组件传递数据
  • 父组件通过子组件标签属性将值传递
    • 方式一:常量 <header-vue 属性名="常量值"></header-vue>
    • 方式二:变量<header-vue :属性名="变量名"></header-vue>
  • 子组件使用该属性值需要使用props 声明
    • 在根属性加 props: ['属性名1','属性名2'...]
    • 在页面中就可以直接使用 {{ 属性名 }}
    • 在js中可以直接使用 this.属性名 访问
export default {
  data () {
    return {
    }
  },
  // 接受父组件参数的设置
  props:['textbody']
}
子组件向父组件通信(vuebus)
  • 通过new Vue() 的一个对象,来$on(‘事件名’, fn(prop1, prop1)) 绑定事件
  • 另一个组件引入统一个vuebus,来$emit(‘事件名’,prop1, prop2) 触发事件
vue高级
  • vue过滤器
  • 获取dom元素
  • mint-ui
  • vue组件的使用
  • 组件间通信
  • vue-router使用
  • vue-resource发起http请求
  • axios
vue过滤器
  • content | 过滤器, vue中没有提供默认过滤器,需要我们自定义过滤器
  • 组件内过滤器 + 全局过滤器
    • 组件内过滤器就是options中的一个filters的属性(一个对象)
      • 多个key就是不同的过滤器名,多个value就是与key对应的函数体
    • Vue.filter(名, fn)
    • 如果名称相同以局部为主

app.vue

<template>
  <div>
    请输入内容:
    <input type="text" name="name" v-model="name"/>
    显示:{{ name | myFilter}}
  </div>
</template>

<script>

    export default {
        // 自定义过滤器
        filters: {
            myFilter: function(value){
                // 输入的内容翻转: 转换为数组->翻转数组 ->转换为字符串
                return value.split('').reverse().join('');
            }
        },
        data(){
            return {
                name:''
            }
        }
    }
</script>

<style scoped>

</style>

main.js

// 全局过滤器
Vue.filter('myFilter1', function(value){
    return value.split('').reverse().join(',');
});
获取DOM元素
  • 前端框架就是为了减少dom操作,特定情况下也提供了的操作方式
  • 在指定的元素上,添加ref=”名称”
  • 在获取的地方加入 this.$refs.名称
    • 如果ref放在了原生DOM元素上,获取的数据就是元素DOM对象
    • 如果ref放在组件对象上,获取的就是组件对象
    • 获取子组件DOM对象,通过this. refs.sub. el
  • 事件
    • created 完成数据初始化,未生成DOM
    • mounted 将数据已经装载到DOM之上,且DOM生成完毕
    <template>
  <div>
    <sub-vue ref="sub"></sub-vue>
    <div ref="myDiv"></div>
  </div>
</template>

<script>
    import SubVue from './components/sub.vue';
    export default {
        data(){
            return {
            }
        },
        components: {
            SubVue: SubVue
        },
        // 组件创建后,数据已经完成初始化,但DOM还未完成
        created (){ // 事件的处理函数(created)
            console.log(this.$refs.sub);           // vue的组件对象
            this.$refs.sub.$el.innerHTML = '哈哈';  // 获取vue组件对象对应的DOM对象
            console.log(this.$refs.myDiv);         // undefined 获取不到
        },

        // 数据装载到DOM上后,各种数据已经就位,将数据渲染到DOM上,DOM已经生产
        mounted (){ // 事件的处理函数(created)
            console.log(this.$refs.myDiv);// 获取的原生DOM对象
            this.$refs.myDiv.innerHTML = '案发生的发生';
        }
    }
</script>

<style scoped>

</style>
vue-router
  • 前端路由 核心就是锚点值的改变,根据不同的值,渲染指定DOM位置的不同数据
  • ui-router(anglar):锚点值改变,通过ajax获取模板
  • vue中,模板数据不是通过ajax请求来的,而是调用函数获取到模板内容
  • vue核心插件:
    • vue-router 路由
    • vuex 管理全局共享数据
  • 使用方式
    • 1: 下载 npm install vue-router -S
    • 2: 引入 impot Router from 'vue-router'
    • 3: 安装插件 Vue.use(Router)
    • 4: 创建路由对象并配置路由规则
    • 5: 将其李洋老师对象传递给Vue实例,options中
    • 6: 留坑
命名路由
  • 需求:通过a标签单击实现页面跳转
  • 使用 标签
<a href="#/music">进入音乐</a>
<a href="#/movie">进入电影</a>
// 以上直接通过a标签方式直接指定路径名称,如果锚点发生改变不好维护

<!-- 根据name跳转(推荐使用该方式)-->
<router-link :to="{name: 'Music'}">进入音乐</router-link>
<router-link :to="{name: 'Movie'}">进入电影</router-link>

<!-- 根据path跳转-->
<router-link to="/movie">进入电影</router-link>
  • vue-router 中挂在了两个对象
  • route() router(功能函数)
  • 参数传递两种方式:
    • 1:查询字符串 query:{key: value} -> /detail?id=1
    <router-link :to="{name: 'Detail',query: {id: user.id}}"> 查看详情 </router-link>

    路由path不用改:
    {
      path: '/detail',
      name: 'Detail',
      component: Detail
     }
- 2: 路径字符串 params:{key: value} -> /detial/1
    <router-link :to="{name: 'Detail',params: {id: user.id}}"> 查看详情 </router-link> 

    路由path需要改:
    {
      path: '/detail/:id',
      name: 'Detail',
      component: Detail
    }
  • 获取参数
    • this.$route.query.id
    • this.$route.params.id
编程式导航
  • 不能保证用户一定会单击某些按钮
  • 并且当前操作除了路由跳转以外,还有一些别的附加操作
  • this.$router.go 根据浏览器记录 前进 1 后退-1
  • this.$router.push(直接跳转到某个页面显示)
    • push参数: 字符串 /xxx
    • push参数: 对象 {name: ‘xxx’,query:{id:1}, params:{id:1,name:’zhangsan’}}
    • 注意:有params的路由规则中一定记得在路由规则path中添加 path: ‘/movie/:id’,
<template>
  <div >
         <button @click="goMusic">跳转到music</button>
         <button @click="goMovie">跳转电影</button>
         <button @click="goBack">跳转到上一页</button>
         <button @click="testQuery">编程导航传递参数query方式</button>
         <button @click="testParams">编程导航传递参数params方式</button>
  </div>
</template>

<script>
export default {
  data () {
    return {
    }
  },
  methods: {
    goMusic (){
        this.$router.push('/music');
    },
    goMovie (){
        this.$router.push({
            name: 'Movie' // 路由规则 name值
        });
    },
    goBack (){
        this.$router.go(-1); //-1 上一次浏览器记录 1 下一个浏览器记录
    },
    testQuery (){
            // 查询字符串方式: /music?id=1&name=zhagnsan
            this.$router.push({
                name: 'Music', // 路由规则 name值
                query: {
                    id: 1,
                    name: 'zhagnsan'
                }
            });
    },
    testParams (){
            // 查询字符串方式: /movie/1
            this.$router.push({
                name: 'Movie', // 路由规则  name值
                params: {      // 路由规则  path: '/movie/:id',
                    id: 1,
                    name: 'zhagnsan'
                }
            });
    }
  }
}
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>

</style>
原生监听锚点值改变
window.addEventListener('hashchange', function(){
    var text = '';// 可以换成模板数据
    switch(location.hash){
        case '#/music':
            text = '各种音乐数据'; 
            break;
        case '#/movie':
            text = '各种电影数据';
            break;
    }
    document.getElementById('content').innerHTML = text;
});
重定向和404
  • 重定向(写死路径名) {path: '/', redirect: '/home'}
  • 重定向(使用name) {path: '/', redirect: {name: 'home'}}
  • 404:在路由规则的最后一个规则中写一个很强大的匹配
    • {path: '*', component: notFoundVue}
    • notFoundVue.vue: 404页面组件
多视图模式
  • 以前一个路由对应一个
  • 现在一个路由可以对应多个
  • 使用components 实现多视图模式
    <router-view name="header"></router-view>
    <router-view ></router-view>  没有name使用default
    <router-view name="footer"></router-view>

     routes: [
        {
          path: '/',
          name: 'Home',
          // 注意这里名称为components
          components: {
            header: HeaderVue,
            footer: FooterVue,
            default: Home
          }
        }
     ]
嵌套路由

借助 vue-router,使用嵌套路由配置,就可以很简单地表达这种关系。

  • 用单页实现多页应用,使用复杂的嵌套路由完成
  • 开发中一般都会用到嵌套路由
  • 视图包含视图
  • 路由父子级关系路由配置


routes: [
{ path: '/user/:id', component: User,
children: [
{
// 当 /user/:id/profile 匹配成功,
// UserProfile 会被渲染在 User 的 <router-view> 中
path: 'profile',
component: UserProfile
},
{
// 当 /user/:id/posts 匹配成功
// UserPosts 会被渲染在 User 的 <router-view> 中
path: 'posts',
component: UserPosts
}
]
}
]

vue-resource (了解)
  • 早期vue团队开发的插件
  • 停止维护了,作者推荐使用axios
axios的使用
Logo

前往低代码交流专区

更多推荐