Vue生命期钩子,Vue组件,Vue-Cli创建项目

Vue生命期钩子

vue 的8个生命周期钩子函数



     钩子函数                                      描述 
 beforeCreate 创建Vue示例之前调用 
 created  创建Vue实例成功后调用(可以在此处发送异步请求后端数据)
 beforeMount  渲染DOM之前调用
 mounted  渲染DOM之后调用
 beforeUpdate  重新渲染之前调用(数据更新等操作时,控制DOM重新渲染)
 updated  重新渲染完成之后调用
 beforeDestroy  销毁之前调用
 destroyed  销毁之后调用
 

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <link href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet">
    <script src="./js/vue.js"></script></head>
<body><div class="container-fluid">
    <div class="row">
        <div class="col-md-6 col-md-offset-3" style="margin-top: 20px"><div id="app">
                {{name}}
            </div>
        </div>
    </div>
</div></body><script>var vm = new Vue({
        el: '#app',
        data: {
            name:'lqz'
        },
        methods: {},
​
        beforeCreate() {
            console.log('当前状态:beforeCreate')
​
        },
        created() {
            console.log('当前状态:created')
​
        },
        beforeMount() {
            console.log('当前状态:beforeMount')
​
        },
        mounted() {
            console.log('当前状态:mounted')
​
          //用的最多,向后端加载数据,创建定时器等
            //挂在,三秒后执行一个任务
// setTimeout(()=> {
            //     console.log('lqz is nb')
            // },3000)
            this.t = setInterval(function () {
                console.log('lqz is nb')
            }, 3000)
​
        },
        beforeUpdate() {
            console.log('当前状态:beforeUpdate')
​
        },
        updated() {
            console.log('当前状态:updated')
​
        },
        beforeDestroy() {
            console.log('当前状态:beforeDestroy')
​
        },
        destroyed() {
            console.log('当前状态:destroyed')
            clearInterval(this.t)
            this.t = null
            console.log('destoryed')
​
        },
​
    })
</script></html>
View Code

组件

jquery-ajax、fetch和axios

jquery的ajax(不推荐使用)
fetch(不是所有浏览器都支持,谷歌浏览器支持)
axios(基本都是用它)

前后端交互之jquery-ajax

前端

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <link href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet">
    <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
    <script src="./js/vue.js"></script></head>
<body><div class="container-fluid">
    <div class="row">
        <div class="col-md-6 col-md-offset-3" style="margin-top: 20px"><div id="app">
                <button @click="handle_load">点我加载数据</button>
                <hr>
                拿回来的数据是:{{name}}
            </div>
        </div>
    </div>
</div></body><script>var vm = new Vue({
        el: '#app',
        data: {
            name:'lqz'
        },
        methods: {
            handle_load(){
                $.ajax({
                    url:'http://127.0.0.1:5000/',
                    type:'get',
                    success:data=> {
                        this.name=data
                    }
                })
​
            }
        },
​
​
        mounted() {
            //跟后端交互,写在这,而不要使用button
            console.log('当前状态:mounted')
            this.handle_load()
​
​
        },
​
​
    })
</script></html>

后端

from flask import Flask, make_response
​
app = Flask(__name__)
​
​
@app.route('/')
def index():
    res = make_response('hello world')
    # 运行所有域向我发请求(解决跨域问题)
    res.headers['Access-Control-Allow-Origin']='*'
    return res
​
​
if __name__ == '__main__':
    app.run()
 

前后端交互之fetch

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <link href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet">
    <script src="./js/vue.js"></script></head>
<body><div class="container-fluid">
    <div class="row">
        <div class="col-md-6 col-md-offset-3" style="margin-top: 20px"><div id="app">
                <ul>
                    <li v-for="film in films_list">
                        <img :src="film.poster" alt="" width="60px" height="80px">
                        <span>{{film.name}}</span>
                        <hr>
                    </li>
                </ul>
            </div>
        </div>
    </div>
</div></body><script>var vm = new Vue({
        el: '#app',
        data: {
            films_list: []
        },
        methods: {
            handle_load() {
                fetch('http://127.0.0.1:5000/home').then(data => data.json()).then(data => {
                    console.log(data)
                    if (data.status == 0) {
                        this.films_list = data.data.films
                    } else {
                        alert('加载出错')
                    }
​
​
                })
​
            }
        },
​
​
        mounted() {
            //跟后端交互,写在这,而不要使用button
            console.log('当前状态:mounted')
            this.handle_load()
​
​
        },
​
​
    })
</script></html>

前后端交互之axios

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <link href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet">
    <script src="https://unpkg.com/axios/dist/axios.min.js"></script>
    <script src="./js/vue.js"></script></head>
<body><div class="container-fluid">
    <div class="row">
        <div class="col-md-6 col-md-offset-3" style="margin-top: 20px"><div id="app">
                <ul>
                    <li v-for="film in films_list">
                        <img :src="film.poster" alt="" width="60px" height="80px">
                        <span>{{film.name}}</span>
                        <hr>
                    </li>
                </ul>
            </div>
        </div>
    </div>
</div></body><script>var vm = new Vue({
        el: '#app',
        data: {
            films_list: []
        },
        methods: {
            handle_load() {
                axios.get('http://127.0.0.1:5000/home').then(data => {
                    //data.data才是后端响应的数据
                    console.log(data)
                    if (data.data.status == 0) {
                        this.films_list = data.data.data.films
                    } else {
                        alert('加载出错')
                    }
                })
​
            }
        },
​
​
        mounted() {
            //跟后端交互,写在这,而不要使用button
            console.log('当前状态:mounted')
            this.handle_load()
​
​
        },
​
​
    })
</script></html>

计算属性

计算属性的特点:只要返回的结果没有发生变化,那么计算属性就只会被执行一次

计算属性的应用场景:由于计算属性会将返回的结果缓存起来,所以如果返回的数据不经常发生变化
那么使用计算属性的性能就会比使用函数的性能高

把输入的首字母大写

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <link href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet">
    <script src="./js/vue.js"></script></head>
<body><div class="container-fluid">
    <div class="row">
        <div class="col-md-6 col-md-offset-3" style="margin-top: 20px">
            <!-- 这个就是MVVM中的 View -->
            <div id="app">
                {{name}}
​
                <input type="text" v-model="s">
                <hr>
    <!-- s.slice 从第0个位置截到第一个位置转成大写,只是第一个字母。还得把后面的字母加上,从第一个截到最后拼上-->
                输入的值是:{{s.slice(0,1).toUpperCase()+s.slice(1)}}
                <hr>
    <!-- 写一个函数,跟上面一样,缺点:只要页面有值变化,它会触发update的执行,
    不管是函数还是其它还会再执行一次 -->
                输入的值是:{{to_upper()}}
                <hr>
                输入的值是(计算属性) :{{str_s}}
            </div>
        </div>
    </div>
</div>
</body>
<script>
     // 这个就是MVVM中的View Model
    var vm = new Vue({
        el: '#app',
         // 这个就是MVVM中的Model
        data: {
            s:'',
            name:''
        },
        // 专门用于定义计算属性的
        computed:{
            str_s(){
                // 计算属性的特点:只要返回的结果没有发生变化,那么计算属性就只会被执行一次
                //只有该方法中使用的值发生变化,才会重新计算
                console.log('计算属性的方法,我执行了')
                return this.s.slice(0,1).toUpperCase()+this.s.slice(1)
            }
        },
         //专门用于存储监听事件回调函数
        methods:{  // 函数的特点:每次调用都会执行
            to_upper(){
                console.log('我执行了')
                return this.s.slice(0,1).toUpperCase()+this.s.slice(1)
            }
        },
    })
</script></html>

重写过滤案例

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <link href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet">
    <script src="./js/vue.js"></script></head>
<body><div class="container-fluid">
    <div class="row">
        <div class="col-md-6 col-md-offset-3" style="margin-top: 20px"><div id="app">
                <p><input type="text" v-model="mytext" @input="handleChange"></p>
                <ul>
                    <li v-for="data in newdatalist">{{data}}</li>
                </ul>
            </div>
        </div>
    </div>
</div></body><script>var vm = new Vue({
        el: '#app',
        data: {
            mytext: '',
            datalist: ['aaa', 'abc', 'abcde', 'abcdef', 'bbb', 'bac'],
        },
​
        computed: {
            newdatalist() {
                var newlist = this.datalist.filter(item => {
                    return item.indexOf(this.mytext) > -1
                })
                return newlist
            }
​
        },
​
​
    })
</script></html>

虚拟dom优化问题

1 v-for循环的时候,经常看到有个自定义属性 key

2 key是一个唯一值,为了虚拟dom替换的时候,效率高

组件化开发介绍

Vue的两大核心:1.数据驱动界面改变,2.组件化

什么是组件?什么是组件化?
    在前端开发中组件就是把一个很大的界面拆分为多个小的界面,每一个小的界面就是一个组件
    将大界面拆分成小界面就是组件化
​
组件化的好处:
    可以简化Vue实例的代码
    可以提高复用性
    -例如:有一个轮播,可以在很多页面中使用,一个轮播有js,css,html
    -组件把js,css,html放到一起,有逻辑,有样式,有html
    
Vue中如何创建组件?
    创建组件构造器
    注册已经创建好的组件
    使用注册好的组件
    
全局组件:整个项目中都能使用的组件
局部组件:只能再局部使用  

注册全局组件

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="./js/vue.js"></script></head>
<body><div id="app">
    <myhead></myhead>
    <hr>
    <myhead></myhead>
</div>
</body><script>
​
    Vue.component('myhead', {
        template: `
            <div>
                    <button @click="handleClick">我是个按钮:点我看美女</button>
                    <button>我又是一个按钮</button>
            </div>
        `,
        methods: {
            handleClick(){
                alert('美女')
            }
        },
    })
​
    var vm = new Vue({
        el: '#app',
        data: {},
        methods: {
        }
    })
</script>
</html>

注册局部组件


<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="./js/vue.js"></script>
</head>
<body>
<div id="app">
    <myhead></myhead>
    <hr>
</div>
</body>
<script>
    Vue.component('myhead', {
        template: `
            <div>
                <button @click="handleClick">我是个按钮:点我看美女</button>
                <button>我又是一个按钮--{{name}}</button>
                {{show}}
                <hr>
                看到美女了
                <child></child>
            </div>
​
        `,
        methods: {
            handleClick() {
                alert('美女')
            }
        },
        components:{
            child:{
                template:`
                <div>
                    <img src="./img/1.jpg" alt="" v-show="show" height="60px" width="60px">
                    <button @click="handleRemove">点我图片消失</button>
                </div>
                `,
                data(){
                    return {
                        show:true
                    }
                },
                methods:{
                    handleRemove(){
                        this.show=!this.show
                    }
                }
            }
        },
        data(){
            return {name:'lqz'}
        },
    })
​
​
    var vm = new Vue({
        el: '#app',
        data: {},
        methods: {}
    })
</script></html> 

组件间通信

1 父子组件传值 (props down, events up)
2 父传子之属性验证props:{name:Number}Number,String,Boolean,Array,Object,Function,null(不限制类型)
3 事件机制a.使用 $on(eventName) 监听事件b.使用 $emit(eventName) 触发事件
4 Ref<input ref="mytext"/>  this.$refs.mytext
5 事件总线var bus = new Vue();* mounted生命周期中进行监听

父传子

在子组件上新增属性

<myhead myname="lqz"></myhead>

在子组件中:定义,myname要跟新增的属性名一致

props:['myname']

在子组件中就可以使用myname变量了,从父组件传入的

注意加不加:的区别

<myhead :myname="lqz"></myhead>
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="./js/vue.js"></script></head>
<body><div id="app">
<!--    <myhead myname="lqz"></myhead>--><!--    <hr>-->
<!--    <myhead :myname="name"></myhead>--><hr>
    <myhead :mybool="false"></myhead>
​
​
</div>
</body><script>
​
​
    Vue.component('myhead', {
        template: `
            <div>
                <button>我是按钮</button>
                我的名字是:
                <br>
                传入的布尔值是:{{typeof mybool}}
            </div>
​
        `,
​
        // props:['myname','mybool']
        //类型限制
        props: {
            mybool: Boolean,
        }
​
    })
​
​
    var vm = new Vue({
        el: '#app',
        data: {
            name: '迪丽热巴'
        },
​
​
    })
</script></html>

通过事件实现子传父

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="./js/vue.js"></script></head>
<body><div id="app"><myhead @myevent="handleParent" @egon="handleEgon"></myhead>
​
​
</div>
</body><script>
​
​
    Vue.component('myhead', {
        template: `
            <div>
                <button @click="handleChild">我是按钮</button>
            </div>
​
        `,
        data(){
            return {
                n:100,
                m:200
            }
        },
        methods:{
            handleChild(){
                console.log('子组件的按钮被点击了')
                // this.$emit('myevent') //触发自定义的事件执行(触发myevent的执行)
                // this.$emit('myevent',this.n,this.m) //触发自定义的事件执行(触发myevent的执行)
                // this.$emit('egon')
            }
        },
        mounted(){
             this.$emit('egon')
        }
​
​
    })
​
​
    var vm = new Vue({
        el: '#app',
        data: {
            n:0,
            m:0,
        },
        methods:{
            handleParent(n,m){
                console.log('自定义的事件执行了')
                this.n=n
                this.m=m
                console.log(n)
                console.log(m)
​
            },
            handleEgon(){
                console.log('egon被打了')
            }
        }
​
​
    })
</script></html>

通过ref实现父子通信

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="./js/vue.js"></script>
</head>
<body><div id="app">
    <input type="text" placeholder="我是父组件的1" ref="myinput">
    <input type="text" placeholder="我是父组件的2" ref="myinput2">
    <input type="password" placeholder="我是父组件的3" ref="myinput3">
    <button @click="handleParentButton">点我执行一个函数</button>
    <hr>
    <myhead ref="mychild"></myhead>
</div>
</body><script>
    Vue.component('myhead', {
        template: `
            <div>
                <button>我是按钮</button>
            </div>
        `,
        data(){
            return {
                name:'lqz'
            }
        },
        methods:{
            tgc(name){
                this.name=name
                alert(name)               
            }
        },
    })
    
    var vm = new Vue({
        el: '#app',
        data: {
​
        },
        methods:{
            handleParentButton(){
                console.log('父组件的button按钮被点击了')
                //
                // console.log(this.$refs.myinput3.value)
                // console.log(this.$refs.myinput3.type)
                console.log(this.$refs.mychild.tgc('lqz is big'))
            }
        }
    })
    //ref属性如果加在普通标签上,通过this.$refs.myinput,取到的就是这个标签
    //ref属性如果加在组件上,通过this.$refs.mychild,取到的就是这个组件,拿到组件的值,拿到组件的方法,并且可以执行
</script></html>

通过事件总线实现组件通信

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="./js/vue.js"></script></head>
<body><div id="app">
    <myhead></myhead>
    <hr>
    <child1></child1></div>
</body><script>// 定义一个事件总线
    var bus = new Vue() //new一个vue的实例,就是中央事件总线
​
​
    Vue.component('myhead', {
        template: `
            <div>
                <button>我是按钮</button>
                来自另一个组件的数据:  <span v-text="recv"></span>
            </div>
​
        `,
        mounted() {
            //生命周期,当前组件dom创建完后悔执行
            console.log('当前组件dom创建完后悔执行')
            //订阅消息
            bus.$on('suibian', (item) => {
                console.log('收到了', item)
                this.recv=item
​
            })
        },
        data(){
            return {
                recv:''
            }
        }
​
​
    })
​
    Vue.component('child1', {
        template: `
            <div>
                <input type="text" v-model="input_1">
                <button @click="handleClick">点我</button>
            </div>`,
        methods: {
            handleClick() {
                bus.$emit('suibian', this.input_1) //发布消息,名字跟订阅消息名一致
            }
        },
        data(){
            return {
                input_1:''
            }
        }
    })
​
​
    var vm = new Vue({
        el: '#app',
        data: {},
​
​
    })
    //ref属性如果加在普通标签上,通过this.$refs.myinput,取到的就是这个标签
    //ref属性如果加在组件上,通过this.$refs.mychild,取到的就是这个组件,拿到组件的值,拿到组件的方法,并且可以执行
</script></html>

动态组件

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="./js/vue.js"></script></head>
<body><div id="app">
    <button @click="who='myhead1'">显示组件1</button>
    <button @click="who='myhead2'">显示组件2</button>
    <button @click="who='myhead3'">显示组件3</button><keep-alive>
        <component :is="who"></component>
    </keep-alive></div>
</body><script>
​
​
    Vue.component('myhead1', {
        template: `
            <div>
                <button> myhead1的按钮</button>
                <div>
                我是组件1111的样子
                </div>
            </div>
​
        `,
​
    })
    Vue.component('myhead2', {
        template: `
            <div>
                <button >myhead2的按钮</button>
                 <div>
                我是组件222的样子
                <input type="text">
                </div>
            </div>
​
        `,
​
    })
    Vue.component('myhead3', {
        template: `
            <div>
                <button >myhead3的按钮</button>
                           <div>
                我是组件333的样子
                <button>点我</button>
                <hr>
                <span>xxx</span>
                </div>
            </div>
​
        `,
​
    })
​
​
    var vm = new Vue({
        el: '#app',
        data: {
            who: 'myhead1'
        },
​
​
    })
    //ref属性如果加在普通标签上,通过this.$refs.myinput,取到的就是这个标签
    //ref属性如果加在组件上,通过this.$refs.mychild,取到的就是这个组件,拿到组件的值,拿到组件的方法,并且可以执行
</script></html>

 

Vue-cli创建项目

1 安装node环境:最新是14
    - 跟python比较
    - node    python
    - npm     pip3
    - 安装cnpm,淘宝做的npm,以后使用npm的地方,都是用cnpm
2 安装cli脚手架
    -cnpm install -g @vue/cli
    
3 创建项目
    vue create my-project # 命令行
    # OR
    vue ui  #图形化界面
    

 目录介绍

image-20210427225921806

├─ node_moduls:项目依赖,当前项目的所有第三方包,(上传项目的时候不需要用:把项目给别人,这个文件夹删掉)
       npm install  就会又把依赖重新装上
       pi3 install -r request.txt     
├─ public文件夹:(你不用动)
    ├─ favicon.ico  网站图标
    └─ index.html  项目入口页面,单页面开发(整个vue项目就这一个页面,一般不会动它)  
├─ src文件夹:代码文件夹(经常动,书写你的所有代码)
    ├─ assets文件夹 :存储项目中自己的一些静态资源,图片,js,css
    ├─ components文件夹:存储项目中的自定义组件(组件,小组件,公共组件)
    ├─ router文件夹:存储VueRouter路由相关文件(装了Router才有,否则没有,页面跳转)
    ├─ store文件夹:存储Vuex相关文件(vuex才有的,状态管理器)
    ├─ views文件夹:存储项目中的自定义组件(大组件,页面级组件,路由级别组件)
    ├─ App.vue:根组件
    └─ main.js:整个项目的入口js
├─ .gitignore  # git的忽略文件,讲到git才知道
├─ babel.config.js # 不用动
├─ package.json     #依赖的模块
├─ package-lock.json #依赖的模块
└─ README.md      # 介绍
    

项目组件介绍(重点)

每一个组件都有三部分
# html内容写在这
// template 用于编写当前组件的结构代码的
<template>
    <div class="home"></div>
</template>
​
​
# js内容
// script 用于编写当前组件的业务代码的
<script>
    export default {
      name: 'Home',
      data(){
          return {
             a:'asdfasdfasdfasdfasd'
          }
​
      },
​
    }
</script>
​
# style的内容
// style 用于编写当前组件额样式代码的
<style>
    
</style>

把vue项目编译成纯html,css,js

webpack:模块化
打包:npm run build  
在项目路径下有个dist文件夹:html,css,js
从来就没有正确的选择,我们只不过是要努力奋斗,使当初的选择变得正确。
原文地址:https://www.cnblogs.com/gfeng/p/14747759.html