1 Star 0 Fork 1

tom/vue-learning

forked from 孙烨/vue-learning 
加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
该仓库未声明开源许可证文件(LICENSE),使用请关注具体项目描述及其代码上游依赖。
克隆/下载
贡献代码
同步代码
取消
提示: 由于 Git 不支持空文件夾,创建文件夹后会生成空的 .keep 文件
Loading...
README
第一天:webpack vue前置知识点
    一:webpack基本使用
        1.新建基本src目录index.html index.js文件
        2.npm init -y 创建package.json文件 
        3.npm install jquery -S 安装jQuery,会记录到package.json文件
        4.import $ from 'jquery' 通过es6方法导入jQuery到index.js  
        5.npm install webpack webpack-cli -D 安装webpack并记录到package.json文件
        6.根目录中创建webpack.config.js的webpack配置文件
            module.exports = {
                mode: 'development' //webpack运行模式,开发环境一般使用development  生产中用production
            }
        7.package.json中的scripts节点下增加dev脚本:
        8.npm run dev运行webpack再目录下生成../dist/main.js包含了index.js和jQuery.js
        9.index.html中引入生成的main.js即可
    二:webpack配置文件进一步使用
        1.webpack默认打包的main.js并未做压缩,仍然保留注释以及换行等
        2.将webpack.config.js中的mode模式由development设置为production
        3.重新运行webpack脚本 npm dev
    三:webpack执行说明:
        1.npm run dev 执行的是package.json中的script脚本中的dev所对应的webpack命令
        2.执行webpack命令会到webpack.config.js中按照mode所指定的模式进行打包
        3.如果webpack.config.js不做指定配置,webpack版本4/5会默认寻找../src/index.js,默认输出到../dist/main.js
        4.自定义输入输出再webpack.config.js配置文件中通过entry和output节点指定出入口,
            使用path变量需要先导包const path = require('path') __dirname表示当前文件的路径
            一般entry写法   entry: path.join(__dirname,'./src/index1.js')
            一般output写法  
    四:每次修改源码需要重新npm run dev才能生效问题处理
        1.自动打包配置插件 webpack-dev-server监听项目代码变动并执行重新发包
        2.安装命令 npm install webpack-dev-server -D
        3.package.json中script脚本中的dev改为"dev": "webpack serve"
        4.执行npm run dev 并发现项目一直启动并监听修改,每次修改都会重新打包
        问题:打开之后get无法请求
            配置webpack.config.js增加devServer节点指定根目录
                devServer: {
                    static: "./",
                },
        问题:打开之后需要点击src才能进入页面
            安装html-webpack-plugin插件
                npm instal html-webpack-plugin -D
            配置webpack.config.js
                1.const HtmlPlugin = require('html-webpack-plugin')//导入html插件获得构造函数
                2.//通过构造函数创建html插件的实例对象
                const html = new HtmlPlugin({
                    template:'./src/index.html',//需要复制的页面
                    filename:'./index.html'//需要复制到的位置
                });
                3.module.exports = {
                    //需要执行的插件数组
                    plugins:[html]
                }
        问题:npm run dev之后不能自动打开浏览器..
            配置webpack.config.js中增加devServer节点
                devServer:{
                    open:true,
                    port:80
                }
    五:webpack loader加载器介绍
        1.webpack默认只能处理.js结尾的文件其他非.js需要对应的loader来进行处理
        2.webpack打包-判断js模块-是否包含高级js语法,通过webpack处理或使用babel寻找loader处理
                            -寻找对应的loader模块
        3.如果在js中使用import导入css文件会导致
            ERROR in ./src/css/index.css 1:3
            Module parse failed: Unexpected token (1:3)
            You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file.
        4.安装支持css文件的loader
            npm i style-loader css-loader -D
            webpack.config.js中的module节点中的rules数组增加匹配规则
                module: {
                    rules:[
                        //定义不同模块对应的loader,有顺序的 style-loader处理完交给css-loader,全都处理完之后交付给webpack并打包到内存中
                        {test: /\.css$/,use:['style-loader','css-loader']},
                    ]
                }
        5.安装支持less文件的loader
            npm i less-loader less -D
            webpack.config.js中的module节点中的rules数组增加匹配规则
                {test: /\.less$/,use:['style-loader','css-loader','less-loader']}
        6.安装支持文件和url的loader
            npm i url-loader file-loader -D
            //大于500字节的数据转为base64处理
            {test: /\.jpg|png|gif$/,use:['url-loader?limit=500']}
        7.部分高级js语法webpacket默认可能也不能处理,比如@装饰器
            安装babel-loader 
            npm i babel-loader @babel/core @babel/plugin-proposal-decorators @babel/plugin-proposal-class-properties -D
            配置加载器,排除第三方包不要对他们做更改
            {test: /\.js$/,use:['babel-loader'],exclude:/node_modules/}
            创建配置文件,根目录下创建bebel.config.js加载babel插件
                module.exports = {
                    "plugins": [
                        ["@babel/plugin-proposal-decorators", { "version": "legacy" }],
                        "@babel/plugin-proposal-class-properties"
                    ]
                }
    六:项目build打包上线
        1.将内存中的文件放到磁盘中
            package.json的script节点增加build命令并加上参数,否则会读取配置文件中的参数开发环境一般为developement
                "build":"webpack --mode production"
        2.装个clean工具能自动把打包文件给删除
            npm.js官网找一下参照文档装clean-webpack-plugin
            使用的时候需要确保输出目录不被占用,否则不会被自动clean
    七:SourceMap的使用
        1.用于储存webpacket打包前后文件的位置信息,便于找到原位置
        2.webpack.config.js中mode同级增加参数
            devtool: 'eval-source-map',//开发调试阶段通过sorceMap使得打包后和打包前行号保持一致
            使得开发中可以通过控制台定位到源代码的位置
        3.webpack.config.js中mode同级增加参数
            devtool: 'nosources-source-map',//发布阶段通过sorceMap使得打包后和打包前行号保持一致
            但不可以通过控制台定位到源代码的位置
        4.webpack.config.js中mode同级增加参数
            devtool: 'source-map',//发布阶段通过sorceMap使得打包后和打包前行号保持一致
            并且可以通过控制台定位到源代码的位置
    八:webpacket的真实配置
        1.webpack工作环境中有工具一键生成
        上面介绍只做原理介绍,实际中开发很少直接进行修改....
        2.拓展@
            前端路径可能比较复杂,如果使用相对路径会比较凌乱
            一般约定使用@表示项目src路径,统一使用@路径由外往里找而不是使用相对路径由某个点开始
            配置:
                webpack.config.js
                新增 resolve 节点声明 alias 属性增加键值对 '@':path.join(__dirname,'./src/')
                    resolve:{
                        alias:{
                            '@':path.join(__dirname,'./src/')
                        }
                    }
    九:安装vue.js devtools调试工具
        这是一个浏览器插件,安装完需要配置允许访问文件url
第二天:了解vue
    一:vue介绍
        1.概念:构建用户界面的前端框架
            包括指令、组件、路由、vueX、组件库等...
        2.特性:
            数据驱动视图-vue监听数据变化来渲染页面结构,此为单向数据改变引起页面改变
            双向数据绑定-在网页中from表单负责采集数据,ajax负责佛则提交数据写表单时数据变化奖备案too
        3.MVVVM
            model:数据源
            view:当前页面的dom结构
            viewModel:vue的实例,检测model和view并做同步或更新,是核心
    二:vue基本使用
        1.使用步骤:
            1.导入vue.js的脚本
                <script src="./lib/vue-2.7.10.js"></script>
            2.创建vue实例对象
                const vm =  new Vue({
                    /* 当前vm实例需要控制的dom区域,el的值是一个选择器 */
                    el: '#app',
                    /* data 需要渲染到页面的数据 */
                    data:{
                        username:'zhangsan',
                    },
                });
            3.使用vue为需要的dom元素填充数据
                <div id="app">{{ username }}</div>
        2.指令:
            vue的模板语法,辅助开发渲染页面基本结构共有六类都很重要也很简单基础
            内容渲染、属性绑定、事件绑定、双向绑定、条件渲染、列表渲染
            1.内容渲染指令:{{}}
                1.v-text 渲染文本内容 覆盖原始内容
                    <!-- 将要被vue控制的div,把数据填充过来 -->
                    <div id="app">
                        <p v-text="username"></p>
                        <p v-text="gender">性别</p>
                    </div>
                    <script src="./lib/vue-2.7.10.js"></script>
                    <script>
                    const vm =  new Vue({
                        el: '#app',
                        data:{
                            username:'zhangsan',
                            gender:'女',
                            
                        },
                    });
                    </script>
                2.{{}} 插值表达式 渲染文本内容 不会覆盖原始内容
                    <p >姓名 {{username}}</p>
                    <p >性别 {{gender}}</p>
                3.v-html 渲染标签内容
                    info:'<h4 style="color:red;font-weight:bold;">高级消息...</>'
                    <div v-html="info"></div>
            2.属性绑定指令:v-bind:  简写 :
                -----------------------分割线---------
                此处先暂停,先补充一下node.js相关知识点
                --------------------------------------
                回来了^_^,node.js可查看 https://gitee.com/qq2528825468/node-js-learn
                --------------------------------------
                1.原因:插值表达式只能用于标签内容节点中,不能用于标签属性节点
                2.使用:v-bind:  (可省略只写:)
                        <!-- 将要被vue控制的div,把数据填充过来 -->
                        <div id="app">
                            <input type="text" v-bind:placeholder=tips>
                        </div>
                        <script src="./lib/vue-2.7.10.js"></script>
                        <script>
                        const vm =  new Vue({
                            el: '#app',
                            data:{
                                tips:'请输入用户名',
                            },
                        });
                        </script>
                3.运算
                    模板渲染中可进行简单的运算处理
                        {{number+1}}
                        {{ok?'YES':'NO'}}
                        {{message.split('').reverse().join('')}}
                        <div v-bind:id="'list-'+id"></div>
            3.事件绑定指令v-on: 简写 @
                1.需要绑定事件处理函数使用
                2.使用 v-on:
                        <!-- 将要被vue控制的div,把数据填充过来 -->
                        <div id="app">
                            <p> count的值:{{count}}</p>
                            <button v-on:click="add()">+n</button>
                        </div>
                        <script src="./lib/vue-2.7.10.js"></script>
                        <script>
                            /* vue实例对象 */
                        const vm =  new Vue({
                            /* el指定页面控制区域 */
                            el: '#app',
                            /* 控制区域内所需要渲染的数据 */
                            data:{
                                count:1,
                            },
                            /* 控制区域所需要渲染的事件处理函数 */
                            methods: {
                                add(n) {
                                    this.count++
                                }
                            },
                        });
                        </script>
                3.获取原生DOM事件的事件对象
                    传参时 不传参或者使用 $event, 表示获取原生DOM事件的事件对象
                4.事件修饰符
                    vue用于在事件绑定时对元素标签动作的修饰
                        <!-- 单击事件将停止传递 -->
                        <a @click.stop="doThis"></a>

                        <!-- 提交事件将不再重新加载页面 -->
                        <form @submit.prevent="onSubmit"></form>

                        <!-- 修饰语可以使用链式书写 -->
                        <a @click.stop.prevent="doThat"></a>

                        <!-- 也可以只有修饰符 -->
                        <form @submit.prevent></form>

                        <!-- 仅当 event.target 是元素本身时才会触发事件处理器 -->
                        <!-- 例如:事件处理器不来自子元素 -->
                        <div @click.self="doThat">...</div>
                4.按键修饰符
                    <!-- 仅在 `key` 为 `Enter` 时调用 `submit` -->
                    <input @keyup.enter="submit" />

                    Vue 为一些常用的按键提供了别名:
                        .enter
                        .tab
                        .delete (捕获“Delete”和“Backspace”两个按键)
                        .esc
                        .space
                        .up
                        .down
                    .exact 修饰符 修饰符允许控制触发一个事件所需的确定组合的系统按键修饰符
                        <!-- 当按下 Ctrl 时,即使同时按下 Alt 或 Shift 也会触发 -->
                        <button @click.ctrl="onClick">A</button>

                        <!-- 仅当按下 Ctrl 且未按任何其他键时才会触发 -->
                        <button @click.ctrl.exact="onCtrlClick">A</button>

                        <!-- 仅当没有按下任何系统按键时触发 -->
                        <button @click.exact="onClick">A</button>
                    鼠标按键修饰符:
                        .left
                        .right
                        .middle
                        <button @click.right="shout(1)">ok</button>
            4.表单输入绑定指令
                1.用于表单标签和js变量进行双向数据绑定
                    <input v-model="text"> input中实时展示text数据
                    非表单标签,虽然可以展示数据但用户不能修改数据,所以双向数据绑定并无实际意义
                2.修饰符:
                    .lazy
                        默认情况下,v-model 会在每次 input 事件后更新数据 (IME 拼字阶段的状态例外)。
                        你可以添加 lazy 修饰符来改为在每次 change 事件后更新数据:
                        <!-- 在 "change" 事件后同步更新而不是 "input" -->
                        <input v-model.lazy="msg" />
                    .number
                        如果你想让用户输入自动转换为数字,你可以在 v-model 后添加 .number 修饰符来管理输入:
                        如果该值无法被 parseFloat() 处理,那么将返回原始值。
                        number 修饰符会在输入框有 type="number" 时自动启用。
                        <input v-model.number="age" />
                    .trim
                        如果你想要默认自动去除用户输入内容中两端的空格,你可以在 v-model 后添加 .trim 修饰符:
                        <input v-model.trim="msg" />
            5.条件渲染指令
                1.v-if v-show
                    1.用法
                        <div id="app">
                            <p v-if="flag_view">v-if 控制的数据</p>
                            <p v-show="flag_view">v-show 控制的数据</p>
                        </div>
                        <script>
                        /* vue实例对象 */
                        const vm =  new Vue({
                            /* el指定页面控制区域 */
                            el: '#app',
                            /* 控制区域内所需要渲染的数据 */
                            data:{
                                /* flag_view true展示数据 false隐藏数据 */
                                flag_view:true
                            },
                            /* 控制区域所需要渲染的事件处理函数 */
                            methods: {
                            },
                        });
                        </script>
                    2.区别
                        v-if使用的是真实标签是否存在
                        v-show使用的是标签的css样式 display 属性值的切换
                        总的来说,v-if 有更高的切换开销,而 v-show 有更高的初始渲染开销。
                        因此,如果需要频繁切换,则使用 v-show 较好
                        如果在运行时绑定条件很少改变,则 v-if 会更合适。
                    3.<template> 上的 v-if 
                    
                    (----------------!!!存疑,在html中这样写是不可以的)
                    
                        因为 v-if 是一个指令,他必须依附于某个元素。但如果我们想要切换不止一个元素呢?
                        在这种情况下我们可以在一个 <template> 元素上使用 v-if,这只是一个不可见的包装器元素,
                        最后渲染的结果并不会包含这个 <template> 元素。
                            <template v-if="ok">
                            <h1>Title</h1>
                            <p>Paragraph 1</p>
                            <p>Paragraph 2</p>
                            </template>
            6.列表渲染指令
                1.v-for
                    我们可以使用 v-for 指令基于一个数组来渲染一个列表。
                    v-for 指令的值需要使用 item in items 或者  (item in items) in items
                    形式的特殊语法,其中 items 是源数据的数组,而 item 是迭代项的别名:
                    <tbody>
                        <tr v-for="(item,index) in list">
                            <td>{{index}}</td>
                            <td>{{item.id}}</td>
                            <td>{{item.name}}</td>
                        </tr>
                    </tbody>
                    
                    data:{
                        list:[
                            {id:1,name:'孙烨'},
                            {id:2,name:'孙花花'}
                        ]
                    },              
                2.说明
                    v-for 的默认方式是尝试就地更新元素而不移动它们。要强制其重新排序元素,你需要用特殊 attribute key 来提供一个排序提示:
                    不要用index作为key值,index是数据在生成之后的顺序值,如果数据变化(或者排序)那么数据所对应的index就会被改变      
                    例如: <li v-for="item in list" :key="item.id">name is : {{item.name}} </li>
        3.过滤器
            1.说明:
                过滤器只在vue2中存在,过滤器可串联调用并可进行传参,vue3已删除该功能,该部分不做详细说明
                在 3.x 中,过滤器已移除,且不再支持。取而代之的是,官方建议用方法调用或计算属性来替换它们。
                https://v3-migration.vuejs.org/zh/breaking-changes/filters.html
            2.全局过滤器:
                new vue实例之前挂载到vue构造函数上面
            3.局部过滤器:
                vue实例初始化之后通过filters属性挂载到实例中
                局部过滤器优先级高于全局过滤器
        4.侦听器watch
            1.说明:
                用于监听数据的变化,watch中声明,可进行函数式声明或者对象式声明
                new Vue({
                    /* 监听器 */
                    watch:{
                        /* 方法形式的监听器-不能页面初始化时进行触发 */
                        message(newVal,oldVal){
                            console.log(newVal+"方法形式的监听器"+oldVal)
                            }
                        },
                        message:{
                            handler: function(newVal,oldVal){
                                console.log(newVal+"对象形式的监听器"+oldVal)
                            },
                            immediate:true, /*初始化时是否调用*/
                            deep: true /* 深度监听,监听对象的每一个属性的变化 */
                        }
                    })
            2.深层侦听
                直接给 watch() 传入一个响应式对象,会隐式地创建一个深层侦听器——该回调函数在所有嵌套的变更时都会被触发
            3.属性监听
                如果要监听对象的某个属性,可以直接声明
                用小括号将监听器方法包起来
                'user.name'(newVal,oldVal){}
        5.计算属性
            1.说明:
                定义到computed节点下,定义为方法形式,使用为数据形式
            2.示例:
                <input type="text" v-model="message">
                <p>{{this.myComputed}}</p>          
                
                data:{
                    message:"hello vue.js",
                },
                computed:{
                    myComputed:function(){
                        return `plus- ${this.message}`
                    }
                }
        5-1.axios
            1.说明:
                基于 promise 网络请求库,作用于node.js 和浏览器中  
            2.使用:
                普通使用和async-await使用
                https://www.axios-http.cn/docs/example
            3.解构赋值
                1.直接使用
                    const username = {id:123,username:"lihua"}.username
                    等同于
                    const {username} = {id:123,username:"lihua"}
                2.重命名
                    const name = {id:123,username:"lihua"}.username
                    等同于
                    const {username:name} = {id:123,username:"lihua"}
        6.vue-cli
            1.单页面应用程序
                一个前端项目,只有一个html页面
            2.说明:
                vue-cli简化了webpack创建项目的过程
                可以专注于编写应用程序,而不是花费数天时间争论配置
            3.使用:
                npm install -g @vue/cli
                vue create demo-first
                选组件
                npm run serve
            4.目录结构
                public-图标和首页HTML
                src-源代码
                    assets-静态资源
                    components-组件
                main.js-入口文件
                APP.vue-项目根组件
            5.vue的本质作用:
                通过main.js将App.vue的内容渲染到inde.html中
        7.vue组件
            1.说明:
                将页面可以重用的ui结构封装为组件达到复用的目的
                vue支持组件化开发,后缀名为.vue,默认的APP.vue就是一个组件
            2.组成:
                template模板结构
                script  js行为
                style 组件的样式,有默认的结构且data需要以函数的形式出现,如果使用less则style中增加lang="less"
            3.父子关系:
                嵌套的使用组件,组件和组件间形成了父子关系或者兄弟关系
            4.组件的使用
                1.父组件中import导包子组件
                2.在components节点中注册组件
                3.以标签的形式使用子组件
                    import left from '@/components/left.vue'
                    import right from '@/components/right.vue'

                    export default {
                    components:{
                        left,right_reName:right
                    },

                    <left_name></left_name>
                    <right_reName></right_reNames>
            5.私有组件:
                通过在components节点中注册组件都是私有组件
                A components B
                B只能在A中使用
            6.全局组件
                main.js中使用Vue.component()方法进行注册
                示例main.js:
                    import Global from '@/components/gloable.vue'
                    Vue.component('Global_name',Global)
            7.props
                组建的自定义属性,合理利用可提高组件复用性,props是只读的应避免直接对其进行修改,应转存到data数据进行修改
                props节点下增加自定义属性
                示例:
                    export default {
                        props:['init'],
                    }

                    <Global_name init="App参数props"></Global_name>
                也可以使用复杂形势
                    所有 prop 默认都是可选的,除非声明了 required: true
                    type 数据类型
                    default 默认的初始值
                    export default {
                    props:{
                        init:{
                            default:"default_name",
                            type:number
                            required: true
                        }
                    },
            8.样式冲突
                <style lang="less" scoped>
                scoped,则当前组件的所有标签会生成唯一属性,防止组件间样式相互影响
                如果父组件引用子组件后,父组件需要修改子组件样式
            9.deep的使用
                使用 scoped 后,父组件的样式将不会渗透到子组件中
                处于 scoped 样式中的选择器如果想要做更“深度”的选择,也即:影响到子组件,可以使用 :deep() 这个伪类:
        8.生命周期:
            1.说明:
                组件从创建、运行、销毁的过程
                通过声明周期函数,可在声明周期各个时间点去执行某些事件
                创建:new vue->before-create->created->before-mount-mounted
                运行:before-update->updated
                销毁:before-destroy->destroyed
            2.使用:
                常在created阶段进行ajax请求将数据转存到data供页面渲染使用
                常在mounted阶段操作dom元素
        9.数据共享
            1.父向子组件之间数据共享
                自定义属性:父组件使用子组件,通过props 进行数据传递
            2.子向父组件之间数据共享
                子组件通过this.$emit('事件名',需要传输数据)触发自定义事件
                父组件中通过标签属性@事件名="事件函数"进行监听数据
                mounted(){
                /* 生命周期中将数据传到父组件 */
                this.$emit("myEmit",this.username)
                }

                <right_name @myEmit="showData"></right_name>
                  methods: {
                    showData(val){
                    console.log(val)
                    }
                },
            3.子组件和子组件之间数据共享
                1.bus.vue,数据传输对象
                    <script>
                    import Vue from 'vue'

                    export default new Vue()
                    </script>
                2.数据发送方,触发自定义事件
                    import busVue from './bus.vue';
                    busVue.$emit('share',this.username)
                3.数据接收方,监听自定义事件
                    import busVue from './bus.vue';
                    busVue.$on('share',function(val){
                        console.log('接受share数据'+val)
                    })

        10.ref引用:
            1.说明:
                辅助开发者不依赖jquery的情况下,获取dom元素或组件的引用
            2.使用:
                在html标签或者组件标签上使用ref="ref_name"标记
                则在vue实例中可用this.$refs中找到所标记的引用标签
            3.场景:
                使用ref的方式,可以方便的在父组件中修改子组件的数据...
                比起props或者bus或者$emit传值要简单得多
            4.延迟:
                ref引用改变之后可能涉及到页面重新渲染,某些代码可能需要在渲染结束之后才应执行
                可以使用this.$nextTick(function(){需要延迟到渲染后执行执行的})
        11.js数组复习
            1.foreach循环
                无法被终止,一旦开启遍历会将数据全部遍历结束
            2.some循环
                return true之后会终止循环
            3.every循环
                判断数组每项是否满足一定条件,如果都满足返回true,存在不满足返回false
            4.reduce循环
                reduce函数,如果不指定初始值则初始值为数组第一个元素,从数组1位置开始循环
                指定初始值则从数组0位置开始循环
    三、案例复习
        1.说明:
            下载demo-cart项目并npm install、npm run serve启动项目
            这是一个购物车案例
            如果node版本高于17,需要在package.json中修改scrips标签
            "scripts": {
                "serve": "SET NODE_OPTIONS=--openssl-legacy-provider && vue-cli-service serve",
                "build": "SET NODE_OPTIONS=--openssl-legacy-provider && vue-cli-service build"
            },
        2.实现步骤
            1.初始化项目基本结构
            2.使用header组件
                App.vue中
                    <Header></Header>
                    <h1>App 根组件</h1>
                    import Header from '@/components/Header/Header.vue'
            3.通过axios请求商品列表数据
                get https://www.escook.cn/api/cart
                npm install axios -S
                App.vue中使用axios发请求
                    async initCartList(){
                        const{data:res} = await axios.get('https://www.escook.cn/api/cart')
                        console.log(res)
                    }
                将数据存到data数据中
                    data() {
                        return {
                        //存储获取到的购物车数据,默认为空数组
                        list:[]
                        }
                    },
                    获取数据的函数增加data转存赋值
                    if(res.status===200){
                        this.list  =  res.list
                    }
            4.使用Footer组件
            5.使用Goods组件
            6.使用Count组件
    
    四、深入组件逻辑复用
        1.介绍:
            本节共包含三个主要知识点
            动态组件,实现组件的按需切换
            插槽,使用组件的时候内容节点的使用和渲染
            自定义指令,除了 Vue 内置的一系列指令 (比如 v-model 或 v-show) 之外,Vue 还允许你注册自定义的指令
        2.动态组件:
            通过 Vue 的 <component> 元素和特殊的 is attribute 实现的:默认组件切换会销毁组件
            1.使用:
                    <component is="Left"></component>
                或者和v-bind连用
                    <component :is="comName"></component>
            2.缓存<KeepAlive> 是一个内置组件,它的功能是在多个组件间动态切换时缓存被移除的组件实例
                <keep-alive>
                    <component :is="comName"></component>
                </keep-alive>
            3.对缓存组件的生命周期监听
                组件第一次将会触发created,但是后续激活只会触发activated
                组件失效的时候会触发deactivated
            4.精准控制缓存组件
                默认情况下keep-alive内的所有标签都会被缓存
                但是如果需要对部分组件缓存或者排除部分缓存组件,可以使用include 和 exclude 
                prop 允许组件有条件地缓存。二者都可以用逗号分隔字符串、正则表达式或一个数组来表示:
                示例:
                    <keep-alive exclude="Left">
                        <component :is="comName"></component>
                    </keep-alive>
            5.补充说明:
                exclude、exclude根据组件名称进行排除,第一优先级是根据组件内部显式声明的名称为主
                如果组件内部没有显示声明名称,则使用组件时的注册名称就是组件的声明名称
                组件的注册名称是给vue用的,组件的名称应该是给开发者看的,比如vue调试工具中组件会展示组件名称
        3. 插槽
            1.说明:
                在之前的章节中,我们已经了解到组件能够接收任意类型的 JavaScript 值作为 props,但组件要如何接收模板内容呢?在某些场景中,我们可能想要为子组件传递一些模板片段,让子组件在它们的组件中渲染这些片段。
            2.使用:
                <FancyButton> 组件
                    <FancyButton>
                        Click me! <!-- 插槽内容 -->
                    </FancyButton>
                <FancyButton> 的模板
                    <button class="fancy-btn">
                        <slot></slot> <!-- 插槽出口 -->
                    </button>
            3.插槽的出口slot可以存在多个,通过名称区分,如果不显式声明则name="default",这种带名字的称为具名插槽
                <FancyButton> 组件
                    <template v-slot:mySlot>
                    <FancyButton>
                        Click me! <!-- 插槽内容 -->
                    </FancyButton>
                    </template>
                <FancyButton> 的模板
                    <button class="fancy-btn">
                        <slot name="mySlot"></slot> <!-- 插槽出口 -->
                    </button>
            4.v-slot 有对应的简写 #
                另外子组件的属性可以在父组件中获取到,这种插槽称之为作用于插槽,接受子组件结果时可以通过结构赋值
                <FancyButton> 组件
                    <template v-slot:mySlot="obj">
                    <FancyButton>
                        Click me! <!-- 插槽内容 -->
                        {{obj.msg}}
                    </FancyButton>
                    </template>
                <FancyButton> 的模板
                    <button class="fancy-btn">
                        <slot name="mySlot" msg="hello vue"></slot> <!-- 插槽出口 -->
                    </button>
        4.自定义指令
            1.说明: 
                除了 Vue 内置的一系列指令 (比如 v-model 或 v-show) 之外,Vue 还允许你注册自定义的指令
            2.私有自定义指令使用:
                vue对象中再directives节点下声明私有自定义指令
                    directives:{
                        sunye:{
                        /* 指令第一次和元素绑定时会触发bind函数,参数为所绑定的dom元素对象 */
                        bind:function(el,binding){
                            el.style.color=binding.value
                        }
                        }
                    },

                在标签中使用
                    <h1 v-sunye="colorName">App 根组件</h1>
                    <h1 v-sunye="'green'">App 根组件</h1>
            3.生命周期: 
                自定义指令有一些生命周期-或者称之为钩子函数
                    bind:只调用一次,指令第一次绑定到元素时调用。在这里可以进行一次性的初始化设置。
                    inserted:被绑定元素插入父节点时调用 (仅保证父节点存在,但不一定已被插入文档中)。
                    update:所在组件的 VNode 更新时调用,但是可能发生在其子 VNode 更新之前。指令的值可能发生了改变,也可能没有。但是你可以通过比较更新前后的值来忽略不必要的模板更新 (详细的钩子函数参数见下)。
            4.全局声明:
                将一个自定义指令全局注册到应用层级也是一种常见的做法,用在main.js中
                const app = createApp({})
                // 使 v-focus 在所有组件中都可用
                app.directive('focus', {
                /* ... */
                })

    五、路由:
        1.说明:
            路由就是一个对应关系,哈希地址(锚点地址)和组件的对应关系
            工作方式,就是点击页面路由链接(本质就是A链接或者锚点链接)之后,url地址栏中哈希值发生变化
                    前端路由检测到地址变化,将哈希地址对应的组件渲染到页面上
        2.vue中router的使用
            1.安装vue-router包
                npm i vue-router@3.6.5
            2.创建路由模块
                创建router文件夹和index.js作为路由模块
            3.导入并挂载路由模块 router/index.js
                import Vue from 'vue'
                import VueRouter from 'vue-router'
                const router = new VueRouter()
                Vue.use(VueRouter)
                export default router
                或者在main.js中vue实例化的时候进行声明
                import Vue from 'vue'
                import App from './App.vue'
                import router from '@/router/index.js'
                new Vue({
                    render: h => h(App),
                    router:router
                }).$mount('#app')
            4.声明路由链接和占位符
                <router-view/>占位符标签,进行组件渲染的位置占位
                路由关系在router/index.js中声明
                /* 实例化router对象 */
                const router = new VueRouter({
                routes:[
                        {path:'/Home',component:Home},
                        {path:'/Movie',component:Movie},
                        {path:'/About',component:About}
                        ]
                    }
                )
        3.路由嵌套
            1.模板内容中有自己的(子集)路由连链接
                写法一致,就是套娃而已,使用children属性
                const router = new VueRouter({
                routes:[
                    {path:'/Home',component:Home},
                    {path:'/Movie',component:Movie},
                    {path:'/About',redirect:'/About/tab1',component:About,
                    /* 声明子路由规则 */
                    children:[
                    {path:'tab1',component:tab1},
                    {path:'tab2',component:tab1},
                    ]
                },
        4.动态路由:
            1.处理restfull风格请求,比如说请求 /movie/1 /movie/2 /movie/3
                表示请求中的地址本质上是一个参数
            2.解决,使用路径参数:标记
                /movie/:movieId  即可匹配到url地址 /movie/*
            3.说明:
                不过这里要说明一下,当参数发生变化时,会映射到相同路由
                原来的组件实例会被复用。因为两个路由都渲染同个组件,比起销毁再创建,复用则显得更加高效。
                不过,这也意味着组件的生命周期钩子不会再被调用。
                ---如果对参数的变化需要重新渲染组件,可以通过监听router对象的属性,或者通过导航守卫
            4.router对象
                this.$route.params 可以获取到url中的路径/movie/:id参数信息
                this.$route.query 获取查询参数/movie?id=1使用
                当然一般不这么用,在组件中使用 $route 会使之与其对应路由形成高度耦合
                从而使组件只能在某些特定的 URL 上使用,限制了其灵活性。如果需要获取参数可以开启prop传参
                    路由模块 props:true
                    {path:'/Movie/:id',component:Movie,props:true},
                    vue模块定义参数    
                    props: ["id"],      
        5.导航:
            1.说明:
                除了使用 <router-link> 创建 a 标签来定义导航链接,称为声明式导航
                我们还可以借助 router 的实例方法,通过编写代码来实现比如说js中的location.href,称为编程式导航
            2.编程式导航api
                在 Vue 实例内部,你可以通过 $router 访问路由实例。因此你可以调用 this.$router.push
                router.push(location, onComplete?, onAbort?)
                在3中只有一个参数,所以后两个可选参数不多说明了
                router.push保留历史记录、 router.replace不保留历史记录 和 router.go前进或者后退历史记录 
                跟 window.history.pushState、 window.history.replaceState 和 window.history.go (opens new window)好像
                实际上它们确实是效仿 window.history API 的。
            3.命名路由
                创建路由实例的时候可以指定name
                new VueRouter({
                    routes: [
                        {
                        path: '/user/:userId',
                        name: 'user',
                        component: User
                        }
                    ]
                })
                使用的时候可以通过name调用,而不需要写path 
                router.push({ name: 'user', params: { userId: 123 } })
            4.命名视图
                默认router-view标签只有一个,这也表明只有一个渲染出口
                如果你需要多个,可以对渲染出口视图命名(可以嵌套使用)
                    <router-view class="view one"></router-view>
                    <router-view class="view two" name="a"></router-view>
                    <router-view class="view three" name="b"></router-view>
                    路由实例定义
                    const router = new VueRouter({
                        routes: [
                            {
                            path: '/',
                            components: {
                                default: Foo,
                                a: Bar,
                                b: Baz
                            }
                            }
                        ]
                    })
        6.导航守卫:
            1.说明:
                “导航”表示路由正在发生改变,导航守卫主要用来通过跳转或取消的方式守卫导航。
                这里有很多方式植入路由导航中:全局的,单个路由独享的,或者组件级的。
                --比如说可以控制不登录不能访问服务页面(通过跳转或者取消跳转的方式对导航进行限制)
            2.全局前置守卫
                当一个导航触发时,全局前置守卫按照创建顺序调用。守卫是异步解析执行,此时导航在所有守卫 resolve 完之前一直处于等待中。
                通过router对象进行声明,多在main.js或者router.js中声明
                vue3的next参数作为可选参数,如果使用next需要保证next函数只会被调用一次,否则将进入无限的路由跳转死循环中
                参数:
                to: Route: 即将要进入的目标 路由对象
                from: Route: 当前导航正要离开的路由
                next: Function: 一定要调用该方法来 resolve 这个钩子。
                    const router = createRouter({ ... })
                    router.beforeEach((to, from) => {
                    // ...
                    // 返回 false 以取消导航
                    return false
                    })
        7.demo练习路由
            router-five-admin-example
		8.创建新的项目练习头条
			1.创建项目
				vue create demo-six-toutiao-example
				选择vue2 eslint标准 less预处理样式
				删除生成的组件,清理路由规则
			2.安装 vant 库

空文件

简介

vue学习,教程 黑马vue 展开 收起
JavaScript
取消

发行版

暂无发行版

贡献者

全部

近期动态

加载更多
不能加载更多了
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
JavaScript
1
https://gitee.com/tengtao/vue-learning.git
git@gitee.com:tengtao/vue-learning.git
tengtao
vue-learning
vue-learning
master

搜索帮助