Vue个人笔记

{}相当于new object,
先把基础的Vue学好,之后再用脚手架,就能够融会贯通了!!!

vue对象中的几个主要对象:
new Vue({
    el:'app',           //作用于哪个模板
    data:{}             //存放vue组件的数据
    methods:{}         //dom绑定事件的书写区
    computed:{}        //计算属性,对于任何复杂逻辑,你都应当使用计算属性,里面放的是函数!
    directives: {}       //自定义指令
    components:{}        //自定义组件
});

//根组件
new Vue({
    data:{}             //存放vue组件的数据
    methods:{}         //dom绑定事件的书写区
    computed:{}
    
        //子组件
    component:{
            data:{}             //存放vue组件的数据
        methods:{}         //dom绑定事件的书写区
        computed:{}
    }
});

一:页面渲染( Rendering ) 
1,数据绑定
    数据绑定最常见的形式就是使用“ Mustache” 语法 ( 双大括号 ) 的文本插值
    {{msg}}
    可以在双大括号中使用 Javascript 表达式
    {{ message.split('').reverse().join('') }}
2,计算属性
模板内的表达式非常便利,但是设计它们的初衷是用于简单运算的。在模板中放入太多的
逻辑会让模板过重且难以维护。
    <div id="example">{{ message.split('').reverse().join('') }}</div>
    对于任何复杂逻辑,你都应当使用计算属性
    <div id="example">
        <p>Computed reversed message: "{{ reversedMessage }}"</p>
    </div>
    var app = new Vue({
        el: '#example',data: {message: 'Hello'},
        computed: {
        reversedMessage: function ()
        {
                return this.message.split('').reverse().join('')
        }
    }})
3,属性的绑定
指令 (Directives) 是带有 v- 前缀的特殊属性,指令的职责是,当表达式的值改变时,将
其产生的连带影响,响应式地作用于 DOM 。一些指令能够接收一个“ ” 参数 ,在指令名称
之后以冒号表示。

v-bind 指令可以用于响应式地更新 HTML 属性,简写形式为 ":"
<a v-bind:href="url"></a>

4,事件的绑定
v-on 指令用于监听 DOM 事件,参数为事件名称,引号内为绑定的事件处理函数或者是
Javascript 代码(不推荐)。简写形式为 "@"
<a v-on:click="doSomething"></a>

4-2
事件修饰符
<form v-on:submit.prevent="onSubmit"></form>
类似的还有停止冒泡( .stop ) , 只当事件在当前元素本身时触发( .self ),仅触发一次 事件( .once )
键值修饰符
<input v-on:keyup.13=“submit”> 13 可以使用 .submit 代替
.enter 、 .tab 、 .delete 、 .esc 、 .space 、 .up 、 .down 、 .left 、 .right

5,条件渲染( v-if )
    根据给定条件判断决定是否显示元素
    <h1 v-if="type === 'A'">A</h1>
    <h1 v-else-if="type === 'B'">B</h1>
    <h1 v-else>C</h1>
条件渲染( v-show )
    与 v-if 不同的是带有 v-show 的元素始终会被渲染并保留在 DOM 中。 v-show 是简单地切换元素的 CSS 属性 display
    注意, v-show 不支持 <template> 语法,也不支持 v-else 。 如果需要非常频繁地切换元素,则使用 v-show 较好

6, 列表渲染( v-for )
v-for 指令根据一组数组的选项列表进行渲染,使用 item in items 形式的特殊语法
 items 是源数据数组并且 item 是数组元素迭代的别名

7,表单输入绑定
v-model 指令可以在表单控件元素上创建双向数据绑定(不会用于文本元素)
    1 . 单行文本、多行文本框、单选按钮、下拉菜单简单使用 v-model 绑定即可
    <input v-model="message"><p>Message is: {{ message }}</p>
    2 . 复选框(绑定到一个数组中)
    <input type="checkbox" value="Jack" v-model="checkedNames">
    <input type="checkbox" value="Jack" v-model="checkedNames">
    data:{checkedNames:[]}

二:动画(animation)

Vue 在插入、更新或者移除 DOM 时,提供多种不同方式的应用过渡效果。 包括以下工具:
1,在 CSS 过渡和动画中自动应用 class
2,可以配合使用第三方 CSS 动画库,如 Animate.css
3,在过渡钩子函数中使用 JavaScript 直接操作 DOM
4,可以配合使用第三方 JavaScript 动画库,如 Velocity.js
Vue 提供了 transition 的封装组件,在下列情形中,可以给任何元素和组件添 加 entering/leaving 过渡
在进入 / 离开的过渡中,会有 6 个 class 切换, v- 是这些类名的前缀,可以在transition 标签中设定 name 属性改变该前缀。
v-enter(进入前) v-enter-active(进入中) v-enter-to(进入后)   v-leave(离开前)  v-leave-active(离开中)  v-leave-to(离开后)
1,自定义过渡样式
        <button @click='show = !show'> 切换 </button>
            <transition name='fade'>
                <p v-if='show'> hello vue </p>
            </transition>
        <style>
            .fade-enter-active, .fade-leave-active {
                transition: opacity .5s
            }
            .fade-enter, .fade-leave-to {
                opacity: 0
            }
        </style>
        
2,自定义过渡的类名,和其他第三方动画库,animate.css结合使用
enter-class 、 enter-active-class 、 enter-to-class
leave-class 、 leave-active-class 、 leave-to-class

    <link rel="stylesheet" href="../css/animate.css">
        <button @click='show = !show'> 切换 </button>
    <transition
        enter-active-class='animated bounce'
        leave-active-class='animated bounce'>
        <p v-if='show'> hello vue </p>
    </transition>

3,javascript 钩子,可以通过 js 钩子定义动画,结合第三方动画库 Velocity.js( 以及插件Velocity.ui.js)
before-enter 、 enter 、 after-enter 、 before-leave 、 leave 、 after-leave
    <script src="../js/velocity.min.js"></script>
    <script src="../js/velocity.ui.js"></script>
        <button @click='show = !show'> 切换 </button>
        <transition @enter='enter' @leave='leave'>
            <p v-if='show'> hello vue </p>
        </transition>
    methods:{
        enter:function(el,done){
        Velocity(el,"callout.pulse", { duration: 650 ,complete:done}) },
        leave:function(el,done){
        Velocity(el,"callout.bounce", { duration: 1500 ,complete:done}) }
    }
    
4,列表过渡
    为了同时渲染整个列表,使用 <transition-group> ,不同于 <transition> ,它会
    以一个真实元素呈现:默认为一个 <span> 。你也可以通过 tag 特性更换为其
    他元素,内部元素 总是需要 提供唯一的 key 属性值
    <script src="../js/velocity.min.js"></script>
    <transition-group tag="ul" @enter="enter" @leave="leave" >
        <li v-for='name in nameList' :key='name'>{{name}}</li>
    </transition-group>
    methods:{
        enter:function(el,done){
        Velocity(el,{ opacity: 1, height: '1.6em' },{ complete: done })},
        leave:function(el,done){
        Velocity(el,{ opacity: 0, height: 0 },{ complete: done })}
    }
    
三:组件
组件 (Component) 是 Vue.js 最强大的功能之一。在较高层面上,组件是自定义元素,template用反引号``, 比用引号方便

1,全局注册
    Vue.component('my-component', {
        // 构造 Vue 实例时传入的选项大多数都可以在组件里使用。 data 为函数
        template : '<div>A custom component!</div>'
    })
    组件在注册之后,便可以作为自定义元素 <my-component></my-component> 在一个实例的模板中使用。注意确保在初始化根实例之前注册
组件(即 new Vue({}))

2,局部注册
局部注册 不必把每个组件都注册到全局。我们可以通过某个 Vue 实例 / 组件的实例
选择 components 注册仅在其作用域中可用的组件。
    var app = new Vue({
        el:'#app',
        components:{
            'my-component':{ template:'<h2>hello component</h2>'}
        }
    });

3,自定义组件的使用
        1,直接使用
            <my-row></my-row>
      2,通过 is 关键字使用
    第一种方式会受到 HTML 本身的限制,因为 Vue 只有在浏览器解析、规范化模
    板之后才能获取其内容,像 <ul> 、 <ol> 、 <table> 、 <select> 这样的元素里允
    许包含的元素有限制。
    <table>
        <my-row></my-row>
    </table>
    变通方法:
    <table>
        <tr is="my-row"></tr>
    </table>

4,父子组件通信
在 Vue 中,父子组件的关系可以总结为 prop 向下(子)传递,事件向上(父)传递 。
父组件通过 prop 给子组件下发数据,子组件通过事件给父组件发送消息

    1,父子组件 -props
        子组件要显式地用 props 选项声明它预期的数据,父组件使用 props 中声明
        的同名属性进行注入
        var app = new Vue({
            el:'#app',
            data:{name:'hello parent'},
            components:{
                'my-son':{
                props:['name'],// 不区分大小写
                data:function(){return {msg:'hello son' }},
                template:'<div> 子组件, {{msg}},{{name}}</div>'
                }
            }
        });
        <div id="app"><my-son :name='name'></my-son></div>
        
    2,父子组件 - 自定义事件
    子组件使用自定义事件系统与父组件通信,每个 Vue 实例都实现了事件接口,使用 $on(eventName) 监听事件,
    使用 $emit(eventName) 触发事件 。父组件可以在使用子组件的地方直接用 v-on 来监听子组件触发的事件
    <div id="app">
        <p><b>total:</b>{{total}}</p>
        <button-counter @increment='incrementTotal'></button-counter>     //监听
        <button-counter @increment=‘incrementTotal’></button-counter>
        </div>
        components:{
            'button-counter':{
            ‘template’:‘<button @click=“incrementCounter”>{{counter}}</button>’,
            data:function(){ return {counter:0}},
            methods:{
            incrementCounter:function(){
            this.counter++;
            this.$emit('increment'); // 向父组件发射事件
        }
        } }
        
    3,插槽
    要想在子组件中使用父组件提供的模板就需要使用到插槽。除非子组件模板包含至少一个 <slot> 插口,否则父组件的内容将会被丢弃。
    <div id="app">
        <my-component><h3>hello Vue</h3></my-component>
    </div>
    components:{
        'my-component':{
        template:'<div><h2>hello my-component</h2><slot>default slot</slot></div>'
        }
    }
    也可以为插槽提供名字,这样可以在一个子组件中插入多个父组件提供的模板。
    <slot name="header"></slot>
    <slot name="footer"></slot>
    <h1 slot="header"> 这里可能是一个页面标题 </h1>
    <p slot="footer"> 这里有一些联系信息 </p>
    
    4,作用域插槽
作用域插槽是一种特殊类型的插槽,用作一个 ( 能被传递数据的 ) 可重用模板,来代替已经渲染好的元素。
在子组件中,只需将数据传递到插槽,在组件中,具有特殊特性 slot-scope 的 <template> 元素必须存在,
表示它是作用域插槽的模板。
    Vue.component('my-ul',{
        template:‘<ul><slot v-for=“name in names”
        :text="name"></slot></ul>',
        data:function(){return {names:['terry','larry','tom','jacky']}}
    });
    Vue.component('my-list',{
        // 允许使用者自定义如何渲染列表的每一项
        template:‘<my-ul><template slot-scope=“props” >
        <li>{{props.text}}</li></template></my-ul>'
    });
    <div id=’app’>
        <my-list></my-list>
    </div>
    
5,动态组件---可以用vue插件--路由来代替
通过使用保留的 <component> 元素,动态地绑定到它的 is 特性,可以让 多个组件可以使用同一个挂载点,并动态切换。
    new Vue({
        data:{ currentView:'my-com2' },
        components:{
            'my-com1':{ template:'<div>component1</div>' },
            'my-com2':{ template:'<div>component2</div>' },
            'my-com3':{ template:'<div>component3</div>' }
        }
    })
    <component v-bind:is="currentView"></component>
    


学习组件后的总结:
  vue就相当于一个组件,它作用于 el:#app 这个模板,这个模板里的方法,写在methods对象中,模板里的数据写在data对象中.....
    一个组件是一个作用域,它们各自的方法,数据写在相应的组件里。
    template模板中,一定要用一个根标签包裹!

四:其他

1,自定义指令
    全局注册
        vue.directive(directiveName,options)
    局部注册
        new Vue({
        directives: {
        directiveName:options
        }
        });
    指令定义函数提供了几个钩子函数:
        bind 只调用一次,指令第一次绑定到元素时调用,用这个钩子函数可以定义一个在绑定时执行一次的初始化动作。
        inserted 被绑定元素插入父节点时调用
        
    钩子函数参数
        el 指令所绑定的元素,可以用来直接操作 DOM
        binding 一个对象,包含了指令相关的信息(参数 binding.argument )

2,过滤器
Vue.js 允许你自定义过滤器,可被用作一些常见的文本格式化。过滤器可以用在两
个地方: mustache 插值和 v-bind 表达式。过滤器应该被添加在 JavaScript 表达
式的尾部,由“ |” 管道 符指示。
    <div id="app"> {{msg | toUpper(arg1,arg2)}}</div>
    new Vue({
        el:"#app",
        data:{msg:'hello world' },
        filters:{
            toUpper:function(val,arg1,arg2){return val.toUpperCase();}
        }
    });

3,插件的使用
    1,通过 script 标签导入,则不需要
    2,npm,如果在一个模块化工程中使用它,必须要通过 Vue.use() 明确地安装该功能
    var Vue = require('vue')
    var VueRouter = require('vue-router')
    // 不要忘了调用此方法
    Vue.use(VueRouter)
    
    
VUEX:
特点:将组件的数据进行集中化管理,将数据以及数据相关操作抽离出来进行统一管理
        只有mutations可以修改state的值(虽然actions也可以,但是不要这样做)
        
1,state,mutations,actions作用
    <script>
            var store = new Vuex.Store({
                //保存所有的数据
                state:{
                    number:0
                },
                //突变,用于修改state的值  必须是同步
                mutations:{
                    updateNumber:function(state,value){
                        state.number = value;
                    }
                },
                //动作,用于调用突变,执行数据的改变  context即store存贮对象 ,可以包含任意异步操作
                actions:{
                    increment:function(context){
                        var value = context.state.number+2;
                        context.commit('updateNumber',value);
                    },
                    decrease:function(context){
                        var value = context.state.number-2;
                        context.commit('updateNumber',value);
                    }
                }
            });
            new Vue({
                el:'#app',
                store:store,
                //用computed计算传值
                computed:{
                    ...Vuex.mapState(['number'])
                },
                methods:{
                    ...Vuex.mapActions(['increment','decrease'])
                }
            });
        </script>
        
2,vue组件怎么访问到state中的数据
    
    通过在根实例中注册 store 选项,该 store 实例会注入到根组件
    下的所有子组件中,且子组件能通过 this.$store 访问到。
    new Vue({
    el:'#app',
    store:store,
    computed: {count () {return this.$store.state.count}}
    })
    
    2-1访问简化方式:
            --------
            <div>{{num}}---{{name}}</div>
    
            --------
            state:{
                number:0,
                name:'kb'
            }
            --------
        computed:{
                //div显示的值要和state的值一致
                // ...Vuex.mapState(['number','name'])
                //若不一致,可用如下方法
                ...Vuex.mapState({'num':'number','name':'name'})
            }
            
3,    定义 Getter
    当我们要过滤从state获取到的数据,可以在 store 中定义“ getter” (可以认为是 store 的计算属性)

        3-1mapGetters 辅助函数
        getters:{
                boys:function(state){
                    return state.students.filter(
                        function(item){
                            return item.gender == 'male'
                        }
                    )
                }
            }
        ...Vuex.mapGetters(['boys'])
         //若不一致,可用如下方法
        //...Vuex.mapGetters({'boys2':'boys'})

4,怎么在vue中调用mutations方法(使用commit)
    更改 Vuex 的 store 中的状态的唯一方法是提交 mutation ,必须是同步操作。
    4-1,提交载荷( 就是传参的意思 )
    mutations:{
                    add:function(state,e){
                            state.events.push(e)
                    }
            }    
    ----------------    
    methods{
    方法1:    this.$store.commit('add',Object.assign({},this.form));  
            //Object.assign({目标对象},{源对象}),Object.assign方法用于对象的合并,将源对象(source)的所有可枚举属性,复制到目标对象(target)。
            如果目标对象与源对象有同名属性,或多个源对象有同名属性,则后面的属性会覆盖前面的属性。
    }
    方法2:
            ...Vuex.mapMutations({add:‘increment'}) // 将 `this.add()` 映射为 `this.$store.commit('increment')`
            this.add(param);
            
5,怎么在vue中调用Actions方法(使用dispatch方法)
Action 类似于 mutation ,不同在于, Action 提交的对象的是 mutation ,而不是直接变更状
态,并且 Action 可以包含任意异步操作, Action 函数接受一个与 store 实例具有相同
方法和属性的 context 对象,因此你可以调用 context.commit 提交一个 mutation ,或
者通过 context.state 和 context.getters 来获取 state 和 getters 。
    -------------
        
    methods:{
        //方法1:this.$store.dispatch('increment',{amount:10})
        方法2:...Vuex.mapActions(['increment'])
        this.increament();//直接执行actions中的increment方法    方法2
    }

什么时候需要承诺?当调用者需要知道这个异步操作执行成功与否的时候!    
6,当A调用B,A需要当B成功后执行一段代码,失败后执行一段代码(或者需要等B返回一个结果),而B是异步操作,怎么做?(eg:调用删除方法,等待方法返回结果,但是是异步的,没法等)
    在B中使用Promise方法,当B执行成功或失败后,会执行相应的成功,失败方法
    deleteBatch:function(context,ids){
                 //promise用于返回状态给调用者的!!!
                 return new Promise(function(resolve,reject){
                        //$.ajax()......
                        $.ajax({
                        type: "GET",
                        url: 'http://localhost:8080/hello4',
                        success: function (data) {
                            console.log("访问成功");
                            // alert(data);
                             //刷新,当删除成功后重新执行查询操作
                            context.dispatch('findAll');
                            resolve('success');            //成功执行该方法
                        },
                        error:function (data) {
                            console.log("访问失败");
                            reject(data);                //失败执行该方法
                        }
                    });
                   
                 });

    }
    --------------------
    methods: {
                handleDelete:function(index,row){
                    this.deleteBatch(row.age).then(function(msg){alert(msg)}).catch(function(e){alert(e)})
                    //当访问的函数返回Promise对象是,可以用.then(成功执行).catch(失败执行)
                }
    }
    

webpack结合Vue:
    webpack作用:将模块打包,简化前端开发,导入模块用import,再不用script,link引入js,css了。css,js,图片都写在src目录下,因为
                    一切皆模块,dist存放打包后的文件

 1,本地安装
    npm install –-save-dev webpack
    
 2,使用方式
   初始化项目并安装 webpack
   npm init –y
   npm install --save-dev webpack
 2-1, 编写配置文件 webpack.config.js  (放在项目目录下)
 ——
 module.exports = {
        entry: './src/app.js',        //打包入口文件(从哪开始打包!)
        output:{                    //打包输出目录
            path: __dirname+'/dist',   //—__dirname:代表本文件目录的绝对路径
            filename:'app.bundle.js'    //表示打包后文件名
        }
};
使用 npm 脚本执行打包操作 在package.json中添加
"scripts": { "build": "webpack" }       //npm run build 就可以打包项目了

以上为webpack环境的搭建!!!


Loader:加载器(将其他类型的文件加载成可打包类型,css,png...)
    
3,如何将es6代码打包成es5代码,需要通过babel(浏览器默认是不支持es6的,除了火狐可以解析)
  3-1,安装命令 npm install --save-dev babel-core babel-preset-env babel-loader  //babel一系列东东
  //配置
  3-2,需要在项目目录下新建一个.babelrc文件
    {
    "presets":["env"]
    }
  3-3,在webpack.config.js文件内的module 添加{ test:/.js$/, exclude: /node_modules/, use: 'babel-loader' }
  3-4,
  安装过程可能遇到的错误:
    1,    "babel-core": "^6.26.3"和"babel-loader": "^7.1.5"版本不兼容,按照报错提示再次安装即可
    2,webpack.config.js文件的module属性配置不对,可以按照官网的方法配置!(即rules,不用loaders)

4,如何将css也弄成模块化(webpack默认只将js文件模块化,图片,css等等得安装loader才可以模块化)
    4-1  安装npm install --save-dev css-loader style-loader
    4-2  配置:在webpack.config.js文件内的module 添加{ test: /.css$/, use: [
                    {loader: 'style-loader' },
                    { loader: 'css-loader'}
                ]}
    4-3    使用:在入口文件中import './css/style.css';
    
5,如何将图片模块化,安装loader
    5-1    安装 npm install --save-dev file-loader
    5-2 配置 {test:/.(jpg|png|gif)$/,use:'file-loader'}
    
    
插件:插件目的在于解决 loader 无法实现的其他事。(前端优化可以想这一点)
1,压缩插件,为了最小化压缩后的代码,提高加载速度
2,webpack4已经升级不支持在plugins里面进行操作,而是放在了optimization里面
3,先安装这个插件 npm install --save-dev uglifyjs-webpack-plugin
4,配置 :在webpack.config.js
    var UglifyJsPlugin = require('uglifyjs-webpack-plugin');
    optimization: {
            minimizer: [
                new UglifyJsPlugin({
                    uglifyOptions: {
                        output: { comments: false, } //去除注释
                    }
                })
            ]
        }

5,定位错误插件
module.exports = {
    devtool: 'eval-source-map'
}

6,webpack-dev-server
        webpack-dev-server 是一个简单的 web 服务器,在代码修改后能重新构建代码并且
        刷新浏览器。
    //安装    npm install --save-dev webpack-dev-server
    //配置    module.exports = {
                devServer: {
                contentBase: './dist' // 服务器服务目录
                }
            }
            //配置 package.json
            "scripts":{"start": "webpack-dev-server --open"}
            
            

利用 vue 脚脚手架开发 手架开发企企业级应 业级应用
    # 全局安装 vue-cli
     npm install --global vue-cli
    # 创建一个基于 webpack 模板的新项目
     vue init webpack my-project
    # 安装依赖,走你
     cd my-project
     npm install
     npm run start
    
    安装会出现如下选项,如下选择即可:
    ? Project name app03
    ? Project description sc html
    ? Author kuangbin <981393967@qq.com>
    ? Vue build standalone
    ? Install vue-router? Yes
    ? Use ESLint to lint your code? No
    ? Set up unit tests No
    ? Setup e2e tests with Nightwatch? No

    node_modules文件夹有什么用:
        首先要说明,devDependencies与Dependencies都是依赖。你用npm install就会把里面二者所有的模块都安装到node_modules。
        那为什么还要个devDependencies呢,这里,devDependencies一般用来放一些对项目运行无用,但能帮助开发的依赖(如测试模块),在实际生产环境中执行npm install --production就只安装Dependencies里的模块,而不会安装devDependencies的模块。

    编写项目所需的其它依赖:
    npm install element-ui jquery vuex moment(日期格式处理)--save    //--save才会保留在package.json中

结合vuex:
    默认情况下,模块内部的 action、mutation 和 getter 是注册在全局命名空间的——这样使得多个模块能够对同一 mutation 或 action 作出响应。
    state模块化他不会为全局声明的,其余是全局声明。
    可以调用getter方法,而不直接调用state获取数据(要用命名空间才可以),但是要避免方法名重复!!!,因为都当做全局声明。

App.vue 主视图
index.html 是我们的首页

如何写一个登陆页面以及结合增删改查?
1,app.vue不用动,它包含公共部分,然后添加其他组件,放在这个公共app.vue即可,只需用<router-view/>
2,在router js文件中写上对应的路由映射,记住子路由可以嵌套!
3,写增删改查页面体悟:只需一个saveOrUpdate方法即可,模态框能重复利用就不用重复写!
4,登陆之后应该把登陆数据放在store(公共)中,index页面就根据store的数据进行对应登入者展示
5,注册思想也一致
6,注意后台传null给前台的话,是转化为"空"字符串,因为家里responseBody!(以后判断为:data!=null&&data!=""就不会错)

原文地址:https://www.cnblogs.com/wskb/p/11490835.html