Vue学习笔记

目录

1.搭建项目

2.如何使用Vue实例

2.1从HTML  中得到视图

2.2用js构建视图

2.3vue-loader

3.Vue的options属性

入门属性

options.data 深入理解

Vue.set和this.$set

data中有数组

进阶属性

computed和watch

绑定属性

绑定事件

条件判断

循环

显示、隐藏

修饰符

directive指令-减少DOM操作的重复

mixin指令-减少data、methods、钩子的重复(mixin可以理解为复制)

extends继承 减少重复,和mixin基本一样,比mixin更抽象的封装

provide、inject(提供、注入)

vue表单和v-model

4.其他

路由和动画暂时不写了,基本上文档上都有。

正则表达式三十分钟速学,可以了解。


1.搭建项目

使用Vue/cli工具

安装:

npm install -g @vue/cli
# OR
yarn global add @vue/cli

查看安装版本:

vue --version

运行以下命令来创建一个新项目:

vue create hello-world

浏览器实时预览:

yarn serve

2.如何使用Vue实例

详看文档

2.1从HTML  中得到视图

从CDN中应用vue.js或vue.min.js 即可做到。

2.2用js构建视图

使用vue.runtime.js,这种方法不方便但是体积小,用户体验更好,要麻烦就麻烦在开发者这边,用户体验第一。

2.3vue-loader

.vue文件翻译成h构建方法

但是HTML只有一个div#app,SEO不友好。

3.Vue的options属性

封装:const vm = new Vue(options)

options五类属性:数据、DOM、生命周期钩子、资源、其他。

入门属性

  • el-挂载点

与$mount有替换关系

  • data-内部数据

支持对象和函数,优先使用函数(*避免两个或多个组件共用data的问题,使用函数是每次调用data得到一个data)

new Vue({
    data(){
        return{
            n:0
        }
    },
    template:`
    <div class="red">
        {{n}}
        <button @click="add">+1</button>
    </div>
    `,
    methods: {
        add(){
            this.n += 1 
        }
    }
}).$mount(#'app')
  • methods-方法

事件处理函数或者普通函数

  • components

Vue组件,注意大小写。

推荐引入方式:

import Demo from './Demo.vue'            //其他组件引入

new Vue({
    components: {
        Frank:Demo                      //老手这样写  Demo:Demo 缩写为Demo
    }
    data(){
        return{
            n:0
        }
    },
    template:`
    <div class="red">
        {{n}}
        <button @click="add">+1</button>
        <Frank/>                         //<Demo/>
    </div>
    `,
    methods: {
        add(){
            this.n += 1 
        }
    }
}).$mount(#'app')
  • 四个钩子
  • created-实例出现在内存中
  • mounted-实例出现在页面中
  • update-实例更新了
  • destroyed-实例消亡了

props-外部属性

main.js文件:

import Demo from './Demo.vue'
 new Vue({
    components:{Demo},
    data(){
        return{
            n:0
        }
    },
    template:`
    <div>
        {{n}}
        <Demo :message="n" :fn="add"/>
    </div>
    `,
    methods: {
        add(){
            this.n += 1 
        }
    }
}).$mount(#'app')

Demo.vue组件:

<template>
    <div>
        这里是Demo内部
        {{message}}
        <button @clink='fn'>call fn</button>
    </div>
</template>

<script>
 export default {
     props: ['message','fn']
 }
</script>

<style scoped>
 .red{
  color:red   
 }
</style>

options.data 深入理解

  • get和set
let obj0 = {
  姓: "高",
  名: "圆圆",
  age: 18
};

// 需求一,得到姓名

let obj1 = {
  姓: "高",
  名: "圆圆",
  姓名() {
    return this.姓 + this.名;
  },
  age: 18
};

console.log("需求一:" + obj1.姓名());
// 姓名后面的括号能删掉吗?不能,因为它是函数
// 怎么去掉括号?

// 需求二,姓名不要括号也能得出值

let obj2 = {
  姓: "高",
  名: "圆圆",
  get 姓名() {
    return this.姓 + this.名;
  },
  age: 18
};

console.log("需求二:" + obj2.姓名);

// 总结:getter 就是这样用的。不加括号的函数,仅此而已。

// 需求三:姓名可以被写

let obj3 = {
  姓: "高",
  名: "圆圆",
  get 姓名() {
    return this.姓 + this.名;
  },
  set 姓名(xxx){
    this.姓 = xxx[0]
    this.名 = xxx.slice(1)
  },
  age: 18
};

obj3.姓名 = '高媛媛'

console.log(`需求三:姓 ${obj3.姓},名 ${obj3.名}`)

// 总结:setter 就是这样用的。用 = xxx 触发 set 函数
let data0 = {
  n: 0
}

// 需求一:用 Object.defineProperty 定义 n
let data1 = {}

Object.defineProperty(data1, 'n', {
  value: 0
})

console.log(`需求一:${data1.n}`)

// 总结:这煞笔语法把事情搞复杂了?非也,继续看。

// 需求二:n 不能小于 0
// 即 data2.n = -1 应该无效,但 data2.n = 1 有效

let data2 = {}

data2._n = 0 // _n 用来偷偷存储 n 的值

Object.defineProperty(data2, 'n', {
  get(){
    return this._n
  },
  set(value){
    if(value < 0) return
    this._n = value
  }
})

console.log(`需求二:${data2.n}`)
data2.n = -1
console.log(`需求二:${data2.n} 设置为 -1 失败`)
data2.n = 1
console.log(`需求二:${data2.n} 设置为 1 成功`)

// 抬杠:那如果对方直接使用 data2._n 呢?
// 算你狠

// 需求三:使用代理

let data3 = proxy({ data:{n:0} }) // 括号里是匿名对象,无法访问

function proxy({data}/* 解构赋值,别TM老问 */){
  const obj = {}
  // 这里的 'n' 写死了,理论上应该遍历 data 的所有 key,这里做了简化
  // 因为我怕你们看不懂
  Object.defineProperty(obj, 'n', { 
    get(){
      return data.n
    },
    set(value){
      if(value<0)return
      data.n = value
    }
  })
  return obj // obj 就是代理
}

// data3 就是 obj
console.log(`需求三:${data3.n}`)
data3.n = -1
console.log(`需求三:${data3.n},设置为 -1 失败`)
data3.n = 1
console.log(`需求三:${data3.n},设置为 1 成功`)

// 杠精你还有话说吗?
// 杠精说有!你看下面代码
// 需求四

let myData = {n:0}
let data4 = proxy({ data:myData }) // 括号里是匿名对象,无法访问

// data3 就是 obj
console.log(`杠精:${data4.n}`)
myData.n = -1
console.log(`杠精:${data4.n},设置为 -1 失败了吗!?`)

// 我现在改 myData,是不是还能改?!你奈我何
// 艹,算你狠

// 需求五:就算用户擅自修改 myData,也要拦截他

let myData5 = {n:0}
let data5 = proxy2({ data:myData5 }) // 括号里是匿名对象,无法访问

function proxy2({data}/* 解构赋值,别TM老问 */){
  // 这里的 'n' 写死了,理论上应该遍历 data 的所有 key,这里做了简化
  // 因为我怕你们看不懂
  let value = data.n
  Object.defineProperty(data, 'n', {
    get(){
      return value
    },
    set(newValue){
      if(newValue<0)return
      value = newValue
    }
  })
  // 就加了上面几句,这几句话会监听 data

  const obj = {}
  Object.defineProperty(obj, 'n', {
    get(){
      return data.n
    },
    set(value){
      if(value<0)return//这句话多余了
      data.n = value
    }
  })
  
  return obj // obj 就是代理
}

// data3 就是 obj
console.log(`需求五:${data5.n}`)
myData5.n = -1
console.log(`需求五:${data5.n},设置为 -1 失败了`)
myData5.n = 1
console.log(`需求五:${data5.n},设置为 1 成功了`)


// 这代码看着眼熟吗?
// let data5 = proxy2({ data:myData5 }) 
// let vm = new Vue({data: myData})

// 现在我们可以说说 new Vue 做了什么了

Object.defineProperty

  • 可以给对象添加属性 style
  • 可以给对象添加getter/setter
  • getter/setter用于对属性的读写进行监控

Vue的data是响应式,Vue2通过Object.defineProperty来实现数据响应式

Vue.set和this.$set

  • 新增key
  • 自动创建代理和监听(如果没有创建过),作用于数组时不会自动监听。
  • 出发ui更新(不会立刻更新)

举例:

this.$set(this. object,'m',100)

data中有数组

可以用this.array.push(),push   API自带set属性

详情可以参考尤雨溪官方文档

进阶属性

computed和watch

computed-计算属性

  • 不需要加括号
  • 他会根据依赖是否变化来缓存

示例:

用 computed 筛选男女

// 引用完整版 Vue
import Vue from "vue/dist/vue.js";

Vue.config.productionTip = false;
let id = 0;
const createUser = (name, gender) => {
  id += 1;
  return { id: id, name: name, gender: gender };
};
new Vue({
  data() {
    return {
      users: [
        createUser("方方", "男"),
        createUser("圆圆", "女"),
        createUser("小新", "男"),
        createUser("小葵", "女")
      ],
      displayUsers: []
    };
  },
  created() {
    this.displayUsers = this.users;
  },
  methods: {
    showMale() {
      this.displayUsers = this.users.filter(u => u.gender === "男");
    },
    showFemale() {
      this.displayUsers = this.users.filter(u => u.gender === "女");
    },
    showAll() {
      this.displayUsers = this.users;
    }
  },

  template: `
    <div>
      <div>
      <button @click="showAll">全部</button>
      <button @click="showMale">男</button>
      <button @click="showFemale">女</button></div>
      <ul>
        <li v-for="(u,index) in displayUsers" :key="index">{{u.name}} - {{u.gender}}</li>
      </ul>
      
    </div>
  `
}).$mount("#app");

用 computed 筛选男女

// 引用完整版 Vue
import Vue from "vue/dist/vue.js";

Vue.config.productionTip = false;
let id = 0;
const createUser = (name, gender) => {
  id += 1;
  return { id: id, name: name, gender: gender };
};
new Vue({
  data() {
    return {
      users: [
        createUser("方方", "男"),
        createUser("圆圆", "女"),
        createUser("小新", "男"),
        createUser("小葵", "女")
      ],
      gender: ""
    };
  },
  computed: {
    displayUsers() {
      const hash = {
        male: "男",
        female: "女"
      };
      const { users, gender } = this;
      if (gender === "") {
        return users;
      } else if (typeof gender === "string") {
        return users.filter(u => u.gender === hash[gender]);
      } else {
        throw new Error("gender 的值是意外的值");
      }
    }
  },
  methods: {
    setGender(string) {
      this.gender = string;
    }
  },

  template: `
    <div>
      <div>
      <button @click="setGender('') ">全部</button>
      <button @click="setGender('male')">男</button>
      <button @click="setGender('female')">女</button></div>
      <ul>
        <li v-for="(u,index) in displayUsers" :key="index">{{u.name}} - {{u.gender}}</li>
      </ul>
      
    </div>
  `
}).$mount("#app");

watch-监听

  • 一旦data发生变化就会执行函数
  • options.watch用法
  • this.$watch用法
  • deep,immediate含义

示例:实现撤销功能

// 引用完整版 Vue,方便讲解
import Vue from "vue/dist/vue.js";

Vue.config.productionTip = false;

new Vue({
  data: {
    n: 0,
    history: [],
    inUndoMode: false
  },
  watch: {
    n: function(newValue, oldValue) {
      console.log(this.inUndoMode);
      if (!this.inUndoMode) {
        this.history.push({ from: oldValue, to: newValue });
      }
    }
  },
  // 不如用 computed 来计算 displayName
  template: `
    <div>
      {{n}}
      <hr />
      <button @click="add1">+1</button>
      <button @click="add2">+2</button>
      <button @click="minus1">-1</button>
      <button @click="minus2">-2</button>
      <hr/>
      <button @click="undo">撤销</button>
      <hr/>

      {{history}}
    </div>
  `,
  methods: {
    add1() {
      this.n += 1;
    },
    add2() {
      this.n += 2;
    },
    minus1() {
      this.n -= 1;
    },
    minus2() {
      this.n -= 2;
    },
    undo() {
      const last = this.history.pop();
      this.inUndoMode = true;
      console.log("ha" + this.inUndoMode);
      const old = last.from;
      this.n = old; // watch n 的函数会异步调用
      this.$nextTick(() => {   //可以理解为setTimeout
        this.inUndoMode = false;
      });
    }
  }
}).$mount("#app");

deep:

deep意思是监听object的时候是否往深了看。

示例:object.a变了,object算不算也变了。需要答案是变了,deep:true;需要答案是不变,deep:false。

// 引用完整版 Vue,方便讲解
import Vue from "vue/dist/vue.js";

Vue.config.productionTip = false;

new Vue({
  data: {
    n: 0,
    obj: {
      a: "a",
      b: "b"
    }
  },
  template: `
    <div>
      <button @click="n += 1">n+1</button>
      <button @click="obj.a += 'hi'">obj.a + 'hi'</button>
      <button @click="obj = {a:'a'}">obj = 新对象</button>
    </div>
  `,
  watch: {
    n() {
      console.log("n 变了");
    },
    obj: {
      handler(){
        console.log("obj 变了");
      },
      deep:true
    },
  
  }
}).$mount("#app");

语法:vm.$watch('xxx', fn, {deep: .., immediate: ..},其中‘xxx’可以改为一个返回字符串的函数。

watch禁止使用箭头函数,this为全局对象window或global

watch:{

        n:()=>{

                this.xxx

        }

}

看文档学习watch

面试题:computed和watch区别

  • computed是计算属性,watch是监听的意思。
  • computed计算出一个值,这个值被调用的时候不需要加括号,根据依赖会自动缓存,依赖不变的话就不会重新计算。
  • watch 中 immediate-第一次渲染的时候是否要执行这个函数,deep-监听对象是否看里边的属性的变化。某个属性变化了就执行一个函数。

绑定属性

  • v-bind

<img v-bind:src='x'>绑定src =>简写为 <img :src='x'>

绑定对象:

<div :style="{border:;'px solid red',height:100}">这里的100px可以写成100</div>

绑定事件

  • v-on:事件名

缩写<button @click="add">+1</button>

条件判断

  • v-if
<div v-if="x>0">
x大于0
</div>
<div v-else-if="x===0">
x=0
</div>
<div v-else>
x小于0
</div>

循环

  • v-for 后边注意加 :key
<ul>
    <li v-for="(value,name) in obj" :key="name">
    属性名:{{name}},属性值{{value}}
    </li>
</ul>

显示、隐藏

  • v-show
<div v-show="n%2===0"> n 是偶数</div>

修饰符

官方文档学习

.sync修饰符

Vue 规则:组件不能修改 props 外部数据
Vue 规则:this.$emit 可以触发事件,并传参 
Vue 规则:$event 可以获取 $emit 的参数

示例学习:

App.vue:

<template>
  <div class="app">
    App.vue 我现在有 {{total}}
    <hr>
    <Child :money.sync="total"/>
//逻辑为 <Child :money="total" v-on:update:money="total=$event"/> 简写成了.sync,实际是个语法糖
  </div>
</template>

<script>
import Child from "./Child.vue";
export default {
  data() {
    return { total: 10000 };
  },
  components: { Child: Child }
};
</script>

<style>
.app {
  border: 3px solid red;
  padding: 10px;
}
</style>

Child.vue:

<template>
  <div class="child">
    {{money}}
    <button @click="$emit('update:money', money-100)">
      <span>花钱</span>
    </button>
  </div>
</template>

<script>
export default {
  props: ["money"]
};
</script>


<style>
.child {
  border: 3px solid green;
}
</style>

directive指令-减少DOM操作的重复

文档学习

mixin指令-减少data、methods、钩子的重复(mixin可以理解为复制)

mixin的代码链接示例,可以学习参考一下

extends继承 减少重复,和mixin基本一样,比mixin更抽象的封装

provide、inject(提供、注入)

作用:大范围的data和methods等共用。

代码示例,参考学习。

vue表单和v-model

文档学习,很详细

基本用法:input/textarea/checkbox/radio/select/form

修饰符:.lazy/.number/.trim

v-model:面试官问Vue的双向绑定,其实就是在问v-model
但是实际上v-model是v-bind:value和v-on:input的语法糖

4.其他

路由和动画暂时不写了,基本上文档上都有。

正则表达式三十分钟速学,可以了解。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值