• Vue(四)——使用脚手架(1)


    安装和启动:

    目录

    分析脚手架结构

    render函数

    修改默认配置

    ref属性

    props配置项

    mixin混入 

    插件

    scoped样式


    分析脚手架结构

    脚手架文件结构

    1. ├── node_modules
    2. ├── public
    3. │ ├── favicon.ico: 页签图标
    4. │ └── index.html: 主页面
    5. ├── src
    6. │ ├── assets: 存放静态资源
    7. │ │ └── logo.png
    8. │ │── component: 存放组件
    9. │ │ └── HelloWorld.vue
    10. │ │── App.vue: 汇总所有组件
    11. │ │── main.js: 入口文件
    12. ├── .gitignore: git版本管制忽略的配置
    13. ├── babel.config.js: babel的配置文件
    14. ├── package.json: 应用包配置文件
    15. ├── README.md: 应用描述文件
    16. ├── package-lock.json:包版本控制文件

    main.js:该文件是整个项目的入口文件

    App.vue:

    index.html:

    render函数

    传统情况下js写法:

    运行之后:(引入了一个残缺的Vue,没有模板解析器)

    实际上在引入的时候,引入的是vue.runtime.esm.js(残缺的vue)

    关于不同版本的Vue:

            1.vue.js与vue.runtime.xxx.js的区别:

                    (1).vue.js是完整版的Vue,包含:核心功能+模板解析器。

                    (2).vue.runtime.xxx.js是运行版的Vue,只包含:核心功能;没有模板解析器。

            2.因为vue.runtime.xxx.js没有模板解析器,所以不能使用template配置项,需要使用

                render函数接收到的createElement函数(这个函数可以改名)去指定具体内容。

    两种解决方法:

    1.使用render函数

    2.引入带模板解析器的Vue    

            当引入残缺版的vue,还想配置具体的内容,就得使用render函数,当然上图写法可以使用箭头函数精简。

            此时这里传入两个参数,是因为h1是html里面的内置元素,这个元素里面得写具体的内容,所以得穿第二个参数,但是如果说用的是组件,此时就不需要再写具体的内容,因为内容都在APP这个组件里面(不过在此之前需要import引入app组件)。

    多说一句,render函数只需要在main.js中引入一次即可。

    修改默认配置

    vue的默认配置文件隐藏了起来,在命令行使用 vue inspect > output.js 命令打包出来。

    注意这种方式只是给你输出出来,让你看一下,并不是修改之后脚手架就变了。

    默认配置下哪些东西不能改?

    这些东西可以改    配置参考 | Vue CLI (vuejs.org)

    在与 package.json同级目录下新建vue.config.js文件,对脚手架进行个性化定制。

    不能预留空位,因为配置会将自定义的部分整合到默认配置文件中,要么就写好,要么就不写。

    1. module.exports = {
    2. pages: {
    3. index: {
    4. // 入口
    5. entry: 'src/index/main.js'
    6. }
    7. },
    8. // 关闭语法检查
    9. lineOnSave:false
    10. }

    ref属性

    目录结构:

    获取this的vc实例对象

    顺着vc触发可以找到dom元素

    正式获取

    给School组件标签加ref,则获得School组件的vc实例对象

    main.js

    1. //引入Vue
    2. import Vue from 'vue'
    3. //引入App
    4. import App from './App.vue'
    5. //关闭Vue的生产提示
    6. Vue.config.productionTip = false
    7. //创建vm
    8. new Vue({
    9. el:'#app',
    10. render: h => h(App)
    11. })

    ./components/School.vue

    1. <template>
    2. <div class="school">
    3. <h2>学校名称:{{name}}h2>
    4. <h2>学校地址:{{address}}h2>
    5. div>
    6. template>
    7. <script>
    8. export default {
    9. name:'School',
    10. data() {
    11. return {
    12. name:'尚硅谷',
    13. address:'北京·昌平'
    14. }
    15. },
    16. }
    17. script>
    18. <style>
    19. .school{
    20. background-color: gray;
    21. }
    22. style>

    App.vue

    1. <template>
    2. <div>
    3. <h1 v-text="msg" ref="title">h1>
    4. <button ref="btn" @click="showDOM">点我输出上方的DOM元素button>
    5. <School ref="sch"/>
    6. div>
    7. template>
    8. <script>
    9. //引入School组件
    10. import School from './components/School'
    11. export default {
    12. name:'App',
    13. components:{School},
    14. data() {
    15. return {
    16. msg:'欢迎学习Vue!'
    17. }
    18. },
    19. methods: {
    20. showDOM(){
    21. console.log(this.$refs.title) //真实DOM元素
    22. console.log(this.$refs.btn) //真实DOM元素
    23. console.log(this.$refs.sch) //School组件的实例对象(vc)
    24. }
    25. },
    26. }
    27. script>

    ref属性

    1. 被用来给元素或子组件(eg:App里的School)注册引用信息(id的替代者)

    2. 应用在html标签上获取的是真实DOM元素,应用在组件标签上是组件实例对象(vc)

    3. 使用方式:

        1. 打标识:```

    .....

    ``` 或 ``````

        2. 获取:```this.$refs.xxx```

    props配置项

    目录结构:

    定义一个Student.vue,并在App.vue中三次引用。

            现在有这么一个需求,已经定义好了一个组件,老王要用和这个一模一样的组件,但是数据不一样,该如何是好?(总不能复制一份)

            在App.vue中使用Student标签中设置属性及其属性值。 

            设置值在另一头也要接收,此时就需要在Student.vue当中使用props,三种方式:

    • 简单声明接收
    props:['name','age','sex'] 
    • 接收的同时对数据进行类型限制

    1. props:{
    2. name:String,
    3. age:Number,
    4. sex:String
    5. }
    •  接收的同时对数据:进行类型限制+默认值的指定+必要性的限制
    1. props:{
    2. name:{
    3. type:String, //name的类型是字符串
    4. required:true, //name是必要的
    5. },
    6. age:{
    7. type:Number,
    8. default:99 //默认值
    9. },
    10. sex:{
    11. type:String,
    12. required:true
    13. }
    14. }

    ./components/Student.vue

    1. <template>
    2. <div>
    3. <h1>{{msg}}h1>
    4. <h2>学生姓名:{{name}}h2>
    5. <h2>学生性别:{{sex}}h2>
    6. <h2>学生年龄:{{myAge+1}}h2>
    7. <button @click="updateAge">尝试修改收到的年龄button>
    8. div>
    9. template>
    10. <script>
    11. export default {
    12. name:'Student',
    13. data() {
    14. console.log(this)
    15. return {
    16. msg:'我是一个尚硅谷的学生',
    17. myAge:this.age
    18. }
    19. },
    20. methods: {
    21. updateAge(){
    22. this.myAge++
    23. }
    24. },
    25. //简单声明接收
    26. // props:['name','age','sex']
    27. //接收的同时对数据进行类型限制
    28. /* props:{
    29. name:String,
    30. age:Number,
    31. sex:String
    32. } */
    33. //接收的同时对数据:进行类型限制+默认值的指定+必要性的限制
    34. props:{
    35. name:{
    36. type:String, //name的类型是字符串
    37. required:true, //name是必要的
    38. },
    39. age:{
    40. type:Number,
    41. default:99 //默认值
    42. },
    43. sex:{
    44. type:String,
    45. required:true
    46. }
    47. }
    48. }
    49. script>

     App.vue

    1. <template>
    2. <div>
    3. <Student name="李四" sex="女" :age="18"/>
    4. div>
    5. template>
    6. <script>
    7. import Student from './components/Student'
    8. export default {
    9. name:'App',
    10. components:{Student}
    11. }
    12. script>

    main.js

    1. //引入Vue
    2. import Vue from 'vue'
    3. //引入App
    4. import App from './App.vue'
    5. //关闭Vue的生产提示
    6. Vue.config.productionTip = false
    7. //创建vm
    8. new Vue({
    9. el:'#app',
    10. render: h => h(App)
    11. })

    props配置项

    1. 功能:让组件接收外部传过来的数据

    2. 传递数据:``````

    3. 接收数据:

        1. 第一种方式(只接收):```props:['name'] ```

        2. 第二种方式(限制类型):```props:{name:String}```

        3. 第三种方式(限制类型、限制必要性、指定默认值):

            ```js

            props:{

             name:{

             type:String, //类型

             required:true, //必要性

             default:'老王' //默认值

             }

            }

            ```

        > 备注:props是只读的,Vue底层会监测你对props的修改,如果进行了修改,就会发出警告。

            若业务需求确实需要修改,那么请复制props的内容到data中一份,然后去修改data中的数据。

    mixin混入 

    目录结构:

    提一个需求,点击按钮弹窗name值:

     可以发现红色框里内容是一样的,此时可以将他们都砍掉,使用mixin。

    新建一个mixin.js,将共用的配置(例如showName方法)提取成混入对象,并暴露出去

    在School.vue和Student.vue中引入并应用,两种方式:全局引入和局部引入

    局部引入:

    全局引入:(所有的vc和vm都会应用混合的东西)

     ./components/School.vue

    1. <template>
    2. <div>
    3. <h2 @click="showName">学校名称:{{name}}h2>
    4. <h2>学校地址:{{address}}h2>
    5. div>
    6. template>
    7. <script>
    8. //引入一个hunhe
    9. // import {hunhe,hunhe2} from '../mixin'
    10. export default {
    11. name:'School',
    12. data() {
    13. return {
    14. name:'尚硅谷',
    15. address:'北京',
    16. x:666
    17. }
    18. },
    19. // mixins:[hunhe,hunhe2],
    20. }
    21. script>

      ./components/Student.vue

    1. <template>
    2. <div>
    3. <h2 @click="showName">学生姓名:{{name}}h2>
    4. <h2>学生性别:{{sex}}h2>
    5. div>
    6. template>
    7. <script>
    8. // import {hunhe,hunhe2} from '../mixin'
    9. export default {
    10. name:'Student',
    11. data() {
    12. return {
    13. name:'张三',
    14. sex:'男'
    15. }
    16. },
    17. // mixins:[hunhe,hunhe2]
    18. }
    19. script>

     App.vue

    1. <template>
    2. <div>
    3. <School/>
    4. <hr>
    5. <Student/>
    6. div>
    7. template>
    8. <script>
    9. import School from './components/School'
    10. import Student from './components/Student'
    11. export default {
    12. name:'App',
    13. components:{School,Student}
    14. }
    15. script>

     main.js

    1. //引入Vue
    2. import Vue from 'vue'
    3. //引入App
    4. import App from './App.vue'
    5. import {hunhe,hunhe2} from './mixin'
    6. //关闭Vue的生产提示
    7. Vue.config.productionTip = false
    8. Vue.mixin(hunhe)
    9. Vue.mixin(hunhe2)
    10. //创建vm
    11. new Vue({
    12. el:'#app',
    13. render: h => h(App)
    14. })

     mixin.js

    1. export const hunhe = {
    2. methods: {
    3. showName(){
    4. alert(this.name)
    5. }
    6. },
    7. mounted() {
    8. console.log('你好啊!')
    9. },
    10. }
    11. export const hunhe2 = {
    12. data() {
    13. return {
    14. x:100,
    15. y:200
    16. }
    17. },
    18. }

    mixin(混入)

    1. 功能:可以把多个组件共用的配置提取成一个混入对象

    2. 使用方式:

        第一步定义混合:

        ```

        {

            data(){....},

            methods:{....}

            ....

        }

        ```

        第二步使用混入:

        ​ 全局混入:```Vue.mixin(xxx)```

        ​ 局部混入:```mixins:['xxx']  ```

    ps:如果***.vue中当中没有混合中的数据则自动混合其中的数据,如果有数据和混合中重复则以***.vue为准。但如果在混合里面加入生命周期钩子函数,则不以任何人为准,都表达出来,且混合在前。

    插件

    目录结构:

     新建plugins.js,编写install方法并暴露

    先应用插件再创建vm

    传入参数为Vue构造函数:

    a是vm的缔造者,vue的构造函数

    有了这个就能做很多事情了

    ./components/School.vue

    1. <template>
    2. <div>
    3. <h2>学校名称:{{name | mySlice}}h2>
    4. <h2>学校地址:{{address}}h2>
    5. <button @click="test">点我测试一个hello方法button>
    6. div>
    7. template>
    8. <script>
    9. export default {
    10. name:'School',
    11. data() {
    12. return {
    13. name:'尚硅谷atguigu',
    14. address:'北京',
    15. }
    16. },
    17. methods: {
    18. test(){
    19. this.hello()
    20. }
    21. },
    22. }
    23. script>

    ./components/Student.vue

    1. <template>
    2. <div>
    3. <h2>学生姓名:{{name}}h2>
    4. <h2>学生性别:{{sex}}h2>
    5. <input type="text" v-fbind:value="name">
    6. div>
    7. template>
    8. <script>
    9. export default {
    10. name:'Student',
    11. data() {
    12. return {
    13. name:'张三',
    14. sex:'男'
    15. }
    16. },
    17. }
    18. script>

    App.vue

    1. <template>
    2. <div>
    3. <School/>
    4. <hr>
    5. <Student/>
    6. div>
    7. template>
    8. <script>
    9. import School from './components/School'
    10. import Student from './components/Student'
    11. export default {
    12. name:'App',
    13. components:{School,Student}
    14. }
    15. script>

     plugins.js

    1. export default {
    2. install(Vue,x,y,z){
    3. console.log(x,y,z)
    4. //全局过滤器
    5. Vue.filter('mySlice',function(value){
    6. return value.slice(0,4)
    7. })
    8. //定义全局指令
    9. Vue.directive('fbind',{
    10. //指令与元素成功绑定时(一上来)
    11. bind(element,binding){
    12. element.value = binding.value
    13. },
    14. //指令所在元素被插入页面时
    15. inserted(element,binding){
    16. element.focus()
    17. },
    18. //指令所在的模板被重新解析时
    19. update(element,binding){
    20. element.value = binding.value
    21. }
    22. })
    23. //定义混入
    24. Vue.mixin({
    25. data() {
    26. return {
    27. x:100,
    28. y:200
    29. }
    30. },
    31. })
    32. //给Vue原型上添加一个方法(vm和vc就都能用了)
    33. Vue.prototype.hello = ()=>{alert('你好啊')}
    34. }
    35. }

     main.js

    1. //引入Vue
    2. import Vue from 'vue'
    3. //引入App
    4. import App from './App.vue'
    5. //引入插件
    6. import plugins from './plugins'
    7. //关闭Vue的生产提示
    8. Vue.config.productionTip = false
    9. //应用(使用)插件
    10. Vue.use(plugins,1,2,3)
    11. //创建vm
    12. new Vue({
    13. el:'#app',
    14. render: h => h(App)
    15. })

    插件

    1. 功能:用于增强Vue(游戏外挂)

    2. 本质:包含install方法的一个对象,install的第一个参数是Vue,第二个以后的参数是插件使用者传递的数据。

    3. 定义插件:

        ```js

        对象.install = function (Vue, options) {

            // 1. 添加全局过滤器

            Vue.filter(....)

       

            // 2. 添加全局指令

            Vue.directive(....)

       

            // 3. 配置全局混入(合)

            Vue.mixin(....)

       

            // 4. 添加实例方法

            Vue.prototype.$myMethod = function () {...}

            Vue.prototype.$myProperty = xxxx

        }

        ```

    4. 使用插件:```Vue.use()``` 

    scoped样式

    目录结构:

    引入一个问题

    给Student和School分别设置样式,恰巧class名相同,都为demo,但是样式颜色不一样

    结果和student一样(student背景色设置的为橙色)

    为啥?因为在App.vue当中,student是后引入的,它覆盖了前一个。

    给style标签添加scoped(作用域)属性,则表示style标签只作用于他当前的template里面。

    其实他是给当前这歌div添加了一个特殊的标签属性,且每次都是随机不一样的。

    完整代码:

     

    效果:

    scoped样式

    1. 作用:让样式在局部生效,防止冲突。

    2. 写法:```