vuejs / vue

This is the repo for Vue 2. For Vue 3, go to https://github.com/vuejs/core
http://v2.vuejs.org
MIT License
208k stars 33.69k forks source link

Hot relaod does not work in functional component ,How to fix it? #11849

Open jackchoumine opened 3 years ago

jackchoumine commented 3 years ago

Version

2.6.11

Reproduction link

https://codesandbox.io/s/brave-field-m1quc?file=/src/App.vue

Steps to reproduce

A functional component in script with render. Hello.vue

<script>
 export default {
   name:'Hello',
   functional:true,
   render(){
     return <h1>
              Does hot reload with functional:true  in script and render?Noo
              </h1>
   }
 }
</script>

The component does not hot reload when I change something in render.

But this does hot reload: Hi.js

export default {
    name: 'Hi',
    functional: true,
    render(h, { props }) {
        const children = [h('h'   props.level, '这是标题'   props.level)]
        return h('div', children)
    },
}

How to fix it?

What is expected?

I want all components can hot reload.

What is actually happening?

I have to reload page by hand when Hello.vue componet changed.


you can get this repo: https://github.com/jackchoumine/vue-demo

you change Hello.vue . It does not hot reload.

sirlancelot commented 3 years ago

Vue's hot-reload API only gets applied to .vue files. Use the first syntax in your example. All Vue components (functional or otherwise) should be in .vue files for maximum compatibility with developer utilities like hot-reload.

You could even use a functional template if you want:

<template functional>
  <div>
    <component :is="`h${props.level}`">Header {{ props.level }}</component>
  </div>
</template>

<script>
export default {
  functional: true,
  props: {
    level: { type: Number, default: 1 }
  }
}
</script>
MJGTwo commented 2 years ago

Hi @sirlancelot I'm having a similar issue inside of my app that uses vue@2.6.12 and bootstrap-vue@2.21.2. the code's purpose is to change the behavior of the <b-table> component from not allowing selections to allowing them depending upon a mode's state being changed elsewhere on that page.

const conditionalTable = {
  functional: true,
  props: {
    selectMode: {type: String, required: true}
  },
  render(createElement, {children, data, props}){
    const {attrs} = data;
    if (props.selectMode === 'Selected'){
      console.log("selectMode", selectMode);
      return createElement("b-table", data, children);
    }
    else {
      console.log("selectMode", selectMode);
      return createElement("b-table",
        {
          ...data,
          attrs: {
            ...attrs,
            'no-select-on-click':"" // <--- prevents rows from being selected
          }
        },
        children
      );
    }
  }
}

With the component being called with

  <conditional-table
        striped
        hover
        selectable
        :select-mode="currentWriteOp"
        @row-selected="onRowSelected"
        selected-variant="warning"
        hover-variant="primary"
        responsibve="sm"
        :items="diff"
        :fields="computedFields()">
        <--! <logic for data being rendered/> -->
   </conditional-table>

I change the variable currentWriteOp (which lives inside the data function of this page) to the value Selected, the condition-table function is called and i see the classes change to remove no-select-on-click via the dev tools on Firefox 96.0, yet when I click on them I cannot see a change in their coloring (a la selected-variant="warning") meaning they are not being selected.