美文网首页
Vue.js,学习心得(十四)组件四

Vue.js,学习心得(十四)组件四

作者: 战神飘雪 | 来源:发表于2017-11-09 18:20 被阅读36次

    学习心得,
    组件(四),

    直接上代码了

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>组件四杂项</title>
        <script src="../js/vue.js"></script>
    </head>
    <body>
    <!--杂项-->
    
    <!--编写可复用组件-->
    
    <!--在编写组件时,最好考虑好以后是否要进行复用。-->
    <!--一次性组件间有紧密的耦合没关系,但是可复用组件应当定义一个清晰的公开接口,同时也不要对其使用的外层数据作出任何假设。-->
    <!--Vue 组件的 API 来自三部分——prop、事件和插槽:-->
    <!--Prop 允许外部环境传递数据给组件;-->
    <!--事件允许从组件内触发外部环境的副作用;-->
    <!--插槽允许外部环境将额外的内容组合在组件中。-->
    <!--使用 v-bind 和 v-on 的简写语法,模板的意图会更清楚且简洁:-->
        <my-component
            v-bind:foo = "baz"
            v-bind:bar = "qux"
            v-on:event-a = "doThis"
            v-on:event-b = "doThat"
        >
            <img slot="icon" src="#" >
            <p slot="main-text">Hello!</p>
        </my-component>
    <!--子组件引用-->
    
    <!--尽管有 prop 和事件,但是有时仍然需要在 JavaScript 中直接访问子组件。-->
    <!--为此可以使用 ref 为子组件指定一个引用 ID。例如:-->
    <div id="parent">
        <user-profile ref="profile"></user-profile>
    </div>
    <hr>
    <script>
        Vue.component('my-component',{
            template:''
        });
        Vue.component('user-profile',{
            template:'<p></p>'
        });
        var parent = new Vue({ el: '#parent'})
        // 访问子组件实例
        var child = parent.$refs.profile
        //当 ref 和 v-for 一起使用时,获取到的引用会是一个数组,包含和循环数据源对应的子组件。
        //$refs 只在组件渲染完成后才填充,并且它是非响应式的。
        // 它仅仅是一个直接操作子组件的应急方案——应当避免在模板或计算属性中使用 $refs。
    </script>
    
    <div id="app-1">
        <async-example>
    
        </async-example>
    </div>
    <hr>
    <script>
    //    异步组件
    //
    //    在大型应用中,我们可能需要将应用拆分为多个小模块,按需从服务器下载。
    //为了进一步简化,Vue.js 允许将组件定义为一个工厂函数,异步地解析组件的定义。
    //Vue.js 只在组件需要渲染时触发工厂函数,并且把结果缓存起来,用于后面的再次渲染。
    //例如:
        Vue.component('async-example',function(resolve,reject){
            setTimeout(function(){
                //将组建定义传入resolve
                resolve({
                    template:'<div>I am async!</div>'
                })
            },1000)
        });
        var app1 = new Vue({
            el:'#app-1'
        });
    
    </script>
    <div id="app-2">
        <async-webpack-example>
    
        </async-webpack-example>
    </div>
    <hr>
    <script>
        //工厂函数接收一个 resolve 回调,在收到从服务器下载的组件定义时调用。
        //也可以调用 reject(reason) 指示加载失败。
        //这里使用 setTimeout 只是为了演示,实际上如何获取组件完全由你决定。
        //推荐配合 webpack 的代码分割功能 来使用:
    
    //    Vue.component(
    //        'async-webpack-example',function(resolve){
    //            // 这个特殊的 require 语法告诉 webpack
    //            // 自动将编译后的代码分割成不同的块,
    //            // 这些块将通过 Ajax 请求自动下载。
    //            require(['./my-async-component'],resolve)
    //        });
    //    var app2 = new Vue({
    //        el:'#app-2'
    //    });
    
    
    //    你可以在工厂函数中返回一个 Promise,所以当使用 webpack 2 + ES2015 的语法时可以这样:
    //Vue.component(
    //    'async-webpack-example',
    //    // 该 `import` 函数返回一个 `Promise` 对象。
    //    () => import('./my-async-component')
    //    )
    
    
    //    当使用局部注册时,也可以直接提供一个返回 Promise 的函数:
    //new Vue({
    //    // ...
    //    components: {
    //        'my-component': () => import('./my-async-component')
    //}
    //    })
    
    //    如果你是 Browserify 用户,可能就无法使用异步组件了,
    //    它的作者已经表明 Browserify 将“永远不会支持异步加载”。
    //    Browserify 社区发现了一些解决方法,可能会有助于已存在的复杂应用。
    //    对于其他场景,我们推荐使用 webpack,因为它对异步加载进行了内置、全面的支持。
    </script>
    
    
    <script>
    //    高级异步组件
    //
    //    2.3.0 新增
    //    自 2.3.0 起,异步组件的工厂函数也可以返回一个如下的对象:
    
    //const AsyncComp = () => ({
    //// 需要加载的组件。应当是一个 Promise
    //        component: import('./MyComp.vue'),
    //// 加载中应当渲染的组件
    //        loading: LoadingComp,
    //// 出错时渲染的组件
    //        error: ErrorComp,
    //// 渲染加载中组件前的等待时间。默认:200ms。
    //        delay: 200,
    //// 最长等待时间。超出此时间则渲染错误组件。默认:Infinity
    //        timeout: 3000
    //    })
    
    //    注意,当一个异步组件被作为 vue-router 的路由组件使用时,
    //这些高级选项都是无效的,因为在路由切换前就会提前加载所需要的异步组件。
    //另外,如果你要在路由组件中使用上述写法,需要使用 vue-router 2.4.0 以上的版本。
    </script>
    <script>
    //    组件命名约定
    //
    //    当注册组件 (或者 prop) 时,可以使用 kebab-case (短横线分隔命名)、camelCase (驼峰式命名) 或 PascalCase (单词首字母大写命名)。
    //    // 在组件定义中
    //    components: {
    //        // 使用 kebab-case 注册
    //        'kebab-cased-component': { /* ... */ },
    //        // 使用 camelCase 注册
    //        'camelCasedComponent': { /* ... */ },
    //        // 使用 PascalCase 注册
    //        'PascalCasedComponent': { /* ... */ }
    //    }
    //    在 HTML 模板中,请使用 kebab-case:
    //    <!-- 在 HTML 模板中始终使用 kebab-case -->
    //    <kebab-cased-component></kebab-cased-component>
    //    <camel-cased-component></camel-cased-component>
    //    <pascal-cased-component></pascal-cased-component>
    //    当使用字符串模式时,可以不受 HTML 大小写不敏感的限制。
    // 这意味实际上在模板中,你可以使用下面的方式来引用你的组件:
    //kebab-case
    //    camelCase 或 kebab-case (如果组件已经被定义为 camelCase)
    //    kebab-case、camelCase 或 PascalCase (如果组件已经被定义为 PascalCase)
    //    components: {
    //        'kebab-cased-component': { /* ... */ },
    //        camelCasedComponent: { /* ... */ },
    //        PascalCasedComponent: { /* ... */ }
    //    }
    //    <kebab-cased-component></kebab-cased-component>
    //    <camel-cased-component></camel-cased-component>
    //    <camelCasedComponent></camelCasedComponent>
    //    <pascal-cased-component></pascal-cased-component>
    //    <pascalCasedComponent></pascalCasedComponent>
    //    <PascalCasedComponent></PascalCasedComponent>
    //    这意味着 PascalCase 是最通用的声明约定而 kebab-case 是最通用的使用约定。
    //如果组件未经 slot 元素传入内容,你甚至可以在组件名后使用 / 使其自闭合:
    //    <my-component/>
    //    当然,这只在字符串模板中有效。因为自闭的自定义元素是无效的 HTML,浏览器原生的解析器也无法识别它。
    </script>
    <script>
    //    递归组件
    //
    //    组件在它的模板内可以递归地调用自己。不过,只有当它有 name 选项时才可以这么做:
    //name: 'unique-name-of-my-component'
    //    当你利用 Vue.component 全局注册了一个组件,全局的 ID 会被自动设置为组件的 name。
    //Vue.component('unique-name-of-my-component', {
    //    // ...
    //})
    //    如果稍有不慎,递归组件可能导致死循环:
    //name: 'stack-overflow',
    //    template: '<div><stack-overflow></stack-overflow></div>'
    //    上面组件会导致一个“max stack size exceeded”错误,所以要确保递归调用有终止条件 (比如递归调用时使用 v-if 并最终解析为 false)。
    </script>
    <script>
    //    组件间的循环引用
    //
    //    假设你正在构建一个文件目录树,像在 Finder 或资源管理器中。你可能有一个 tree-folder 组件:
    //    <p>
    //    <span>{{ folder.name }}</span>
    //    <tree-folder-contents :children="folder.children"/>
    //        </p>
    //    以及一个 tree-folder-contents 组件:
    //    <ul>
    //    <li v-for="child in children">
    //        <tree-folder v-if="child.children" :folder="child"/>
    //        <span v-else>{{ child.name }}</span>
    //    </li>
    //    </ul>
    //    当你仔细看时,会发现在渲染树上这两个组件同时为对方的父节点和子节点——这是矛盾的!
    // 当使用 Vue.component 将这两个组件注册为全局组件的时候,框架会自动为你解决这个矛盾。如果你已经是这样做的,就跳过下面这段吧。
    //然而,如果你使用诸如 webpack 或者 Browserify 之类的模块化管理工具来 require/import 组件的话,就会报错了:
    //Failed to mount component: template or render function not defined.
    //        为了解释为什么会报错,简单的将上面两个组件称为 A 和 B。模块系统看到它需要 A,但是首先 A 需要 B,但是 B 需要 A,而 A 需要 B,循环往复。
    // 因为不知道到底应该先解析哪个,所以将会陷入无限循环。要解决这个问题,我们需要在其中一个组件中告诉模块化管理系统:“A 虽然最后会用到 B,但是不需要优先导入 B”。
    //在我们的例子中,可以选择让 tree-folder 组件中来做这件事。
    // 我们知道引起矛盾的子组件是 tree-folder-contents,所以我们要等到 beforeCreate 生命周期钩子中才去注册它:
    //beforeCreate: function () {
    //    this.$options.components.TreeFolderContents = require('./tree-folder-contents.vue')
    //}
    //    问题解决了!
    </script>
    
    <script>
    //    内联模板
    //
    //    如果子组件有 inline-template 特性,组件将把它的内容当作它的模板,而不是把它当作分发内容。这让模板编写起来更灵活。
    //    <my-component inline-template>
    //    <div>
    //    <p>这些将作为组件自身的模板。</p>
    //    <p>而非父组件透传进来的内容。</p>
    //    </div>
    //    </my-component>
    //    但是 inline-template 让模板的作用域难以理解。使用 template 选项在组件内定义模板或者在 .vue 文件中使用 template 元素才是最佳实践。
    </script>
    
    <!--X-Template-->
    
    <!--另一种定义模板的方式是在 JavaScript 标签里使用 text/x-template 类型,并且指定一个 id。例如:-->
    <script type="text/x-template" id="hello-world-template">
        <p>Hello hello hello</p>
    </script>
    <script>
        Vue.component('hello-world', {
            template: '#hello-world-template'
        })
    //    这在有很多大模板的演示应用或者特别小的应用中可能有用,其它场合应该避免使用,因为这将模板和组件的其它定义分离了。
    </script>
    
    <script>
    //    对低开销的静态组件使用 v-once
    //
    //    尽管在 Vue 中渲染 HTML 很快,不过当组件中包含大量静态内容时,可以考虑使用 v-once 将渲染结果缓存起来,就像这样:
    //Vue.component('terms-of-service', {
    //    template: '\
    //    <div v-once>\
    //      <h1>Terms of Service</h1>\
    //      ...很多静态内容...\
    //    </div>\
    //  '
    //})
    </script>
    </body>
    </html>
    

    相关文章

      网友评论

          本文标题:Vue.js,学习心得(十四)组件四

          本文链接:https://www.haomeiwen.com/subject/sdemmxtx.html