Skip to content

01 Vue基本

javascript
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <div id="app">
        <h2>{{ msg }}</h2>
    </div>
   <!-- <script src="https://cdn.jsdelivr.net/npm/vue@2.7.14/dist/vue.js"></script> -->
   <script src="./vue.js"></script>
   <script>
    // 实例vm  
    // MVVM :  
    // 1. M Model data中的数据
    // 2. V View 视图,展示在页面上html结构
    // 3. VM  ViewModel 把它当做Vue实例 
    const vm = new Vue({
        // 不建议data写成对象
        // data:{
        //     msg:'你好呀,下午好'
        // },
        // data:function(){
        //     return {
        //         msg:'yo'
        //     }
        // },
        // data存放数据变量的,要写成一个函数
        data(){
            return {
                msg:'yohuohuo'
            }
        }
        // el:'#app',
  
        // 1. 如果有template,会以template模板的内容挂载到HTML上
        // 2. 如果没有template,会直接以#app这个节点作为模板展示内容
  
        // template:'<div>{{ msg }}</div>'
    })

    // 3秒之后显示这个模板 
    setTimeout(function(){
        // mount 就是挂载的意思,把模板挂载到#app节点上
        vm.$mount('#app')
    }, 1000)
   </script>
</body>
</html>

02 插值语法

javascript
<div id="app">
    <h2>{{ msg }}</h2>
    {{ msg2 }}
    <!-- {{ demo }} -->
    <!-- 3. 属性值不能写插值语法 -->
    <!-- <div class="{{ color }}"></div> -->
    <div v-bind:class="color"></div>
    <div :class="color"></div>
</div>
<script src="./vue.js"></script>
<script>
    const vm = new Vue({
        el:'#app',
        data(){
            return {
                msg:'我是msg',
                // 1. 插值语法,需要注意,标签会当做普通文本解析
                // 2. {{}} 中的变量,一定要在data中存在,不存在,会报错
                // 3. 标签的属性上,不能使用{{}} ,也会报错
                msg2:'<p>123</p>',
                color:'red'
            }
        }
    })
</script>

03 v-bind注意事项

javascript
    <div id="app">
        <div v-bind:class="msg"></div>
        <!-- 1. : v-bind   msg ==> 变量,需要再data中去寻找这个变量 -->
        <div :class="msg"></div>
        <!-- 2. 不加冒号    msg 是一个普通的字符串,写死的 -->
        <div class="msg"></div>
    </div>
    <script>
        // v-bind 让标签的某些属性和我们data中的数据做一个绑定
        // 绑定:有了相互的关系,数据变化了,属性值也会改变
    </script>
    <script src="./vue.js"></script>
    <script>
        const vm = new Vue({
            el:'#app',
            data(){
                return {
                    msg:'我是msg',
                }
            }
        })
    </script>

04 v-on 注册事件

javascript
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <div id="app">
        <button @click="count++">{{ count }}</button>
        <button @click="addCount">{{ num }}</button>

        <h2>{{ money }}</h2>
        <button @click="eat('建国')">请建国吃饭</button>
        <button @click="eat('海龙')">请海龙吃饭</button>
    </div>
    <script src="./vue.js"></script>
    <script>
        // 1. v-on 注册事件
        // 2. 语法:
        //    1. v-on:事件名 = 要执行的少量代码
        //    2. v-on:事件名 = methods中的函数
        //    3. v-on:事件名 = methods中函数名(传参1,传参2...)

        // 3. v-on 简写 @ 

        new Vue({
            el:'#app',
            data(){
                return {
                    count:100,
                    num:1000,
                    money:500
                }
            },
            methods:{
                addCount(){
                    this.num++
                },
                eat(person){
                    if(person === '建国'){
                        this.money -= 10
                    }
                    if(person === '海龙'){
                        this.money -= 100
                    }
                }
            }
        })
    </script>
</body>
</html>

04 组件的注册

javascript
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <div id="app">
        <button-counter></button-counter>

        <h2>我是局部组件</h2>
        <component-a></component-a>
    </div>
    <script src="./vue.js"></script>
    <script>
        // 定义一个名为 button-counter 的新组件
        // 1. 先注册组件
        // Vue.component 是一个全局组件
        Vue.component('button-counter', {
            data () {
                return {
                    count: 0
                }
            },
            template: '<button v-on:click="count++">You clicked me {{ count }} times.</button>'
        })

        
        // 2。 局部注册组件
      	// 通过一个普通的对象来注册组件。。 ===> .vue单文件组件
        const componentA = {
            data(){
                return {
                    num:100
                }
            },
            // 当前这个组件的结构 tempalte中只有一个根标签
            template: `
            <div>
                <button-counter></button-counter>
                <button @click=num++>{{ num }}</button>
            </div>

            `
        }

        // 组件:组件就是页面上的一个部分,一个模块
        // 可以包含 html / js / css
        const vm = new Vue({
            el:'#app',
            data(){
                return {
                    count:100,
                    msg:'我是msg',
                }
            },
            components:{
                // components 左边的key就是我们要使用的组件名
                'component-a': componentA
            }
        })



    </script>
</body>
</html>

05 创建Vue项目

javascript
Vue create vue-demo
  • package.json
javascript
"start": "vue-cli-service serve",
// npm run start  ==> 如果是start ,可以简写为 npm start 
// yarn start
全局注册组件
javascript
创建一个 GlobalDemo
vue
<template>
  <!-- 只能有一个根标签 -->
  <div>
    <h2>{{ msg }}</h2>
  </div>
</template>

<script>
  export default {
    data(){
      return {
        msg:'我是全局注册的组件'
      }
    }
  }
</script>

<style>

</style>
javascript
import Vue from 'vue'
import App from './App.vue'

// 1. 导入 import
import GobalDemo from './components/GlobalDemo.vue'

Vue.config.productionTip = false

// 2. 全局注册 左边是组件名,右边是组件对象
//  ---> 使用的时候,可以短横线   global-demo
Vue.component('GlobalDemo', GobalDemo)

new Vue({
  render: h => h(App),
}).$mount('#app')

06 终端报错

7635383b-92b1-49e4-88a4-81f977303489.png 右键以管理员身份运行 image.png

javascript
set-ExecutionPolicy RemoteSigned

07 nrm

javascript
npm i nrm -g 全局安装

// 1. nrm ls 查看资源地址
// 2. nrm test 测试下载速度
// 3. nrm use taobao  使用淘宝镜像安装

08 组件注册建议驼峰命名

  1. 组件名,多单词
  2. 组件名建议大驼峰
javascript
// 1. 导入 import
import GobalDemo from './components/GobalDemo.vue'

Vue.config.productionTip = false

// 2. 全局注册
// 1. 这里注册的名字,如果都是驼峰大写,在组件内使用的时候,
// 可以大写,也可以中横线

// 2. 如果这里写短横线的形式,组件内使用,只能是短横线

// ===>  推荐 :命名 驼峰大写
Vue.component('GlobalDemo', GobalDemo)

09 局部注册组件

javascript
<template>
  <div>
    <button>{{ msg }}</button>
  </div>
</template>

<script>
export default {
    data(){
        return {
            msg:'我是局部组件'
        }
    }
}
</script>

<style>

</style>
javascript
<template>
  <div id="app">
    <global-demo></global-demo>
    <!-- <GlobalDemo></GlobalDemo> -->
    <!-- 组件在.vue中使用的时候,三种都可以 -->
    <ButtonDemo></ButtonDemo>
    <button-demo></button-demo>
    <button-demo/>
  </div>
</template>

<script>
import ButtonDemo from './components/ButtonDemo.vue'


export default {
  name: 'App',
  components:{
    ButtonDemo
  }
}
</script>

10 计算属性

javascript
<template>
  <div>
    <h2>计算属性</h2>
    <div>{{ sum }}</div>
  </div>
</template>

<script>
export default {
    data(){
        return {
            num1 : 10,
            num2 : 12
        }
    },
    // computed这里是对象
    computed:{
        // sum是一个方法,但是当做属性来使用
        sum(){
            // this指向的是vue的实例
            return this.num1 + this.num2

            // 1. 计算属性是一个函数,这个函数要写return!!
            // 2. 当依赖的数据(num1,num2)改变的时候,sum的值也一起发生改变
            // 3. this指向的是vue的实例
            // 4. 使用的时候,不加括号,当做属性使用(和data中定义的数据一样,当做变量使用)
        }
    }
}
</script>

<style>

</style>

11 计算属性有缓存

javascript
<template>
  <div>
    <h2>计算属性</h2>
    <div>{{ sum }}</div>
    <div>{{ sum }}</div>
    <div>{{ sum }}</div>
    <div>{{ sum }}</div>
    <h3>这是方法调用</h3>
    <div>{{ sumFn() }}</div>
    <div>{{ sumFn() }}</div>
    <div>{{ sumFn() }}</div>
    <div>{{ sumFn() }}</div>
  </div>
</template>

<script>
export default {
    data(){
        return {
            num1 : 10,
            num2 : 12
        }
    },
    methods:{
        sumFn(){
            console.log('这是方法调用')
            return this.num1 + this.num2
        }
    },
    // computed这里是对象
    computed:{
        // sum是一个方法,但是当做属性来使用
        sum(){
            console.log('这是计算属性')
            // this指向的是vue的实例
            return this.num1 + this.num2

            // 1. 计算属性是一个函数,这个函数要写return!!
            // 2. 当依赖的数据(num1,num2)改变的时候,sum的值也一起发生改变
            // 3. this指向的是vue的实例
            // 4. 使用的时候,不加括号,当做属性使用(和data中定义的数据一样,当做变量使用)
        }
    }
}
  // ===> 
  // 1. 计算属性会缓存结果,只要依赖项不变,直接读取缓存
  // 2. 如果依赖项改变,重新计算并缓存最新的结果

  // 使用场景:
  // 1. 求和,求平均值等 
  // 2. 全选反选 
</script>

<style>

</style>

12 计算属性高级写法

当我们需要修改计算属性的时候,使用 set

javascript
<template>
  <div>
    姓<input type="text" v-model="firstName">
    名<input type="text" v-model="lastName">
    
    <h2>{{ fullName }}</h2>
    <button @click="changeName">改变名字</button>
  </div>
</template>

<script>
export default {
    data(){
        return {
            firstName:'小野',
            lastName:'太郎'
        }
    },
    methods:{
        changeName(){
            console.log(111)
            this.fullName = '罗广-太君'
        }
    },
  computed: {
    // 如果要修改计算属性
    // fullName () {
    //   return this.firstName + '-' + this.lastName
    // },
    fullName:{
        // getter函数 --> 当我们读取fullName的时候
        get(){
            return this.firstName + '-' + this.lastName
        },
        set(newVal){
            // 我们需要基于修改的值,更新依赖项,依赖项更新,计算属性自然而然就会更新
            console.log(newVal)
            // 字符串转数组 
            const arr = newVal.split('-')

            this.firstName = arr[0]
            this.lastName = arr[1]
        }
    }
  }
}
</script>

<style>

</style>

12 watch侦听器

javascript
<template>
  <div>
    <h3>银行卡余额{{ money }}</h3>
    <button @click='money = money + 10000'>发工资</button>
    <button @click='money = money - 20'>干饭</button>
    <button @click='changeAge'>花花长了一岁</button>
    <button @click='changePerson'>他变了</button>
  </div>
</template>

<script>
export default {
    data(){
        return {
            money: 100,
            obj:{
                name:'花花', // 顶流女明星 大熊猫 panda
                age:3
            },
            // 监听这个人各个变化
            person:{
                name:'嫌疑犯',
                age:18,
                desc:'喜欢踩点,蹦迪,唱跳rap'
            }
        }
    },
    methods:{
        changeAge(){
            this.obj.age++
        },
        changePerson(){
            this.person.age++
        }
    },
    watch:{
        // 监听data中money改变
        // 1.1. 第一种写法
        money(newVal, oldVal){
            console.log('尊敬的Vip用户,你的余额变更为'+newVal, '原来是' + oldVal)
        },
        // 1.2. 第二种写法
        'money'(newVal, oldVal){
            console.log('尊敬的Vip用户,你的余额变更为'+newVal, '原来是' + oldVal)
        },

        // 2.监听对象中的某个值
        'obj.age'(newVal, oldVal){
            console.log(`花花的年龄现在是${newVal}, 原来是${oldVal}`)
        },

        // 3. 监听一个对象的所有属性,只要有一个变化了,就会触发
        person:{
            deep:true,
            immediate:true, // 一进入页面,首先执行一次
            // 对于复杂类型的监听,newVal和oldVal 会指向同一个对象,所以oldVal意义不大
            // handler(val, oldVal){
            //     console.log(val, oldVal)
            //     console.log(val === oldVal)
            // }
            handler(val){
                console.log(val)
            }
        }
        
    }
}
</script>

<style>

</style>

13 父组件给子组件传值

javascript
<template>
  <div id="app">
    <!-- 
      父组件,
      1. 父组件通过给子组件,添加标签属性传值
      2. 子组件props接收
     -->
     <h2>建国的黑店</h2>
    <!-- <my-product title='无敌猪肘子' price="199" desc="好吃极了" />
    <my-product title='爽口大西瓜' price="99" desc="忒甜了" />
    <my-product title='红烧大排骨' price="299" desc="贵死了" /> -->

    <!-- 加冒号和不加冒号的区别: 是否是动态绑定,动态绑定的意思就是使用的是data中的数据 -->
       
    <my-product v-for="item in list" :key="item.id"
        :title="item.title"
        :price="item.price"
     />
  </div>
</template>

<script>
import MyProduct from './components/MyProduct.vue'
// import ComputedAdvance from './components/ComputedAdvance.vue'
// import WatchDemo from './components/WatchDemo.vue'



export default {
  name: 'App',
  data(){
    return {
      list: [
        { id: 1, title: '无敌猪肘子', price: 188 },
        { id: 2, title: '爽口大西瓜', price: 360},
        { id: 3, title: '美味大闸蟹', price: 42}
    ]
    }
  },
  components:{
    // ComputedAdvanc,
    // WatchDemo,
    MyProduct
  }
}
</script>

子组件props接收

javascript
<template>
    <!-- 子组件 -->
    <div class="goods">
        <h3>{{title}}</h3>
        <p>{{price}}</p>
        <!-- <p>{{desc}}</p> -->
    </div>
</template>

<script>
export default {
    name:'MyProduct',
    props:['title', 'price', 'desc']
}
</script>

14 子组件给父组件传参

父组件 App.vue

javascript
<template>
  <div id="app">
    <!-- 
      父组件,
      1. 想要往子组件传参,添加标签属性传值
      2. 子组件props接收
     -->
     <h2>建国的黑店</h2>
    <!-- <my-product title='无敌猪肘子' price="199" desc="好吃极了" />
    <my-product title='爽口大西瓜' price="99" desc="忒甜了" />
    <my-product title='红烧大排骨' price="299" desc="贵死了" /> -->

    <!-- 加冒号和不加冒号的区别: 是否是动态绑定,动态绑定的意思就是使用的是data中的数据 -->
    <my-product v-for="item in list" :key="item.id"
        :title="item.title"
        :price="item.price"
        :desc="item.desc"
        @changePrice="handlePrice"
     />
    
  </div>
</template>

<script>
import MyProduct from './components/MyProduct.vue'
// import ComputedAdvance from './components/ComputedAdvance.vue'
// import WatchDemo from './components/WatchDemo.vue'



export default {
  name: 'App',
  data(){
    return {
      list: [
        { id: 1, title: '无敌猪肘子', price: 188 ,desc:'美味极了'},
        { id: 2, title: '爽口大西瓜', price: 360, desc:'爽歪歪'},
        { id: 3, title: '美味大闸蟹', price: 42, desc:'泰裤辣'}
    ]
    }
  },
  methods:{
    // changePrice(val){
    //   console.log(val)
    //   this.list[0].price -=  val
    // }
    handlePrice(price, id){
      const good = this.list.find(el => el.id === id) // 找到要修改的那个对象
      good.price -= price
    }
  },
  components:{
    // ComputedAdvanc,
    // WatchDemo,
    MyProduct
  }
}
</script>

子组件 MyProduct

javascript
<template>
    <!-- 子组件 -->
    <div class="goods">
        <h3>{{title}}</h3>
        <p>{{price}}</p>
        <p>{{desc}}</p>
        <button @click='cutPrice'>砍一刀</button>
    </div>
</template>

<script>
export default {
    name:'MyProduct',
    props:['title', 'price', 'desc'],
    methods:{
        cutPrice(){
            // 不能再子组件中去修改父组件穿过来的props值
            // 数据流向 ==> 从父组件,到子组件
            // this.price = this.price - 10

            //  如果自组件想要修改父组件传的数据
            // 怎么办呢,通知父组件,让父组件自己去修改这个数据
            // 1. 第一个参数,子组件自定义的事件名,这个事件会在组件注册监听
            // 2. 第二个参数,要传递给父组件的参数(信息)
            
            // 如果要给对应的那个对象砍一刀,可以给一个id标识
            this.$emit('cutPrice', 10, id)

            // this.$emit('changePrice', 10)
        }
    }
}
</script>