Vue 学习笔记

前言
官网:https://cn.vuejs.org/
官方文档:https://cn.vuejs.org/v2/guide/
热门组件库地址:https://github.com/vuejs/awesome-vue
第三方UI框架:Element、Iview、MintUI
安装
直接引入方式:下载 vue.js ,直接在项目中引入(和引用 JQuery 一样)

CDN引入方式:

开发环境

<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>

生产环境

<script src="https://cdn.jsdelivr.net/npm/vue@2.6.0"></script>

NPM,使用 vue-cli 构建 vue 项目

初入门
<script>
<html>
<head>
<meta charset="utf-8">
<title>Vue-Learn</title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
<div id="box1">
{{name}}
</div>
</body>
<script type="text/javascript">
// 初始化 vue,在浏览器控制台可以通过 vm 控制
var vm = new Vue({
el: "#box1",
data:{
name: "Hello World!"
},
// 方法
methods: {

        },
        // 计算属性
        computed: {
            
        }
    })
</script>

</html>
</script>
Vue 基础
模板语法

直接取值

{{ 属性 }}

需要解析标签,防止XSS、CSRF攻击

<div v-html=""></div>

表达式

<img v-bind:src="imgSrc"></img>
或者简写
<img :src="imgSrc"></img>

条件

v-if : 从 dom 中删除
v-else-if :
v-else
v-show :只是不在页面显示

列表

v-for="todo in todos"
v-for="(todo,index) in todos" : index 为索引值
或者
v-for="todo of todos"
v-for="(todo,index) of todos"

事件

v-on:click 或者 @click
v-model : 实现表单输入和应用状态之间的双向绑定。可以代替输入框value

class 与 style

绑定HTML Class

|----对象语法
|----数组语法

绑定内联样式

|----对象语法
|----数组语法

数组更新检测

使用以下方法操作数组,可以检测变动

push()、pop()、shift()、unshift()、splice()、sort()、reverse()
1
filter() concat() 和 slice() map(),不会检测变动,可以使用新数组替旧数组

输入框事件

事件对象

@input="handleInput"

handleInput(ev){
// ev 表示事件对象
console.log(ev)
// 输入框的值
console.log(ev.target.value)
}

事件对象和传参

@input="handleInput($event, param)"

handleInput(ev, param){
// ev 表示事件对象
console.log(ev)
console.log(ev.data)
}

多选框

v-model 使用数组,value 表示对应的标识

获取 v-model 绑定的值即可获取多选的值

<input type="checkbox" v-model="checkedGroup" value="vue"> vue
<input type="checkbox" v-model="checkedGroup" value="react"> react
<input type="checkbox" v-model="checkedGroup" value="jquery"> jquery

new Vue({
el: "#box",
data: {
checkedGroup: []
}
})

单选框

v-model 使用字符串,value 表示对应的标识,name 标识一组单选

获取 v-model 绑定的值即可获取单选的值

<input type="radio" v-model="picked" name="favor" value="vue">vue
<input type="radio" v-model="picked" name="favor" value="react">react
<input type="radio" v-model="picked" name="favor" value="query">query

Axios 请求
参考链接:https://github.com/axios/axios

计算属性
调用不能使用小括号,必须有返回值。写起来像方法,用起来是属性;

计算属性当属性值发生改变的时候,会自动重新计算属性值,并渲染到页面上;

watch 监听
监听某一个值发生变化,和改变之后需要如何处理

mixins 混入

引入js,同名方法优先级低于 methods

new Vue({
mixins: [funUtils]
})

生命周期
组件注册方式
组件作用域隔离;组件只能有另一个根节点;

全局组件
data 必须是函数式写法,必须有返回值

Vue.component("", {})

局部组件
Vue.component("common", {
components:{
"localComponents":{
// 局部组件,该组件只供common组件使用
}
}
})

通信
父传子通信
通过 Prop 向子组件传递数据:不限制类型

父组件在调用子组件的时候赋值

<div id="commucation">
<p>父组件</p>
// 父传子通信,如果动态传值可以对 param 使用 v-bind 绑定
<child param="君不见黄河之水天上来"></child>
</div>

子组件通过 props 属性获取父组件的传参

Vue.component("child", {
template:
<nav> <span style="background: yellow">子组件</span> <br> {{ param }} </nav>,
// props:["param"]
// 属性验证
props:{
param:String
}
})

完整示例

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
</head>
<body>
<div id="commucation">
<p>父组件</p>
<child param="君不见黄河之水天上来"></child>
</div>
</body>

<script type="text/javascript"> 
    // 组件之间互不影响,没有任何关联,但是可以通信
    // 子组件
    Vue.component("child", {
        template:
        `
        <nav>   
            <span style="background: yellow">子组件</span>
            <br>
            {{ param }}
         </nav>
        `,
        // props:["param"]
        // 属性验证
        props:{
            param:String
        }
    })

    // 父组件
    let vm = new Vue({
        el: "#commucation"
    })
</script>

</html>

子传父通信
通过事件通知父组件

子组件通过事件通知父组件调用子组件时绑定的事件

childClick(){
console.log("子组件点击调用")
// 使用 this.emit 通知父组件的中调用子组件标签中的事件,1000 为参数 this.emit("noticeevent", 1000);
}

父组件在调用子组件的时候绑定事件,并指定父组件中接收参数的函数

调用子组件

<div id="commucation">
<p>父组件</p>
<child @noticeevent="getChildParam"></child>
</div>

接收参数的函数

// 父组件
let vm = new Vue({
el: "#commucation",
methods:{
// data 为子组件传的参数
getChildParam(data){
console.log("data", data)
}
}
})

完整示例

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
</head>
<body>
<div id="commucation">
<p>父组件</p>
<child @noticeevent="getChildParam"></child>
</div>
</body>

<script type="text/javascript"> 
    // 组件之间互不影响,没有任何关联,但是可以通信
    // 子组件
    Vue.component("child", {
        template:
        `
        <nav>   
            <span style="background: yellow">子组件</span>
            <br>
            <button @click="childClick()">子组件click</button>
            <br>
        </nav>
        `,
        methods:{
            childClick(){
                console.log("子组件点击调用")
                // 通知父组件的中调用子组件标签中的事件
                this.$emit("noticeevent", 1000);
            }
        }
    })

    // 父组件
    let vm = new Vue({
        el: "#commucation",
        methods:{
            getChildParam(data){
                console.log("data", data)
            }
        }
    })
</script>

</html>

refs 通信
ref 绑定在标签上, this.refs 获取原生标签; ref 绑定在组件上, this.refs 获取时组件对象;
ref 绑定在标签上
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
</head>
<body>
<div id="commucation">
<input type="text" ref="name"/>
<button type="button" @click="getDom">GET</button>
</div>
</body>

<script type="text/javascript">         
    // 父组件
    let vm = new Vue({
        el: "#commucation",
        methods:{
            getDom(){
                // this.$refs 获取所有ref
                // this.$refs.name 获取ref值为name的节点
                // this.$refs.name.value 获取ref值为name节点的值
                console.log("获取的值为:", this.$refs.name.value)
            }
        }
    })
</script>

</html>

ref 绑定在组件上
父传子
父组件通过 ref 绑定调用子组件的调用标签,通过 this.r e f s . c h i l d C o m p o n e n t ( c h i l d C o m p o n e n t 指 定 的 是 父 组 件 调 用 子 组 件 绑 定 的 r e f 值 ) 获 取 子 组 件 , 通 过 t h i s . refs.childComponent (childComponent指定的是父组件调用子组件绑定的ref值)获取子组件,通过 this.refs.childComponent(childComponent指定的是父组件调用子组件绑定的ref值)获取子组件,通过this.refs.childComponent.getParent(params) 调用子组件的函数

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
</head>
<body>
<div id="commucation">
<p>父组件</p>
<input type="text" ref="inputVal"/>
<button type="button" @click="transferVal">通过refs传值给子组件</button>
<child ref="childComponent"></child>
</div>
</body>

<script type="text/javascript"> 
    // 组件之间互不影响,没有任何关联,但是可以通信
    // 子组件
    Vue.component("child", {
        template:
        `
        <nav>   
            <span style="background: yellow">子组件</span>
            <br>
        </nav>
        `,
        methods:{
            getParent(data){
                console.log("获取父组件的值为:", data)
            }
        }
    })

    // 父组件
    let vm = new Vue({
        el: "#commucation",
        methods:{
            transferVal(){
                console.log("this.$refs.inputVal.value", this.$refs.inputVal.value);
                let params = this.$refs.inputVal.value;
                // 获取ref绑定的子组件,并调用子组件的函数(可以传参)
                // this.$refs.childComponent 获取子组件
                // this.$refs.childComponent.getParent(params) 调用子组件的函数
                this.$refs.childComponent.getParent(params);
            }
        }
    })
</script>

</html>

bus 通信(简单的非父子通信)
发布订阅模式,通过同一个 vue 实例作为中间件中心

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
</head>
<body>
<div id="commucation">
<p>父组件</p>
<child1></child1>
<child2></child2>
</div>
</body>

<script type="text/javascript"> 
    // 创建一个 vue 实例,作为中央事件总线
    let bus = new Vue();

    // 子组件 1
    Vue.component("child1", {
        template:
        `
        <nav>   
            <span style="background: yellow">子组件 1</span>
            <button @click="transferData()">transfer</button>
        </nav>
        `,
        methods:{
            transferData(){
                console.log("开始输出数据");
                // 通知dataMount事件
                bus.$emit("dataMount", "君不见黄河之水天上来")
            }
        }
    })

    // 子组件 2
    Vue.component("child2", {
        template:
        `
        <nav>   
            <span style="background: red">子组件 2</span>
            <br>
        </nav>
        `,
        mounted() {
            // 监听dataMount事件
            bus.$on("dataMount", (data)=>{
                console.log("the data is ", data);
            })
        }
    })

    // 父组件
    let vm = new Vue({
        el: "#commucation"
    })
</script>

</html>

Vuex
import Vue from 'vue';
import Vuex from 'vuex';

Vue.use(Vuex);

export default new Vuex.Store({
state: {
// 共享状态
},
mutations: {
// 用于修改共享状态
},
actions: {
// ajax 异步请求调用 mutations 中的函数,修改共享状态
},
});

// 其他vue组件通过 "this.$store.state.共享状态属性" 进行访问

动态组件

<component :is=""></component>


<keep-alive>
<component :is=""></component>
</keep-alive>

slot 插槽
插槽是混合父组件的内容混到子组件中

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
</head>
<body>
<div id="commucation">
<p>父组件</p>
<child>

<ul>
<li>11111111</li>
<li>22222222</li>
<li>33333333</li>
</ul>
</child>
</div>
</body>

<script type="text/javascript"> 
    // 子组件 2
    Vue.component("child", {
        template:
        `
            <nav>   
                <div>子组件</div>
                <!--slot插槽:混合父组件的内容混到子组件中-->
                <slot></slot>
            </nav>
        `
    })
    
    // 父组件
    let vm = new Vue({
        el: "#commucation"
    })
</script>

</html>

具名插槽
插槽具有名字,可以使用name属性指定使用插槽的位置

父组件使用 slot 属性指定插槽名称

子组件使用 <slot name=""> 指定slot名称

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
</head>
<body>
<div id="commucation">
<p>父组件</p>
<child>

<div slot="slot1">aaaaa</div>
<div slot="slot2">bbbbb</div>
<div slot="slot3">ccccc</div>
</child>
</div>
</body>

<script type="text/javascript"> 
    // 子组件 2
    Vue.component("child", {
        template:
        `
            <nav>   
                <div>子组件</div>
                <!--slot插槽:混合父组件的内容混到子组件中, name指定插槽名称-->
                <div style="background: red">
                    <slot name="slot1"></slot>
                </div>
                <div style="background: yellow">
                    <slot name="slot2"></slot>
                </div>
                <div style="background: blue">
                    <slot name="slot3"></slot>
                </div>
            </nav>
        `
    })
    
    // 父组件
    let vm = new Vue({
        el: "#commucation"
    })
</script>

</html>

动画
推荐:https://github.com/daneden/animate.css

使用方式:

<div id="commucation">

<p class="animated bounceIn"> 君不见黄河之水天上来 </p>
</div>

轮播/滑动效果
推荐:https://www.swiper.com.cn/

指令
指令不在 Vue 实例中

指令可以传js对象

<div v-demo="{ color: 'white', text: 'hello!' }"></div>
1
指令具有生命周期

// 注册一个全局自定义指令 v-focus
Vue.directive('focus', {
// 当被绑定的元素插入到 DOM 中时……
inserted: function (el,binding) {
// el 是原生节点,binding 表示标签值
// 聚焦元素
el.focus()
}
})

过滤器
自定义过滤器

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
</head>
<body>
<div id="commucation">
{{name | msgFilter}}
</div>
</body>

<script type="text/javascript">
    let vm = new Vue({
        el: "#commucation",
        data:{
            name: "君不见黄河之水天上来"
        },
        filters:{
            msgFilter: function(value){
                console.log("value", value)
                // 处理数据
                return value.split('之')[1];
            }
        }
    })
</script>

</html>

路由
路由容器
<router-view name=""></router-view>
1
hash 路由

location.hash 切换
window.onhashchange 监听路径的切换
1
2
history 路由

// 路径没有 #
const router = new Router({
mode : "history",
})

history.pushState 切换
window.onpopstate 监听路径的切换

嵌套路由
import Vue from 'vue'
import Router from 'vue-router'
import Home from './views/Home.vue'

// 注册路由模块
Vue.use(Router)

export default new Router({
mode: 'history',
base: process.env.BASE_URL,
routes: [
{
path: '/',
name: 'home',
alias: "/index", // 别名
component: Home,
children:[
{
path: '/',
name: 'home',
component: Home,
}
]
},
// 重定向
{
path: '/li',
name: 'li',
redirect: "/about"
}
]
})

动态路由配置
{
# 使用 :id 做动态路由配置,: 是做一个占位符
path: '/detail/:id1/:id2/:id3',
name: 'home'
component: Detail
}

编程式路由

路径跳转

this.$router.push(/path/{id})

路由名称跳转

this.$router.push({name:"",params:{}})

声明式路由

<router-link>

获取hash值

获取当前路由

let hashVal = location.hash

获取当前路由信息

this.$route

路由守卫
全局守卫
在 router.js 配置

router.befaoreEach((to, from, next) => {
if(to.path === '/center'){
// 拦截判断
if(usre.isLogin()){
// 有登录信息,可以访问
next();
}else{
// 无登录信息,需要登录
next('/login')
}
}else{
// 允许过去
next();
}
})

Vuex
管理共享状态——解决非父子通信
数据快照——缓存后端数据,避免重复请求,影响用户体验
时光旅行——调式

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,992评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,212评论 3 388
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,535评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,197评论 1 287
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,310评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,383评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,409评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,191评论 0 269
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,621评论 1 306
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,910评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,084评论 1 342
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,763评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,403评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,083评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,318评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,946评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,967评论 2 351